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 static android.Manifest.permission.MODIFY_PHONE_STATE; 20 21 import android.Manifest; 22 import android.annotation.CallbackExecutor; 23 import android.annotation.ElapsedRealtimeLong; 24 import android.annotation.FlaggedApi; 25 import android.annotation.IntDef; 26 import android.annotation.IntRange; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SystemApi; 31 import android.app.Notification; 32 import android.bluetooth.BluetoothDevice; 33 import android.compat.annotation.UnsupportedAppUsage; 34 import android.content.ComponentName; 35 import android.content.Intent; 36 import android.hardware.camera2.CameraManager; 37 import android.location.Location; 38 import android.net.Uri; 39 import android.os.Binder; 40 import android.os.Bundle; 41 import android.os.Handler; 42 import android.os.IBinder; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.OutcomeReceiver; 46 import android.os.Parcel; 47 import android.os.ParcelFileDescriptor; 48 import android.os.Parcelable; 49 import android.os.RemoteException; 50 import android.os.SystemClock; 51 import android.telephony.CallQuality; 52 import android.telephony.CellIdentity; 53 import android.telephony.ims.ImsStreamMediaProfile; 54 import android.util.ArraySet; 55 import android.view.Surface; 56 57 import com.android.internal.os.SomeArgs; 58 import com.android.internal.telecom.IVideoCallback; 59 import com.android.internal.telecom.IVideoProvider; 60 import com.android.server.telecom.flags.Flags; 61 62 import java.io.FileInputStream; 63 import java.io.FileOutputStream; 64 import java.io.IOException; 65 import java.io.InputStreamReader; 66 import java.io.OutputStreamWriter; 67 import java.lang.annotation.Retention; 68 import java.lang.annotation.RetentionPolicy; 69 import java.nio.channels.Channels; 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.Collections; 73 import java.util.List; 74 import java.util.Objects; 75 import java.util.Set; 76 import java.util.concurrent.ConcurrentHashMap; 77 import java.util.concurrent.Executor; 78 79 /** 80 * Represents a phone call or connection to a remote endpoint that carries voice and/or video 81 * traffic. 82 * <p> 83 * Implementations create a custom subclass of {@code Connection} and return it to the framework 84 * as the return value of 85 * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)} 86 * or 87 * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. 88 * Implementations are then responsible for updating the state of the {@code Connection}, and 89 * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no 90 * longer used and associated resources may be recovered. 91 * <p> 92 * Subclasses of {@code Connection} override the {@code on*} methods to provide the 93 * {@link ConnectionService}'s implementation of calling functionality. The {@code on*} methods are 94 * called by Telecom to inform an instance of a {@code Connection} of actions specific to that 95 * {@code Connection} instance. 96 * <p> 97 * Basic call support requires overriding the following methods: {@link #onAnswer()}, 98 * {@link #onDisconnect()}, {@link #onReject()}, {@link #onAbort()} 99 * <p> 100 * Where a {@code Connection} has {@link #CAPABILITY_SUPPORT_HOLD}, the {@link #onHold()} and 101 * {@link #onUnhold()} methods should be overridden to provide hold support for the 102 * {@code Connection}. 103 * <p> 104 * Where a {@code Connection} supports a variation of video calling (e.g. the 105 * {@code CAPABILITY_SUPPORTS_VT_*} capability bits), {@link #onAnswer(int)} should be overridden 106 * to support answering a call as a video call. 107 * <p> 108 * Where a {@code Connection} has {@link #PROPERTY_IS_EXTERNAL_CALL} and 109 * {@link #CAPABILITY_CAN_PULL_CALL}, {@link #onPullExternalCall()} should be overridden to provide 110 * support for pulling the external call. 111 * <p> 112 * Where a {@code Connection} supports conference calling {@link #onSeparate()} should be 113 * overridden. 114 * <p> 115 * There are a number of other {@code on*} methods which a {@code Connection} can choose to 116 * implement, depending on whether it is concerned with the associated calls from Telecom. If, 117 * for example, call events from a {@link InCallService} are handled, 118 * {@link #onCallEvent(String, Bundle)} should be overridden. Another example is 119 * {@link #onExtrasChanged(Bundle)}, which should be overridden if the {@code Connection} wishes to 120 * make use of extra information provided via the {@link Call#putExtras(Bundle)} and 121 * {@link Call#removeExtras(String...)} methods. 122 */ 123 public abstract class Connection extends Conferenceable { 124 125 /**@hide*/ 126 @Retention(RetentionPolicy.SOURCE) 127 @IntDef(prefix = "STATE_", value = { 128 STATE_INITIALIZING, 129 STATE_NEW, 130 STATE_RINGING, 131 STATE_DIALING, 132 STATE_ACTIVE, 133 STATE_HOLDING, 134 STATE_DISCONNECTED, 135 STATE_PULLING_CALL 136 }) 137 public @interface ConnectionState {} 138 139 /** 140 * The connection is initializing. This is generally the first state for a {@code Connection} 141 * returned by a {@link ConnectionService}. 142 */ 143 public static final int STATE_INITIALIZING = 0; 144 145 /** 146 * The connection is new and not connected. 147 */ 148 public static final int STATE_NEW = 1; 149 150 /** 151 * An incoming connection is in the ringing state. During this state, the user's ringer or 152 * vibration feature will be activated. 153 */ 154 public static final int STATE_RINGING = 2; 155 156 /** 157 * An outgoing connection is in the dialing state. In this state the other party has not yet 158 * answered the call and the user traditionally hears a ringback tone. 159 */ 160 public static final int STATE_DIALING = 3; 161 162 /** 163 * A connection is active. Both parties are connected to the call and can actively communicate. 164 */ 165 public static final int STATE_ACTIVE = 4; 166 167 /** 168 * A connection is on hold. 169 */ 170 public static final int STATE_HOLDING = 5; 171 172 /** 173 * A connection has been disconnected. This is the final state once the user has been 174 * disconnected from a call either locally, remotely or by an error in the service. 175 */ 176 public static final int STATE_DISCONNECTED = 6; 177 178 /** 179 * The state of an external connection which is in the process of being pulled from a remote 180 * device to the local device. 181 * <p> 182 * A connection can only be in this state if the {@link #PROPERTY_IS_EXTERNAL_CALL} property and 183 * {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection. 184 */ 185 public static final int STATE_PULLING_CALL = 7; 186 187 /** 188 * Indicates that the network could not perform verification. 189 */ 190 public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; 191 192 /** 193 * Indicates that verification by the network passed. This indicates there is a high likelihood 194 * that the call originated from a valid source. 195 */ 196 public static final int VERIFICATION_STATUS_PASSED = 1; 197 198 /** 199 * Indicates that verification by the network failed. This indicates there is a high likelihood 200 * that the call did not originate from a valid source. 201 */ 202 public static final int VERIFICATION_STATUS_FAILED = 2; 203 204 /**@hide*/ 205 @Retention(RetentionPolicy.SOURCE) 206 @IntDef(prefix = "VERIFICATION_STATUS_", value = { 207 VERIFICATION_STATUS_NOT_VERIFIED, 208 VERIFICATION_STATUS_PASSED, 209 VERIFICATION_STATUS_FAILED 210 }) 211 public @interface VerificationStatus {} 212 213 /** 214 * Connection can currently be put on hold or unheld. This is distinct from 215 * {@link #CAPABILITY_SUPPORT_HOLD} in that although a connection may support 'hold' most times, 216 * it does not at the moment support the function. This can be true while the call is in the 217 * state {@link #STATE_DIALING}, for example. During this condition, an in-call UI may 218 * display a disabled 'hold' button. 219 */ 220 public static final int CAPABILITY_HOLD = 0x00000001; 221 222 /** Connection supports the hold feature. */ 223 public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002; 224 225 /** 226 * Connections within a conference can be merged. A {@link ConnectionService} has the option to 227 * add a {@link Conference} before the child {@link Connection}s are merged. This is how 228 * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this 229 * capability allows a merge button to be shown while the conference is in the foreground 230 * of the in-call UI. 231 * <p> 232 * This is only intended for use by a {@link Conference}. 233 */ 234 public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004; 235 236 /** 237 * Connections within a conference can be swapped between foreground and background. 238 * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information. 239 * <p> 240 * This is only intended for use by a {@link Conference}. 241 */ 242 public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008; 243 244 /** 245 * @hide 246 */ 247 public static final int CAPABILITY_UNUSED = 0x00000010; 248 249 /** Connection supports responding via text option. */ 250 public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020; 251 252 /** Connection can be muted. */ 253 public static final int CAPABILITY_MUTE = 0x00000040; 254 255 /** 256 * Connection supports conference management. This capability only applies to 257 * {@link Conference}s which can have {@link Connection}s as children. 258 */ 259 public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; 260 261 /** 262 * Local device supports receiving video. 263 */ 264 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100; 265 266 /** 267 * Local device supports transmitting video. 268 */ 269 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200; 270 271 /** 272 * Local device supports bidirectional video calling. 273 */ 274 public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL = 275 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX; 276 277 /** 278 * Remote device supports receiving video. 279 */ 280 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400; 281 282 /** 283 * Remote device supports transmitting video. 284 */ 285 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800; 286 287 /** 288 * Remote device supports bidirectional video calling. 289 */ 290 public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL = 291 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX; 292 293 /** 294 * Connection is able to be separated from its parent {@code Conference}, if any. 295 */ 296 public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000; 297 298 /** 299 * Connection is able to be individually disconnected when in a {@code Conference}. 300 */ 301 public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000; 302 303 /** 304 * Un-used. 305 * @hide 306 */ 307 public static final int CAPABILITY_UNUSED_2 = 0x00004000; 308 309 /** 310 * Un-used. 311 * @hide 312 */ 313 public static final int CAPABILITY_UNUSED_3 = 0x00008000; 314 315 /** 316 * Un-used. 317 * @hide 318 */ 319 public static final int CAPABILITY_UNUSED_4 = 0x00010000; 320 321 /** 322 * Un-used. 323 * @hide 324 */ 325 public static final int CAPABILITY_UNUSED_5 = 0x00020000; 326 327 /** 328 * Speed up audio setup for MT call. 329 * <p> 330 * Used for IMS calls to indicate that mobile-terminated (incoming) call audio setup should take 331 * place as soon as the device answers the call, but prior to it being connected. This is an 332 * optimization some IMS stacks depend on to ensure prompt setup of call audio. 333 * @hide 334 */ 335 @SystemApi 336 public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000; 337 338 /** 339 * Call can be upgraded to a video call. 340 * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and 341 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call whether or not 342 * video calling is supported. 343 */ 344 public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000; 345 346 /** 347 * For video calls, indicates whether the outgoing video for the call can be paused using 348 * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState. 349 */ 350 public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000; 351 352 /** 353 * For a conference, indicates the conference will not have child connections. 354 * <p> 355 * An example of a conference with child connections is a GSM conference call, where the radio 356 * retains connections to the individual participants of the conference. Another example is an 357 * IMS conference call where conference event package functionality is supported; in this case 358 * the conference server ensures the radio is aware of the participants in the conference, which 359 * are represented by child connections. 360 * <p> 361 * An example of a conference with no child connections is an IMS conference call with no 362 * conference event package support. Such a conference is represented by the radio as a single 363 * connection to the IMS conference server. 364 * <p> 365 * Indicating whether a conference has children or not is important to help user interfaces 366 * visually represent a conference. A conference with no children, for example, will have the 367 * conference connection shown in the list of calls on a Bluetooth device, where if the 368 * conference has children, only the children will be shown in the list of calls on a Bluetooth 369 * device. 370 * @hide 371 */ 372 @SystemApi 373 public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 0x00200000; 374 375 /** 376 * Indicates that the connection itself wants to handle any sort of reply response, rather than 377 * relying on SMS. 378 */ 379 public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000; 380 381 /** 382 * When set, prevents a video call from being downgraded to an audio-only call. 383 * <p> 384 * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or 385 * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be 386 * downgraded from a video call back to a VideoState of 387 * {@link VideoProfile#STATE_AUDIO_ONLY}. 388 * <p> 389 * Intuitively, a call which can be downgraded to audio should also have local and remote 390 * video 391 * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and 392 * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}). 393 */ 394 public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00800000; 395 396 /** 397 * When set for an external connection, indicates that this {@code Connection} can be pulled 398 * from a remote device to the current device. 399 * <p> 400 * Should only be set on a {@code Connection} where {@link #PROPERTY_IS_EXTERNAL_CALL} 401 * is set. 402 */ 403 public static final int CAPABILITY_CAN_PULL_CALL = 0x01000000; 404 405 /** Call supports the deflect feature. */ 406 public static final int CAPABILITY_SUPPORT_DEFLECT = 0x02000000; 407 408 /** 409 * When set, indicates that this {@link Connection} supports initiation of a conference call 410 * by directly adding participants using {@link #onAddConferenceParticipants(List)}. When 411 * participants are added to a {@link Connection}, it will be replaced by a {@link Conference} 412 * instance with {@link #PROPERTY_IS_ADHOC_CONFERENCE} set to indicate that it is an adhoc 413 * conference call. 414 */ 415 public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000; 416 417 /** 418 * Indicates that this {@code Connection} can be transferred to another 419 * number. 420 * Connection supports the confirmed and unconfirmed call transfer feature. 421 * @hide 422 */ 423 public static final int CAPABILITY_TRANSFER = 0x08000000; 424 425 /** 426 * Indicates that this {@code Connection} can be transferred to another 427 * ongoing {@code Connection}. 428 * Connection supports the consultative call transfer feature. 429 * @hide 430 */ 431 public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x10000000; 432 433 /** 434 * Indicates whether the remote party supports RTT or not to the UI. 435 */ 436 437 public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x20000000; 438 439 //********************************************************************************************** 440 // Next CAPABILITY value: 0x40000000 441 //********************************************************************************************** 442 443 /** 444 * Indicates that the current device callback number should be shown. 445 * <p> 446 * Supports Telephony calls where CDMA emergency callback mode is active. 447 * @hide 448 */ 449 @SystemApi 450 public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 1<<0; 451 452 /** 453 * Whether the call is a generic conference, where we do not know the precise state of 454 * participants in the conference (eg. on CDMA). 455 * <p> 456 * Supports legacy telephony CDMA calls. 457 * @hide 458 */ 459 @SystemApi 460 public static final int PROPERTY_GENERIC_CONFERENCE = 1<<1; 461 462 /** 463 * Connection is using high definition audio. 464 * <p> 465 * Indicates that the {@link Connection} is using a "high definition" audio codec. This usually 466 * implies something like AMR wideband, but the interpretation of when a call is considered high 467 * definition is left to the {@link ConnectionService} to decide. 468 * <p> 469 * Translates to {@link android.telecom.Call.Details#PROPERTY_HIGH_DEF_AUDIO}. 470 */ 471 public static final int PROPERTY_HIGH_DEF_AUDIO = 1<<2; 472 473 /** 474 * Connection is using WIFI. 475 * <p> 476 * Used to indicate that a call is taking place over WIFI versus a carrier network. 477 * <p> 478 * Translates to {@link android.telecom.Call.Details#PROPERTY_WIFI}. 479 */ 480 public static final int PROPERTY_WIFI = 1<<3; 481 482 /** 483 * When set, indicates that the {@code Connection} does not actually exist locally for the 484 * {@link ConnectionService}. 485 * <p> 486 * Consider, for example, a scenario where a user has two devices with the same phone number. 487 * When a user places a call on one devices, the telephony stack can represent that call on the 488 * other device by adding is to the {@link ConnectionService} with the 489 * {@link #PROPERTY_IS_EXTERNAL_CALL} capability set. 490 * <p> 491 * An {@link ConnectionService} should not assume that all {@link InCallService}s will handle 492 * external connections. Only those {@link InCallService}s which have the 493 * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its 494 * manifest will see external connections. 495 */ 496 public static final int PROPERTY_IS_EXTERNAL_CALL = 1<<4; 497 498 /** 499 * Indicates that the connection has CDMA Enhanced Voice Privacy enabled. 500 */ 501 public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 1<<5; 502 503 /** 504 * Indicates that the connection represents a downgraded IMS conference. 505 * <p> 506 * This property is set when an IMS conference undergoes SRVCC and is re-added to Telecom as a 507 * new entity to indicate that the new connection was a conference. 508 * @hide 509 */ 510 @SystemApi 511 public static final int PROPERTY_IS_DOWNGRADED_CONFERENCE = 1<<6; 512 513 /** 514 * Set by the framework to indicate that the {@link Connection} originated from a self-managed 515 * {@link ConnectionService}. 516 * <p> 517 * See {@link PhoneAccount#CAPABILITY_SELF_MANAGED}. 518 */ 519 public static final int PROPERTY_SELF_MANAGED = 1<<7; 520 521 /** 522 * Set by the framework to indicate that a connection has an active RTT session associated with 523 * it. 524 */ 525 public static final int PROPERTY_IS_RTT = 1 << 8; 526 527 /** 528 * Set by the framework to indicate that a connection is using assisted dialing. 529 * <p> 530 * This is used for outgoing calls. 531 * 532 * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING 533 */ 534 public static final int PROPERTY_ASSISTED_DIALING = 1 << 9; 535 536 /** 537 * Set by the framework to indicate that the network has identified a Connection as an emergency 538 * call. 539 * <p> 540 * This is used for incoming (mobile-terminated) calls to indicate the call is from emergency 541 * services. 542 */ 543 public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10; 544 545 /** 546 * Set by the framework to indicate that a Conference or Connection is hosted by a device other 547 * than the current one. Used in scenarios where the conference originator is the remote device 548 * and the current device is a participant of that conference. 549 * <p> 550 * This property is specific to IMS conference calls originating in Telephony. 551 * @hide 552 */ 553 @SystemApi 554 public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11; 555 556 /** 557 * Set by the framework to indicate that a call is an adhoc conference call. 558 * <p> 559 * This is used for outgoing and incoming conference calls. 560 */ 561 public static final int PROPERTY_IS_ADHOC_CONFERENCE = 1 << 12; 562 563 /** 564 * Connection is using cross sim technology. 565 * <p> 566 * Indicates that the {@link Connection} is using a cross sim technology which would 567 * register IMS over internet APN of default data subscription. 568 * <p> 569 */ 570 public static final int PROPERTY_CROSS_SIM = 1 << 13; 571 572 //********************************************************************************************** 573 // Next PROPERTY value: 1<<14 574 //********************************************************************************************** 575 576 /** 577 * Indicates that the audio codec is currently not specified or is unknown. 578 */ 579 public static final int AUDIO_CODEC_NONE = ImsStreamMediaProfile.AUDIO_QUALITY_NONE; // 0 580 /** 581 * Adaptive Multi-rate audio codec. 582 */ 583 public static final int AUDIO_CODEC_AMR = ImsStreamMediaProfile.AUDIO_QUALITY_AMR; // 1 584 /** 585 * Adaptive Multi-rate wideband audio codec. 586 */ 587 public static final int AUDIO_CODEC_AMR_WB = ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB; // 2 588 /** 589 * Qualcomm code-excited linear prediction 13 kilobit audio codec. 590 */ 591 public static final int AUDIO_CODEC_QCELP13K = ImsStreamMediaProfile.AUDIO_QUALITY_QCELP13K; //3 592 /** 593 * Enhanced Variable Rate Codec. See 3GPP2 C.S0014-A. 594 */ 595 public static final int AUDIO_CODEC_EVRC = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC; // 4 596 /** 597 * Enhanced Variable Rate Codec B. Commonly used on CDMA networks. 598 */ 599 public static final int AUDIO_CODEC_EVRC_B = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_B; // 5 600 /** 601 * Enhanced Variable Rate Wideband Codec. See RFC5188. 602 */ 603 public static final int AUDIO_CODEC_EVRC_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB; // 6 604 /** 605 * Enhanced Variable Rate Narrowband-Wideband Codec. 606 */ 607 public static final int AUDIO_CODEC_EVRC_NW = ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_NW; // 7 608 /** 609 * GSM Enhanced Full-Rate audio codec, also known as GSM-EFR, GSM 06.60, or simply EFR. 610 */ 611 public static final int AUDIO_CODEC_GSM_EFR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_EFR; // 8 612 /** 613 * GSM Full-Rate audio codec, also known as GSM-FR, GSM 06.10, GSM, or simply FR. 614 */ 615 public static final int AUDIO_CODEC_GSM_FR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_FR; // 9 616 /** 617 * GSM Half Rate audio codec. 618 */ 619 public static final int AUDIO_CODEC_GSM_HR = ImsStreamMediaProfile.AUDIO_QUALITY_GSM_HR; // 10 620 /** 621 * ITU-T G711U audio codec. 622 */ 623 public static final int AUDIO_CODEC_G711U = ImsStreamMediaProfile.AUDIO_QUALITY_G711U; // 11 624 /** 625 * ITU-T G723 audio codec. 626 */ 627 public static final int AUDIO_CODEC_G723 = ImsStreamMediaProfile.AUDIO_QUALITY_G723; // 12 628 /** 629 * ITU-T G711A audio codec. 630 */ 631 public static final int AUDIO_CODEC_G711A = ImsStreamMediaProfile.AUDIO_QUALITY_G711A; // 13 632 /** 633 * ITU-T G722 audio codec. 634 */ 635 public static final int AUDIO_CODEC_G722 = ImsStreamMediaProfile.AUDIO_QUALITY_G722; // 14 636 /** 637 * ITU-T G711AB audio codec. 638 */ 639 public static final int AUDIO_CODEC_G711AB = ImsStreamMediaProfile.AUDIO_QUALITY_G711AB; // 15 640 /** 641 * ITU-T G729 audio codec. 642 */ 643 public static final int AUDIO_CODEC_G729 = ImsStreamMediaProfile.AUDIO_QUALITY_G729; // 16 644 /** 645 * Enhanced Voice Services Narrowband audio codec. See 3GPP TS 26.441. 646 */ 647 public static final int AUDIO_CODEC_EVS_NB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_NB; // 17 648 /** 649 * Enhanced Voice Services Wideband audio codec. See 3GPP TS 26.441. 650 */ 651 public static final int AUDIO_CODEC_EVS_WB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB; // 18 652 /** 653 * Enhanced Voice Services Super-Wideband audio codec. See 3GPP TS 26.441. 654 */ 655 public static final int AUDIO_CODEC_EVS_SWB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB; // 19 656 /** 657 * Enhanced Voice Services Fullband audio codec. See 3GPP TS 26.441. 658 */ 659 public static final int AUDIO_CODEC_EVS_FB = ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB; // 20 660 661 /**@hide*/ 662 @Retention(RetentionPolicy.SOURCE) 663 @IntDef(prefix = "AUDIO_CODEC_", value = { 664 AUDIO_CODEC_NONE, 665 AUDIO_CODEC_AMR, 666 AUDIO_CODEC_AMR_WB, 667 AUDIO_CODEC_QCELP13K, 668 AUDIO_CODEC_EVRC, 669 AUDIO_CODEC_EVRC_B, 670 AUDIO_CODEC_EVRC_WB, 671 AUDIO_CODEC_EVRC_NW, 672 AUDIO_CODEC_GSM_EFR, 673 AUDIO_CODEC_GSM_FR, 674 AUDIO_CODEC_GSM_HR, 675 AUDIO_CODEC_G711U, 676 AUDIO_CODEC_G723, 677 AUDIO_CODEC_G711A, 678 AUDIO_CODEC_G722, 679 AUDIO_CODEC_G711AB, 680 AUDIO_CODEC_G729, 681 AUDIO_CODEC_EVS_NB, 682 AUDIO_CODEC_EVS_SWB, 683 AUDIO_CODEC_EVS_FB 684 }) 685 public @interface AudioCodec {} 686 687 /** 688 * Contains the same value as {@link #getCallerNumberVerificationStatus()}, except will be 689 * present in the {@link #getExtras()} using this key. 690 * @hide 691 */ 692 public static final String EXTRA_CALLER_NUMBER_VERIFICATION_STATUS = 693 "android.telecom.extra.CALLER_NUMBER_VERIFICATION_STATUS"; 694 695 /** 696 * Connection extra key used to store the last forwarded number associated with the current 697 * connection. Used to communicate to the user interface that the connection was forwarded via 698 * the specified number. 699 */ 700 public static final String EXTRA_LAST_FORWARDED_NUMBER = 701 "android.telecom.extra.LAST_FORWARDED_NUMBER"; 702 703 /** 704 * Connection extra key used to store a child number associated with the current connection. 705 * Used to communicate to the user interface that the connection was received via 706 * a child address (i.e. phone number) associated with the {@link PhoneAccount}'s primary 707 * address. 708 */ 709 public static final String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; 710 711 /** 712 * Connection extra key used to store the subject for an incoming call. The user interface can 713 * query this extra and display its contents for incoming calls. Will only be used if the 714 * {@link PhoneAccount} supports the capability {@link PhoneAccount#CAPABILITY_CALL_SUBJECT}. 715 */ 716 public static final String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; 717 718 /** 719 * Boolean connection extra key set on a {@link Connection} in 720 * {@link Connection#STATE_RINGING} state to indicate that answering the call will cause the 721 * current active foreground call to be dropped. 722 */ 723 public static final String EXTRA_ANSWERING_DROPS_FG_CALL = 724 "android.telecom.extra.ANSWERING_DROPS_FG_CALL"; 725 726 /** 727 * String connection extra key set on a {@link Connection} in {@link Connection#STATE_RINGING} 728 * state to indicate the name of the third-party app which is responsible for the current 729 * foreground call. 730 * <p> 731 * Used when {@link #EXTRA_ANSWERING_DROPS_FG_CALL} is true to ensure that the default Phone app 732 * is able to inform the user that answering the new incoming call will cause a call owned by 733 * another app to be dropped when the incoming call is answered. 734 */ 735 public static final String EXTRA_ANSWERING_DROPS_FG_CALL_APP_NAME = 736 "android.telecom.extra.ANSWERING_DROPS_FG_CALL_APP_NAME"; 737 738 /** 739 * Boolean connection extra key on a {@link Connection} which indicates that adding an 740 * additional call is disallowed. 741 * <p> 742 * Used for mobile-network calls to identify scenarios where carrier requirements preclude 743 * adding another call at the current time. 744 * @hide 745 */ 746 @SystemApi 747 public static final String EXTRA_DISABLE_ADD_CALL = 748 "android.telecom.extra.DISABLE_ADD_CALL"; 749 750 /** 751 * String connection extra key on a {@link Connection} or {@link Conference} which contains the 752 * original Connection ID associated with the connection. Used in 753 * {@link RemoteConnectionService} to track the Connection ID which was originally assigned to a 754 * connection/conference added via 755 * {@link ConnectionService#addExistingConnection(PhoneAccountHandle, Connection)} and 756 * {@link ConnectionService#addConference(Conference)} APIs. This is important to pass to 757 * Telecom for when it deals with RemoteConnections. When the ConnectionManager wraps the 758 * {@link RemoteConnection} and {@link RemoteConference} and adds it to Telecom, there needs to 759 * be a way to ensure that we don't add the connection again as a duplicate. 760 * <p> 761 * For example, the TelephonyCS calls addExistingConnection for a Connection with ID 762 * {@code TelephonyCS@1}. The ConnectionManager learns of this via 763 * {@link ConnectionService#onRemoteExistingConnectionAdded(RemoteConnection)}, and wraps this 764 * in a new {@link Connection} which it adds to Telecom via 765 * {@link ConnectionService#addExistingConnection(PhoneAccountHandle, Connection)}. As part of 766 * this process, the wrapped RemoteConnection gets assigned a new ID (e.g. {@code ConnMan@1}). 767 * The TelephonyCS will ALSO try to add the existing connection to Telecom, except with the 768 * ID it originally referred to the connection as. Thus Telecom needs to know that the 769 * Connection with ID {@code ConnMan@1} is really the same as {@code TelephonyCS@1}. 770 * <p> 771 * This is an internal Telecom framework concept and is not exposed outside of the Telecom 772 * framework. 773 * @hide 774 */ 775 public static final String EXTRA_ORIGINAL_CONNECTION_ID = 776 "android.telecom.extra.ORIGINAL_CONNECTION_ID"; 777 778 /** 779 * Extra key set on a {@link Connection} when it was created via a remote connection service. 780 * For example, if a connection manager requests a remote connection service to create a call 781 * using one of the remote connection service's phone account handle, this extra will be set so 782 * that Telecom knows that the wrapped remote connection originated in a remote connection 783 * service. We stash this in the extras since connection managers will typically copy the 784 * extras from a {@link RemoteConnection} to a {@link Connection} (there is ultimately not 785 * other way to relate a {@link RemoteConnection} to a {@link Connection}. 786 * @hide 787 */ 788 public static final String EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE = 789 "android.telecom.extra.REMOTE_PHONE_ACCOUNT_HANDLE"; 790 791 /** 792 * The Telecom call ID of the conference an existing connection should be added to. This is 793 * required when {@link com.android.services.telephony.TelephonyConnectionService} adds a 794 * {@link Conference} to Telecom using the 795 * {@link ConnectionService#addExistingConnection(PhoneAccountHandle, Connection, Conference)} 796 * API. That API specifies a parent conference associated with the new existing connection 797 * being added, and there is no equivalent as part of the {@link RemoteConnectionService} API. 798 * This extra key is used to stack the ID of the conference to which the existing connection 799 * will be added so that Telecom can link it up correctly when the {@link RemoteConference} 800 * is added to Telecom by the connection manager. 801 * @hide 802 */ 803 public static final String EXTRA_ADD_TO_CONFERENCE_ID = 804 "android.telecom.extra.ADD_TO_CONFERENCE_ID"; 805 806 /** 807 * Extra key set from a {@link ConnectionService} when using the remote connection APIs 808 * (e.g. {@link RemoteConnectionService#createRemoteConnection(PhoneAccountHandle, 809 * ConnectionRequest, boolean)}) to create a remote connection. Provides the receiving 810 * {@link ConnectionService} with a means to know the package name of the requesting 811 * {@link ConnectionService} so that {@link #EXTRA_REMOTE_PHONE_ACCOUNT_HANDLE} can be set for 812 * better visibility in Telecom of where a connection ultimately originated. 813 * @hide 814 */ 815 public static final String EXTRA_REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME = 816 "android.telecom.extra.REMOTE_CONNECTION_ORIGINATING_PACKAGE_NAME"; 817 818 /** 819 * Boolean connection extra key set on the extras passed to 820 * {@link Connection#sendConnectionEvent} which indicates that audio is present 821 * on the RTT call when the extra value is true. 822 */ 823 public static final String EXTRA_IS_RTT_AUDIO_PRESENT = 824 "android.telecom.extra.IS_RTT_AUDIO_PRESENT"; 825 826 /** 827 * The audio codec in use for the current {@link Connection}, if known. Examples of valid 828 * values include {@link #AUDIO_CODEC_AMR_WB} and {@link #AUDIO_CODEC_EVS_WB}. 829 */ 830 public static final @AudioCodec String EXTRA_AUDIO_CODEC = 831 "android.telecom.extra.AUDIO_CODEC"; 832 833 /** 834 * Float connection extra key used to store the audio codec bitrate in kbps for the current 835 * {@link Connection}. 836 */ 837 public static final String EXTRA_AUDIO_CODEC_BITRATE_KBPS = 838 "android.telecom.extra.AUDIO_CODEC_BITRATE_KBPS"; 839 840 /** 841 * Float connection extra key used to store the audio codec bandwidth in khz for the current 842 * {@link Connection}. 843 */ 844 public static final String EXTRA_AUDIO_CODEC_BANDWIDTH_KHZ = 845 "android.telecom.extra.AUDIO_CODEC_BANDWIDTH_KHZ"; 846 847 /** 848 * Last known cell identity key {@link CellIdentity} to be used to fill geo location header 849 * in case of an emergency call. This entry will not be filled if call is not identified as 850 * an emergency call. Only provided to the {@link ConnectionService} for the purpose of 851 * placing an emergency call; will not be present in the {@link InCallService} layer. 852 * The {@link ConnectionService}'s implementation will be logged for fine location access 853 * when an outgoing call is placed in this case. 854 */ 855 public static final String EXTRA_LAST_KNOWN_CELL_IDENTITY = 856 "android.telecom.extra.LAST_KNOWN_CELL_IDENTITY"; 857 858 /** 859 * Boolean connection extra key used to indicate whether device to device communication is 860 * available for the current call. 861 * @hide 862 */ 863 public static final String EXTRA_IS_DEVICE_TO_DEVICE_COMMUNICATION_AVAILABLE = 864 "android.telecom.extra.IS_DEVICE_TO_DEVICE_COMMUNICATION_AVAILABLE"; 865 866 /** 867 * Connection event used to inform Telecom that it should play the on hold tone. This is used 868 * to play a tone when the peer puts the current call on hold. Sent to Telecom via 869 * {@link #sendConnectionEvent(String, Bundle)}. 870 */ 871 public static final String EVENT_ON_HOLD_TONE_START = 872 "android.telecom.event.ON_HOLD_TONE_START"; 873 874 /** 875 * Connection event used to inform Telecom that it should stop the on hold tone. This is used 876 * to stop a tone when the peer puts the current call on hold. Sent to Telecom via 877 * {@link #sendConnectionEvent(String, Bundle)}. 878 */ 879 public static final String EVENT_ON_HOLD_TONE_END = 880 "android.telecom.event.ON_HOLD_TONE_END"; 881 882 /** 883 * Connection event used to inform {@link InCallService}s when pulling of an external call has 884 * failed. The user interface should inform the user of the error. 885 * <p> 886 * Expected to be used by the {@link ConnectionService} when the {@link Call#pullExternalCall()} 887 * API is called on a {@link Call} with the properties 888 * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and 889 * {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not 890 * pull the external call due to an error condition. 891 * <p> 892 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 893 * expected to be null when this connection event is used. 894 */ 895 public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; 896 897 /** 898 * Connection event used to inform {@link InCallService}s when the merging of two calls has 899 * failed. The User Interface should use this message to inform the user of the error. 900 * <p> 901 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 902 * expected to be null when this connection event is used. 903 */ 904 public static final String EVENT_CALL_MERGE_FAILED = "android.telecom.event.CALL_MERGE_FAILED"; 905 906 /** 907 * Connection event used to inform Telecom when a hold operation on a call has failed. 908 * <p> 909 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 910 * expected to be null when this connection event is used. 911 */ 912 public static final String EVENT_CALL_HOLD_FAILED = "android.telecom.event.CALL_HOLD_FAILED"; 913 914 /** 915 * Connection event used to inform Telecom when a switch operation on a call has failed. 916 * <p> 917 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 918 * expected to be null when this connection event is used. 919 */ 920 public static final String EVENT_CALL_SWITCH_FAILED = 921 "android.telecom.event.CALL_SWITCH_FAILED"; 922 923 /** 924 * Connection event used to inform {@link InCallService}s when the process of merging a 925 * Connection into a conference has begun. 926 * <p> 927 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 928 * expected to be null when this connection event is used. 929 */ 930 public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START"; 931 932 /** 933 * Connection event used to inform {@link InCallService}s when the process of merging a 934 * Connection into a conference has completed. 935 * <p> 936 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 937 * expected to be null when this connection event is used. 938 */ 939 public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE"; 940 941 /** 942 * Connection event used to inform {@link InCallService}s when a call has been put on hold by 943 * the remote party. 944 * <p> 945 * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the 946 * call is being held locally on the device. When a capable {@link ConnectionService} receives 947 * signalling to indicate that the remote party has put the call on hold, it can send this 948 * connection event. 949 */ 950 public static final String EVENT_CALL_REMOTELY_HELD = 951 "android.telecom.event.CALL_REMOTELY_HELD"; 952 953 /** 954 * Connection event used to inform {@link InCallService}s when a call which was remotely held 955 * (see {@link #EVENT_CALL_REMOTELY_HELD}) has been un-held by the remote party. 956 * <p> 957 * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the 958 * call is being held locally on the device. When a capable {@link ConnectionService} receives 959 * signalling to indicate that the remote party has taken the call off hold, it can send this 960 * connection event. 961 */ 962 public static final String EVENT_CALL_REMOTELY_UNHELD = 963 "android.telecom.event.CALL_REMOTELY_UNHELD"; 964 965 /** 966 * String Connection extra key used to store SIP invite fields for an incoming call for IMS call 967 */ 968 public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE"; 969 970 /** 971 * Connection event used to inform an {@link InCallService} that the RTT audio indication 972 * has changed. 973 */ 974 public static final String EVENT_RTT_AUDIO_INDICATION_CHANGED = 975 "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED"; 976 977 /** 978 * Connection event used to signal between the telephony {@link ConnectionService} and Telecom 979 * when device to device messages are sent/received. 980 * <p> 981 * Device to device messages originating from the network are sent by telephony using 982 * {@link Connection#sendConnectionEvent(String, Bundle)} and are routed up to any active 983 * {@link CallDiagnosticService} implementation which is active. 984 * <p> 985 * Likewise, if a {@link CallDiagnosticService} sends a message using 986 * {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}, it will be routed to telephony 987 * via {@link Connection#onCallEvent(String, Bundle)}. The telephony stack will relay the 988 * message to the other device. 989 * @hide 990 */ 991 @SystemApi 992 public static final String EVENT_DEVICE_TO_DEVICE_MESSAGE = 993 "android.telecom.event.DEVICE_TO_DEVICE_MESSAGE"; 994 995 /** 996 * Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device 997 * message type. 998 * 999 * See {@link CallDiagnostics} for more information. 1000 * @hide 1001 */ 1002 @SystemApi 1003 public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE = 1004 "android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_TYPE"; 1005 1006 /** 1007 * Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device 1008 * message value. 1009 * <p> 1010 * See {@link CallDiagnostics} for more information. 1011 * @hide 1012 */ 1013 @SystemApi 1014 public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE = 1015 "android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_VALUE"; 1016 1017 /** 1018 * Connection event used to communicate a {@link android.telephony.CallQuality} report from 1019 * telephony to Telecom for relaying to 1020 * {@link CallDiagnostics#onCallQualityReceived(CallQuality)}. 1021 * @hide 1022 */ 1023 @SystemApi 1024 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) 1025 public static final String EVENT_CALL_QUALITY_REPORT = 1026 "android.telecom.event.CALL_QUALITY_REPORT"; 1027 1028 /** 1029 * Extra sent with {@link #EVENT_CALL_QUALITY_REPORT} containing the 1030 * {@link android.telephony.CallQuality} data. 1031 * @hide 1032 */ 1033 @SystemApi 1034 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) 1035 public static final String EXTRA_CALL_QUALITY_REPORT = 1036 "android.telecom.extra.CALL_QUALITY_REPORT"; 1037 1038 /** 1039 * Key to obtain location as a result of ({@code queryLocationForEmergency} from Bundle 1040 * @hide 1041 */ 1042 public static final String EXTRA_KEY_QUERY_LOCATION = 1043 "android.telecom.extra.KEY_QUERY_LOCATION"; 1044 1045 // Flag controlling whether PII is emitted into the logs 1046 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); 1047 1048 /** 1049 * Renders a set of capability bits ({@code CAPABILITY_*}) as a human readable string. 1050 * 1051 * @param capabilities A capability bit field. 1052 * @return A human readable string representation. 1053 */ capabilitiesToString(int capabilities)1054 public static String capabilitiesToString(int capabilities) { 1055 return capabilitiesToStringInternal(capabilities, true /* isLong */); 1056 } 1057 1058 /** 1059 * Renders a set of capability bits ({@code CAPABILITY_*}) as a *short* human readable 1060 * string. 1061 * 1062 * @param capabilities A capability bit field. 1063 * @return A human readable string representation. 1064 * @hide 1065 */ capabilitiesToStringShort(int capabilities)1066 public static String capabilitiesToStringShort(int capabilities) { 1067 return capabilitiesToStringInternal(capabilities, false /* isLong */); 1068 } 1069 capabilitiesToStringInternal(int capabilities, boolean isLong)1070 private static String capabilitiesToStringInternal(int capabilities, boolean isLong) { 1071 StringBuilder builder = new StringBuilder(); 1072 builder.append("["); 1073 if (isLong) { 1074 builder.append("Capabilities:"); 1075 } 1076 1077 if ((capabilities & CAPABILITY_HOLD) == CAPABILITY_HOLD) { 1078 builder.append(isLong ? " CAPABILITY_HOLD" : " hld"); 1079 } 1080 if ((capabilities & CAPABILITY_SUPPORT_HOLD) == CAPABILITY_SUPPORT_HOLD) { 1081 builder.append(isLong ? " CAPABILITY_SUPPORT_HOLD" : " sup_hld"); 1082 } 1083 if ((capabilities & CAPABILITY_MERGE_CONFERENCE) == CAPABILITY_MERGE_CONFERENCE) { 1084 builder.append(isLong ? " CAPABILITY_MERGE_CONFERENCE" : " mrg_cnf"); 1085 } 1086 if ((capabilities & CAPABILITY_SWAP_CONFERENCE) == CAPABILITY_SWAP_CONFERENCE) { 1087 builder.append(isLong ? " CAPABILITY_SWAP_CONFERENCE" : " swp_cnf"); 1088 } 1089 if ((capabilities & CAPABILITY_RESPOND_VIA_TEXT) == CAPABILITY_RESPOND_VIA_TEXT) { 1090 builder.append(isLong ? " CAPABILITY_RESPOND_VIA_TEXT" : " txt"); 1091 } 1092 if ((capabilities & CAPABILITY_MUTE) == CAPABILITY_MUTE) { 1093 builder.append(isLong ? " CAPABILITY_MUTE" : " mut"); 1094 } 1095 if ((capabilities & CAPABILITY_MANAGE_CONFERENCE) == CAPABILITY_MANAGE_CONFERENCE) { 1096 builder.append(isLong ? " CAPABILITY_MANAGE_CONFERENCE" : " mng_cnf"); 1097 } 1098 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_RX) == CAPABILITY_SUPPORTS_VT_LOCAL_RX) { 1099 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_RX" : " VTlrx"); 1100 } 1101 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_TX) == CAPABILITY_SUPPORTS_VT_LOCAL_TX) { 1102 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_TX" : " VTltx"); 1103 } 1104 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) 1105 == CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) { 1106 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL" : " VTlbi"); 1107 } 1108 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_RX) == CAPABILITY_SUPPORTS_VT_REMOTE_RX) { 1109 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_RX" : " VTrrx"); 1110 } 1111 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_TX) == CAPABILITY_SUPPORTS_VT_REMOTE_TX) { 1112 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_TX" : " VTrtx"); 1113 } 1114 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) 1115 == CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) { 1116 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL" : " VTrbi"); 1117 } 1118 if ((capabilities & CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) 1119 == CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) { 1120 builder.append(isLong ? " CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO" : " !v2a"); 1121 } 1122 if ((capabilities & CAPABILITY_SPEED_UP_MT_AUDIO) == CAPABILITY_SPEED_UP_MT_AUDIO) { 1123 builder.append(isLong ? " CAPABILITY_SPEED_UP_MT_AUDIO" : " spd_aud"); 1124 } 1125 if ((capabilities & CAPABILITY_CAN_UPGRADE_TO_VIDEO) == CAPABILITY_CAN_UPGRADE_TO_VIDEO) { 1126 builder.append(isLong ? " CAPABILITY_CAN_UPGRADE_TO_VIDEO" : " a2v"); 1127 } 1128 if ((capabilities & CAPABILITY_CAN_PAUSE_VIDEO) == CAPABILITY_CAN_PAUSE_VIDEO) { 1129 builder.append(isLong ? " CAPABILITY_CAN_PAUSE_VIDEO" : " paus_VT"); 1130 } 1131 if ((capabilities & CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) 1132 == CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) { 1133 builder.append(isLong ? " CAPABILITY_SINGLE_PARTY_CONFERENCE" : " 1p_cnf"); 1134 } 1135 if ((capabilities & CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) 1136 == CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) { 1137 builder.append(isLong ? " CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION" : " rsp_by_con"); 1138 } 1139 if ((capabilities & CAPABILITY_CAN_PULL_CALL) == CAPABILITY_CAN_PULL_CALL) { 1140 builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull"); 1141 } 1142 if ((capabilities & CAPABILITY_SUPPORT_DEFLECT) == CAPABILITY_SUPPORT_DEFLECT) { 1143 builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def"); 1144 } 1145 if ((capabilities & CAPABILITY_ADD_PARTICIPANT) == CAPABILITY_ADD_PARTICIPANT) { 1146 builder.append(isLong ? " CAPABILITY_ADD_PARTICIPANT" : " add_participant"); 1147 } 1148 if ((capabilities & CAPABILITY_TRANSFER) == CAPABILITY_TRANSFER) { 1149 builder.append(isLong ? " CAPABILITY_TRANSFER" : " sup_trans"); 1150 } 1151 if ((capabilities & CAPABILITY_TRANSFER_CONSULTATIVE) 1152 == CAPABILITY_TRANSFER_CONSULTATIVE) { 1153 builder.append(isLong ? " CAPABILITY_TRANSFER_CONSULTATIVE" : " sup_cTrans"); 1154 } 1155 if ((capabilities & CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT) 1156 == CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT) { 1157 builder.append(isLong ? " CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT" : " sup_rtt"); 1158 } 1159 builder.append("]"); 1160 return builder.toString(); 1161 } 1162 1163 /** 1164 * Renders a set of property bits ({@code PROPERTY_*}) as a human readable string. 1165 * 1166 * @param properties A property bit field. 1167 * @return A human readable string representation. 1168 */ propertiesToString(int properties)1169 public static String propertiesToString(int properties) { 1170 return propertiesToStringInternal(properties, true /* isLong */); 1171 } 1172 1173 /** 1174 * Renders a set of property bits ({@code PROPERTY_*}) as a *short* human readable string. 1175 * 1176 * @param properties A property bit field. 1177 * @return A human readable string representation. 1178 * @hide 1179 */ propertiesToStringShort(int properties)1180 public static String propertiesToStringShort(int properties) { 1181 return propertiesToStringInternal(properties, false /* isLong */); 1182 } 1183 propertiesToStringInternal(int properties, boolean isLong)1184 private static String propertiesToStringInternal(int properties, boolean isLong) { 1185 StringBuilder builder = new StringBuilder(); 1186 builder.append("["); 1187 if (isLong) { 1188 builder.append("Properties:"); 1189 } 1190 1191 if ((properties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) { 1192 builder.append(isLong ? " PROPERTY_SELF_MANAGED" : " self_mng"); 1193 } 1194 1195 if ((properties & PROPERTY_EMERGENCY_CALLBACK_MODE) == PROPERTY_EMERGENCY_CALLBACK_MODE) { 1196 builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm"); 1197 } 1198 1199 if ((properties & PROPERTY_HIGH_DEF_AUDIO) == PROPERTY_HIGH_DEF_AUDIO) { 1200 builder.append(isLong ? " PROPERTY_HIGH_DEF_AUDIO" : " HD"); 1201 } 1202 1203 if ((properties & PROPERTY_WIFI) == PROPERTY_WIFI) { 1204 builder.append(isLong ? " PROPERTY_WIFI" : " wifi"); 1205 } 1206 1207 if ((properties & PROPERTY_GENERIC_CONFERENCE) == PROPERTY_GENERIC_CONFERENCE) { 1208 builder.append(isLong ? " PROPERTY_GENERIC_CONFERENCE" : " gen_conf"); 1209 } 1210 1211 if ((properties & PROPERTY_IS_EXTERNAL_CALL) == PROPERTY_IS_EXTERNAL_CALL) { 1212 builder.append(isLong ? " PROPERTY_IS_EXTERNAL_CALL" : " xtrnl"); 1213 } 1214 1215 if ((properties & PROPERTY_HAS_CDMA_VOICE_PRIVACY) == PROPERTY_HAS_CDMA_VOICE_PRIVACY) { 1216 builder.append(isLong ? " PROPERTY_HAS_CDMA_VOICE_PRIVACY" : " priv"); 1217 } 1218 1219 if ((properties & PROPERTY_IS_RTT) == PROPERTY_IS_RTT) { 1220 builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt"); 1221 } 1222 1223 if ((properties & PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) 1224 == PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) { 1225 builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall"); 1226 } 1227 1228 if ((properties & PROPERTY_REMOTELY_HOSTED) == PROPERTY_REMOTELY_HOSTED) { 1229 builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst"); 1230 } 1231 1232 if ((properties & PROPERTY_IS_ADHOC_CONFERENCE) == PROPERTY_IS_ADHOC_CONFERENCE) { 1233 builder.append(isLong ? " PROPERTY_IS_ADHOC_CONFERENCE" : " adhoc_conf"); 1234 } 1235 1236 if ((properties & PROPERTY_IS_DOWNGRADED_CONFERENCE) == PROPERTY_IS_DOWNGRADED_CONFERENCE) { 1237 builder.append(isLong ? " PROPERTY_IS_DOWNGRADED_CONFERENCE" : " dngrd_conf"); 1238 } 1239 1240 builder.append("]"); 1241 return builder.toString(); 1242 } 1243 1244 /** @hide */ 1245 abstract static class Listener { onStateChanged(Connection c, int state)1246 public void onStateChanged(Connection c, int state) {} onAddressChanged(Connection c, Uri newAddress, int presentation)1247 public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} onCallerDisplayNameChanged( Connection c, String callerDisplayName, int presentation)1248 public void onCallerDisplayNameChanged( 1249 Connection c, String callerDisplayName, int presentation) {} onVideoStateChanged(Connection c, int videoState)1250 public void onVideoStateChanged(Connection c, int videoState) {} onDisconnected(Connection c, DisconnectCause disconnectCause)1251 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {} onPostDialWait(Connection c, String remaining)1252 public void onPostDialWait(Connection c, String remaining) {} onPostDialChar(Connection c, char nextChar)1253 public void onPostDialChar(Connection c, char nextChar) {} onRingbackRequested(Connection c, boolean ringback)1254 public void onRingbackRequested(Connection c, boolean ringback) {} onDestroyed(Connection c)1255 public void onDestroyed(Connection c) {} onConnectionCapabilitiesChanged(Connection c, int capabilities)1256 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {} onConnectionPropertiesChanged(Connection c, int properties)1257 public void onConnectionPropertiesChanged(Connection c, int properties) {} onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes)1258 public void onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes) {} onVideoProviderChanged( Connection c, VideoProvider videoProvider)1259 public void onVideoProviderChanged( 1260 Connection c, VideoProvider videoProvider) {} onAudioModeIsVoipChanged(Connection c, boolean isVoip)1261 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} onStatusHintsChanged(Connection c, StatusHints statusHints)1262 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} onConferenceablesChanged( Connection c, List<Conferenceable> conferenceables)1263 public void onConferenceablesChanged( 1264 Connection c, List<Conferenceable> conferenceables) {} onConferenceChanged(Connection c, Conference conference)1265 public void onConferenceChanged(Connection c, Conference conference) {} onConferenceMergeFailed(Connection c)1266 public void onConferenceMergeFailed(Connection c) {} onExtrasChanged(Connection c, Bundle extras)1267 public void onExtrasChanged(Connection c, Bundle extras) {} onExtrasRemoved(Connection c, List<String> keys)1268 public void onExtrasRemoved(Connection c, List<String> keys) {} onConnectionEvent(Connection c, String event, Bundle extras)1269 public void onConnectionEvent(Connection c, String event, Bundle extras) {} onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress)1270 public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {} onRttInitiationSuccess(Connection c)1271 public void onRttInitiationSuccess(Connection c) {} onRttInitiationFailure(Connection c, int reason)1272 public void onRttInitiationFailure(Connection c, int reason) {} onRttSessionRemotelyTerminated(Connection c)1273 public void onRttSessionRemotelyTerminated(Connection c) {} onRemoteRttRequest(Connection c)1274 public void onRemoteRttRequest(Connection c) {} 1275 /** @hide */ onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle)1276 public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {} onConnectionTimeReset(Connection c)1277 public void onConnectionTimeReset(Connection c) {} onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor, OutcomeReceiver<Void, CallEndpointException> callback)1278 public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor, 1279 OutcomeReceiver<Void, CallEndpointException> callback) {} onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Location, QueryLocationException> callback)1280 public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider, 1281 @NonNull @CallbackExecutor Executor executor, 1282 @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {} 1283 } 1284 1285 /** 1286 * Provides methods to read and write RTT data to/from the in-call app. 1287 */ 1288 public static final class RttTextStream { 1289 private static final int READ_BUFFER_SIZE = 1000; 1290 private final InputStreamReader mPipeFromInCall; 1291 private final OutputStreamWriter mPipeToInCall; 1292 private final ParcelFileDescriptor mFdFromInCall; 1293 private final ParcelFileDescriptor mFdToInCall; 1294 1295 private final FileInputStream mFromInCallFileInputStream; 1296 private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; 1297 1298 /** 1299 * @hide 1300 */ RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall)1301 public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) { 1302 mFdFromInCall = fromInCall; 1303 mFdToInCall = toInCall; 1304 mFromInCallFileInputStream = new FileInputStream(fromInCall.getFileDescriptor()); 1305 1306 // Wrap the FileInputStream in a Channel so that it's interruptible. 1307 mPipeFromInCall = new InputStreamReader( 1308 Channels.newInputStream(Channels.newChannel(mFromInCallFileInputStream))); 1309 mPipeToInCall = new OutputStreamWriter( 1310 new FileOutputStream(toInCall.getFileDescriptor())); 1311 } 1312 1313 /** 1314 * Writes the string {@param input} into the text stream to the UI for this RTT call. Since 1315 * RTT transmits text in real-time, this method should be called as often as text snippets 1316 * are received from the remote user, even if it is only one character. 1317 * <p> 1318 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1319 * lead to interleaved text. 1320 * 1321 * @param input The message to send to the in-call app. 1322 */ write(String input)1323 public void write(String input) throws IOException { 1324 mPipeToInCall.write(input); 1325 mPipeToInCall.flush(); 1326 } 1327 1328 1329 /** 1330 * Reads a string from the in-call app, blocking if there is no data available. Returns 1331 * {@code null} if the RTT conversation has been terminated and there is no further data 1332 * to read. 1333 * <p> 1334 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1335 * lead to interleaved text. 1336 * 1337 * @return A string containing text entered by the user, or {@code null} if the 1338 * conversation has been terminated or if there was an error while reading. 1339 */ read()1340 public String read() throws IOException { 1341 int numRead = mPipeFromInCall.read(mReadBuffer, 0, READ_BUFFER_SIZE); 1342 if (numRead < 0) { 1343 return null; 1344 } 1345 return new String(mReadBuffer, 0, numRead); 1346 } 1347 1348 /** 1349 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to 1350 * be read. 1351 * 1352 * @return A string containing text entered by the user, or {@code null} if the user has 1353 * not entered any new text yet. 1354 */ readImmediately()1355 public String readImmediately() throws IOException { 1356 if (mFromInCallFileInputStream.available() > 0) { 1357 return read(); 1358 } else { 1359 return null; 1360 } 1361 } 1362 1363 /** @hide */ getFdFromInCall()1364 public ParcelFileDescriptor getFdFromInCall() { 1365 return mFdFromInCall; 1366 } 1367 1368 /** @hide */ getFdToInCall()1369 public ParcelFileDescriptor getFdToInCall() { 1370 return mFdToInCall; 1371 } 1372 } 1373 1374 /** 1375 * Provides constants to represent the results of responses to session modify requests sent via 1376 * {@link Call#sendRttRequest()} 1377 */ 1378 public static final class RttModifyStatus { RttModifyStatus()1379 private RttModifyStatus() {} 1380 /** 1381 * Session modify request was successful. 1382 */ 1383 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; 1384 1385 /** 1386 * Session modify request failed. 1387 */ 1388 public static final int SESSION_MODIFY_REQUEST_FAIL = 2; 1389 1390 /** 1391 * Session modify request ignored due to invalid parameters. 1392 */ 1393 public static final int SESSION_MODIFY_REQUEST_INVALID = 3; 1394 1395 /** 1396 * Session modify request timed out. 1397 */ 1398 public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; 1399 1400 /** 1401 * Session modify request rejected by remote user. 1402 */ 1403 public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; 1404 1405 1406 /**@hide*/ 1407 @Retention(RetentionPolicy.SOURCE) 1408 @IntDef(prefix = "SESSION_MODIFY_REQUEST_", value = { 1409 SESSION_MODIFY_REQUEST_SUCCESS, 1410 SESSION_MODIFY_REQUEST_FAIL, 1411 SESSION_MODIFY_REQUEST_INVALID, 1412 SESSION_MODIFY_REQUEST_TIMED_OUT, 1413 SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE 1414 }) 1415 public @interface RttSessionModifyStatus {} 1416 } 1417 1418 /** 1419 * Provides a means of controlling the video session associated with a {@link Connection}. 1420 * <p> 1421 * Implementations create a custom subclass of {@link VideoProvider} and the 1422 * {@link ConnectionService} creates an instance sets it on the {@link Connection} using 1423 * {@link Connection#setVideoProvider(VideoProvider)}. Any connection which supports video 1424 * should set the {@link VideoProvider}. 1425 * <p> 1426 * The {@link VideoProvider} serves two primary purposes: it provides a means for Telecom and 1427 * {@link InCallService} implementations to issue requests related to the video session; 1428 * it provides a means for the {@link ConnectionService} to report events and information 1429 * related to the video session to Telecom and the {@link InCallService} implementations. 1430 * <p> 1431 * {@link InCallService} implementations interact with the {@link VideoProvider} via 1432 * {@link android.telecom.InCallService.VideoCall}. 1433 */ 1434 public static abstract class VideoProvider { 1435 /** 1436 * Video is not being received (no protocol pause was issued). 1437 * @see #handleCallSessionEvent(int) 1438 */ 1439 public static final int SESSION_EVENT_RX_PAUSE = 1; 1440 1441 /** 1442 * Video reception has resumed after a {@link #SESSION_EVENT_RX_PAUSE}. 1443 * @see #handleCallSessionEvent(int) 1444 */ 1445 public static final int SESSION_EVENT_RX_RESUME = 2; 1446 1447 /** 1448 * Video transmission has begun. This occurs after a negotiated start of video transmission 1449 * when the underlying protocol has actually begun transmitting video to the remote party. 1450 * @see #handleCallSessionEvent(int) 1451 */ 1452 public static final int SESSION_EVENT_TX_START = 3; 1453 1454 /** 1455 * Video transmission has stopped. This occurs after a negotiated stop of video transmission 1456 * when the underlying protocol has actually stopped transmitting video to the remote party. 1457 * @see #handleCallSessionEvent(int) 1458 */ 1459 public static final int SESSION_EVENT_TX_STOP = 4; 1460 1461 /** 1462 * A camera failure has occurred for the selected camera. The {@link VideoProvider} can use 1463 * this as a cue to inform the user the camera is not available. 1464 * @see #handleCallSessionEvent(int) 1465 */ 1466 public static final int SESSION_EVENT_CAMERA_FAILURE = 5; 1467 1468 /** 1469 * Issued after {@link #SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready 1470 * for operation. The {@link VideoProvider} can use this as a cue to inform the user that 1471 * the camera has become available again. 1472 * @see #handleCallSessionEvent(int) 1473 */ 1474 public static final int SESSION_EVENT_CAMERA_READY = 6; 1475 1476 /** 1477 * Session event raised by Telecom when 1478 * {@link android.telecom.InCallService.VideoCall#setCamera(String)} is called and the 1479 * caller does not have the necessary {@link android.Manifest.permission#CAMERA} permission. 1480 * @see #handleCallSessionEvent(int) 1481 */ 1482 public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7; 1483 1484 /** 1485 * Session modify request was successful. 1486 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1487 */ 1488 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; 1489 1490 /** 1491 * Session modify request failed. 1492 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1493 */ 1494 public static final int SESSION_MODIFY_REQUEST_FAIL = 2; 1495 1496 /** 1497 * Session modify request ignored due to invalid parameters. 1498 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1499 */ 1500 public static final int SESSION_MODIFY_REQUEST_INVALID = 3; 1501 1502 /** 1503 * Session modify request timed out. 1504 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1505 */ 1506 public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; 1507 1508 /** 1509 * Session modify request rejected by remote user. 1510 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1511 */ 1512 public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; 1513 1514 private static final int MSG_ADD_VIDEO_CALLBACK = 1; 1515 private static final int MSG_SET_CAMERA = 2; 1516 private static final int MSG_SET_PREVIEW_SURFACE = 3; 1517 private static final int MSG_SET_DISPLAY_SURFACE = 4; 1518 private static final int MSG_SET_DEVICE_ORIENTATION = 5; 1519 private static final int MSG_SET_ZOOM = 6; 1520 private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7; 1521 private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8; 1522 private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9; 1523 private static final int MSG_REQUEST_CONNECTION_DATA_USAGE = 10; 1524 private static final int MSG_SET_PAUSE_IMAGE = 11; 1525 private static final int MSG_REMOVE_VIDEO_CALLBACK = 12; 1526 1527 private static final String SESSION_EVENT_RX_PAUSE_STR = "RX_PAUSE"; 1528 private static final String SESSION_EVENT_RX_RESUME_STR = "RX_RESUME"; 1529 private static final String SESSION_EVENT_TX_START_STR = "TX_START"; 1530 private static final String SESSION_EVENT_TX_STOP_STR = "TX_STOP"; 1531 private static final String SESSION_EVENT_CAMERA_FAILURE_STR = "CAMERA_FAIL"; 1532 private static final String SESSION_EVENT_CAMERA_READY_STR = "CAMERA_READY"; 1533 private static final String SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR = 1534 "CAMERA_PERMISSION_ERROR"; 1535 private static final String SESSION_EVENT_UNKNOWN_STR = "UNKNOWN"; 1536 1537 private VideoProvider.VideoProviderHandler mMessageHandler; 1538 private final VideoProvider.VideoProviderBinder mBinder; 1539 1540 /** 1541 * Stores a list of the video callbacks, keyed by IBinder. 1542 * 1543 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 1544 * load factor before resizing, 1 means we only expect a single thread to 1545 * access the map so make only a single shard 1546 */ 1547 private ConcurrentHashMap<IBinder, IVideoCallback> mVideoCallbacks = 1548 new ConcurrentHashMap<IBinder, IVideoCallback>(8, 0.9f, 1); 1549 1550 /** 1551 * Default handler used to consolidate binder method calls onto a single thread. 1552 */ 1553 private final class VideoProviderHandler extends Handler { VideoProviderHandler()1554 public VideoProviderHandler() { 1555 super(); 1556 } 1557 VideoProviderHandler(Looper looper)1558 public VideoProviderHandler(Looper looper) { 1559 super(looper); 1560 } 1561 1562 @Override handleMessage(Message msg)1563 public void handleMessage(Message msg) { 1564 switch (msg.what) { 1565 case MSG_ADD_VIDEO_CALLBACK: { 1566 IBinder binder = (IBinder) msg.obj; 1567 IVideoCallback callback = IVideoCallback.Stub 1568 .asInterface((IBinder) msg.obj); 1569 if (callback == null) { 1570 Log.w(this, "addVideoProvider - skipped; callback is null."); 1571 break; 1572 } 1573 1574 if (mVideoCallbacks.containsKey(binder)) { 1575 Log.i(this, "addVideoProvider - skipped; already present."); 1576 break; 1577 } 1578 mVideoCallbacks.put(binder, callback); 1579 break; 1580 } 1581 case MSG_REMOVE_VIDEO_CALLBACK: { 1582 IBinder binder = (IBinder) msg.obj; 1583 IVideoCallback callback = IVideoCallback.Stub 1584 .asInterface((IBinder) msg.obj); 1585 if (!mVideoCallbacks.containsKey(binder)) { 1586 Log.i(this, "removeVideoProvider - skipped; not present."); 1587 break; 1588 } 1589 mVideoCallbacks.remove(binder); 1590 break; 1591 } 1592 case MSG_SET_CAMERA: 1593 { 1594 SomeArgs args = (SomeArgs) msg.obj; 1595 try { 1596 onSetCamera((String) args.arg1); 1597 onSetCamera((String) args.arg1, (String) args.arg2, args.argi1, 1598 args.argi2, args.argi3); 1599 } finally { 1600 args.recycle(); 1601 } 1602 } 1603 break; 1604 case MSG_SET_PREVIEW_SURFACE: 1605 onSetPreviewSurface((Surface) msg.obj); 1606 break; 1607 case MSG_SET_DISPLAY_SURFACE: 1608 onSetDisplaySurface((Surface) msg.obj); 1609 break; 1610 case MSG_SET_DEVICE_ORIENTATION: 1611 onSetDeviceOrientation(msg.arg1); 1612 break; 1613 case MSG_SET_ZOOM: 1614 onSetZoom((Float) msg.obj); 1615 break; 1616 case MSG_SEND_SESSION_MODIFY_REQUEST: { 1617 SomeArgs args = (SomeArgs) msg.obj; 1618 try { 1619 onSendSessionModifyRequest((VideoProfile) args.arg1, 1620 (VideoProfile) args.arg2); 1621 } finally { 1622 args.recycle(); 1623 } 1624 break; 1625 } 1626 case MSG_SEND_SESSION_MODIFY_RESPONSE: 1627 onSendSessionModifyResponse((VideoProfile) msg.obj); 1628 break; 1629 case MSG_REQUEST_CAMERA_CAPABILITIES: 1630 onRequestCameraCapabilities(); 1631 break; 1632 case MSG_REQUEST_CONNECTION_DATA_USAGE: 1633 onRequestConnectionDataUsage(); 1634 break; 1635 case MSG_SET_PAUSE_IMAGE: 1636 onSetPauseImage((Uri) msg.obj); 1637 break; 1638 default: 1639 break; 1640 } 1641 } 1642 } 1643 1644 /** 1645 * IVideoProvider stub implementation. 1646 */ 1647 private final class VideoProviderBinder extends IVideoProvider.Stub { addVideoCallback(IBinder videoCallbackBinder)1648 public void addVideoCallback(IBinder videoCallbackBinder) { 1649 mMessageHandler.obtainMessage( 1650 MSG_ADD_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); 1651 } 1652 removeVideoCallback(IBinder videoCallbackBinder)1653 public void removeVideoCallback(IBinder videoCallbackBinder) { 1654 mMessageHandler.obtainMessage( 1655 MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); 1656 } 1657 setCamera(String cameraId, String callingPackageName, int targetSdkVersion)1658 public void setCamera(String cameraId, String callingPackageName, 1659 int targetSdkVersion) { 1660 1661 SomeArgs args = SomeArgs.obtain(); 1662 args.arg1 = cameraId; 1663 // Propagate the calling package; originally determined in 1664 // android.telecom.InCallService.VideoCall#setCamera(String) from the calling 1665 // process. 1666 args.arg2 = callingPackageName; 1667 // Pass along the uid and pid of the calling app; this gets lost when we put the 1668 // message onto the handler. These are required for Telecom to perform a permission 1669 // check to see if the calling app is able to use the camera. 1670 args.argi1 = Binder.getCallingUid(); 1671 args.argi2 = Binder.getCallingPid(); 1672 // Pass along the target SDK version of the calling InCallService. This is used to 1673 // maintain backwards compatibility of the API for older callers. 1674 args.argi3 = targetSdkVersion; 1675 mMessageHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget(); 1676 } 1677 setPreviewSurface(Surface surface)1678 public void setPreviewSurface(Surface surface) { 1679 mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget(); 1680 } 1681 setDisplaySurface(Surface surface)1682 public void setDisplaySurface(Surface surface) { 1683 mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget(); 1684 } 1685 setDeviceOrientation(int rotation)1686 public void setDeviceOrientation(int rotation) { 1687 mMessageHandler.obtainMessage( 1688 MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget(); 1689 } 1690 setZoom(float value)1691 public void setZoom(float value) { 1692 mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget(); 1693 } 1694 sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)1695 public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) { 1696 SomeArgs args = SomeArgs.obtain(); 1697 args.arg1 = fromProfile; 1698 args.arg2 = toProfile; 1699 mMessageHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget(); 1700 } 1701 sendSessionModifyResponse(VideoProfile responseProfile)1702 public void sendSessionModifyResponse(VideoProfile responseProfile) { 1703 mMessageHandler.obtainMessage( 1704 MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget(); 1705 } 1706 requestCameraCapabilities()1707 public void requestCameraCapabilities() { 1708 mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget(); 1709 } 1710 requestCallDataUsage()1711 public void requestCallDataUsage() { 1712 mMessageHandler.obtainMessage(MSG_REQUEST_CONNECTION_DATA_USAGE).sendToTarget(); 1713 } 1714 setPauseImage(Uri uri)1715 public void setPauseImage(Uri uri) { 1716 mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget(); 1717 } 1718 } 1719 VideoProvider()1720 public VideoProvider() { 1721 mBinder = new VideoProvider.VideoProviderBinder(); 1722 mMessageHandler = new VideoProvider.VideoProviderHandler(Looper.getMainLooper()); 1723 } 1724 1725 /** 1726 * Creates an instance of the {@link VideoProvider}, specifying the looper to use. 1727 * 1728 * @param looper The looper. 1729 * @hide 1730 */ 1731 @UnsupportedAppUsage VideoProvider(Looper looper)1732 public VideoProvider(Looper looper) { 1733 mBinder = new VideoProvider.VideoProviderBinder(); 1734 mMessageHandler = new VideoProvider.VideoProviderHandler(looper); 1735 } 1736 1737 /** 1738 * Returns binder object which can be used across IPC methods. 1739 * @hide 1740 */ getInterface()1741 public final IVideoProvider getInterface() { 1742 return mBinder; 1743 } 1744 1745 /** 1746 * Sets the camera to be used for the outgoing video. 1747 * <p> 1748 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1749 * camera via 1750 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1751 * <p> 1752 * Sent from the {@link InCallService} via 1753 * {@link InCallService.VideoCall#setCamera(String)}. 1754 * 1755 * @param cameraId The id of the camera (use ids as reported by 1756 * {@link CameraManager#getCameraIdList()}). 1757 */ onSetCamera(String cameraId)1758 public abstract void onSetCamera(String cameraId); 1759 1760 /** 1761 * Sets the camera to be used for the outgoing video. 1762 * <p> 1763 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1764 * camera via 1765 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1766 * <p> 1767 * This prototype is used internally to ensure that the calling package name, UID and PID 1768 * are sent to Telecom so that can perform a camera permission check on the caller. 1769 * <p> 1770 * Sent from the {@link InCallService} via 1771 * {@link InCallService.VideoCall#setCamera(String)}. 1772 * 1773 * @param cameraId The id of the camera (use ids as reported by 1774 * {@link CameraManager#getCameraIdList()}). 1775 * @param callingPackageName The AppOpps package name of the caller. 1776 * @param callingUid The UID of the caller. 1777 * @param callingPid The PID of the caller. 1778 * @param targetSdkVersion The target SDK version of the caller. 1779 * @hide 1780 */ onSetCamera(String cameraId, String callingPackageName, int callingUid, int callingPid, int targetSdkVersion)1781 public void onSetCamera(String cameraId, String callingPackageName, int callingUid, 1782 int callingPid, int targetSdkVersion) {} 1783 1784 /** 1785 * Sets the surface to be used for displaying a preview of what the user's camera is 1786 * currently capturing. When video transmission is enabled, this is the video signal which 1787 * is sent to the remote device. 1788 * <p> 1789 * Sent from the {@link InCallService} via 1790 * {@link InCallService.VideoCall#setPreviewSurface(Surface)}. 1791 * 1792 * @param surface The {@link Surface}. 1793 */ onSetPreviewSurface(Surface surface)1794 public abstract void onSetPreviewSurface(Surface surface); 1795 1796 /** 1797 * Sets the surface to be used for displaying the video received from the remote device. 1798 * <p> 1799 * Sent from the {@link InCallService} via 1800 * {@link InCallService.VideoCall#setDisplaySurface(Surface)}. 1801 * 1802 * @param surface The {@link Surface}. 1803 */ onSetDisplaySurface(Surface surface)1804 public abstract void onSetDisplaySurface(Surface surface); 1805 1806 /** 1807 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of 1808 * the device is 0 degrees. 1809 * <p> 1810 * Sent from the {@link InCallService} via 1811 * {@link InCallService.VideoCall#setDeviceOrientation(int)}. 1812 * 1813 * @param rotation The device orientation, in degrees. 1814 */ onSetDeviceOrientation(int rotation)1815 public abstract void onSetDeviceOrientation(int rotation); 1816 1817 /** 1818 * Sets the camera zoom ratio. 1819 * <p> 1820 * Sent from the {@link InCallService} via {@link InCallService.VideoCall#setZoom(float)}. 1821 * 1822 * @param value The camera zoom ratio; for the current camera, should be a value in the 1823 * range defined by 1824 * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}. 1825 */ onSetZoom(float value)1826 public abstract void onSetZoom(float value); 1827 1828 /** 1829 * Issues a request to modify the properties of the current video session. 1830 * <p> 1831 * Example scenarios include: requesting an audio-only call to be upgraded to a 1832 * bi-directional video call, turning on or off the user's camera, sending a pause signal 1833 * when the {@link InCallService} is no longer the foreground application. 1834 * <p> 1835 * If the {@link VideoProvider} determines a request to be invalid, it should call 1836 * {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} to report the 1837 * invalid request back to the {@link InCallService}. 1838 * <p> 1839 * Where a request requires confirmation from the user of the peer device, the 1840 * {@link VideoProvider} must communicate the request to the peer device and handle the 1841 * user's response. {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} 1842 * is used to inform the {@link InCallService} of the result of the request. 1843 * <p> 1844 * Sent from the {@link InCallService} via 1845 * {@link InCallService.VideoCall#sendSessionModifyRequest(VideoProfile)}. 1846 * 1847 * @param fromProfile The video profile prior to the request. 1848 * @param toProfile The video profile with the requested changes made. 1849 */ onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)1850 public abstract void onSendSessionModifyRequest(VideoProfile fromProfile, 1851 VideoProfile toProfile); 1852 1853 /** 1854 * Provides a response to a request to change the current video session properties. 1855 * <p> 1856 * For example, if the peer requests and upgrade from an audio-only call to a bi-directional 1857 * video call, could decline the request and keep the call as audio-only. 1858 * In such a scenario, the {@code responseProfile} would have a video state of 1859 * {@link VideoProfile#STATE_AUDIO_ONLY}. If the user had decided to accept the request, 1860 * the video state would be {@link VideoProfile#STATE_BIDIRECTIONAL}. 1861 * <p> 1862 * Sent from the {@link InCallService} via 1863 * {@link InCallService.VideoCall#sendSessionModifyResponse(VideoProfile)} in response to 1864 * a {@link InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} 1865 * callback. 1866 * 1867 * @param responseProfile The response video profile. 1868 */ onSendSessionModifyResponse(VideoProfile responseProfile)1869 public abstract void onSendSessionModifyResponse(VideoProfile responseProfile); 1870 1871 /** 1872 * Issues a request to the {@link VideoProvider} to retrieve the camera capabilities. 1873 * <p> 1874 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1875 * camera via 1876 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1877 * <p> 1878 * Sent from the {@link InCallService} via 1879 * {@link InCallService.VideoCall#requestCameraCapabilities()}. 1880 */ onRequestCameraCapabilities()1881 public abstract void onRequestCameraCapabilities(); 1882 1883 /** 1884 * Issues a request to the {@link VideoProvider} to retrieve the current data usage for the 1885 * video component of the current {@link Connection}. 1886 * <p> 1887 * The {@link VideoProvider} should respond by communicating current data usage, in bytes, 1888 * via {@link VideoProvider#setCallDataUsage(long)}. 1889 * <p> 1890 * Sent from the {@link InCallService} via 1891 * {@link InCallService.VideoCall#requestCallDataUsage()}. 1892 */ onRequestConnectionDataUsage()1893 public abstract void onRequestConnectionDataUsage(); 1894 1895 /** 1896 * Provides the {@link VideoProvider} with the {@link Uri} of an image to be displayed to 1897 * the peer device when the video signal is paused. 1898 * <p> 1899 * Sent from the {@link InCallService} via 1900 * {@link InCallService.VideoCall#setPauseImage(Uri)}. 1901 * 1902 * @param uri URI of image to display. 1903 */ onSetPauseImage(Uri uri)1904 public abstract void onSetPauseImage(Uri uri); 1905 1906 /** 1907 * Used to inform listening {@link InCallService} implementations when the 1908 * {@link VideoProvider} receives a session modification request. 1909 * <p> 1910 * Received by the {@link InCallService} via 1911 * {@link InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)}, 1912 * 1913 * @param videoProfile The requested video profile. 1914 * @see #onSendSessionModifyRequest(VideoProfile, VideoProfile) 1915 */ receiveSessionModifyRequest(VideoProfile videoProfile)1916 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 1917 if (mVideoCallbacks != null) { 1918 for (IVideoCallback callback : mVideoCallbacks.values()) { 1919 try { 1920 callback.receiveSessionModifyRequest(videoProfile); 1921 } catch (RemoteException ignored) { 1922 Log.w(this, "receiveSessionModifyRequest callback failed", ignored); 1923 } 1924 } 1925 } 1926 } 1927 1928 /** 1929 * Used to inform listening {@link InCallService} implementations when the 1930 * {@link VideoProvider} receives a response to a session modification request. 1931 * <p> 1932 * Received by the {@link InCallService} via 1933 * {@link InCallService.VideoCall.Callback#onSessionModifyResponseReceived(int, 1934 * VideoProfile, VideoProfile)}. 1935 * 1936 * @param status Status of the session modify request. Valid values are 1937 * {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS}, 1938 * {@link VideoProvider#SESSION_MODIFY_REQUEST_FAIL}, 1939 * {@link VideoProvider#SESSION_MODIFY_REQUEST_INVALID}, 1940 * {@link VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT}, 1941 * {@link VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE} 1942 * @param requestedProfile The original request which was sent to the peer device. 1943 * @param responseProfile The actual profile changes agreed to by the peer device. 1944 * @see #onSendSessionModifyRequest(VideoProfile, VideoProfile) 1945 */ receiveSessionModifyResponse(int status, VideoProfile requestedProfile, VideoProfile responseProfile)1946 public void receiveSessionModifyResponse(int status, 1947 VideoProfile requestedProfile, VideoProfile responseProfile) { 1948 if (mVideoCallbacks != null) { 1949 for (IVideoCallback callback : mVideoCallbacks.values()) { 1950 try { 1951 callback.receiveSessionModifyResponse(status, requestedProfile, 1952 responseProfile); 1953 } catch (RemoteException ignored) { 1954 Log.w(this, "receiveSessionModifyResponse callback failed", ignored); 1955 } 1956 } 1957 } 1958 } 1959 1960 /** 1961 * Used to inform listening {@link InCallService} implementations when the 1962 * {@link VideoProvider} reports a call session event. 1963 * <p> 1964 * Received by the {@link InCallService} via 1965 * {@link InCallService.VideoCall.Callback#onCallSessionEvent(int)}. 1966 * 1967 * @param event The event. Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE}, 1968 * {@link VideoProvider#SESSION_EVENT_RX_RESUME}, 1969 * {@link VideoProvider#SESSION_EVENT_TX_START}, 1970 * {@link VideoProvider#SESSION_EVENT_TX_STOP}, 1971 * {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE}, 1972 * {@link VideoProvider#SESSION_EVENT_CAMERA_READY}, 1973 * {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE}. 1974 */ handleCallSessionEvent(int event)1975 public void handleCallSessionEvent(int event) { 1976 if (mVideoCallbacks != null) { 1977 for (IVideoCallback callback : mVideoCallbacks.values()) { 1978 try { 1979 callback.handleCallSessionEvent(event); 1980 } catch (RemoteException ignored) { 1981 Log.w(this, "handleCallSessionEvent callback failed", ignored); 1982 } 1983 } 1984 } 1985 } 1986 1987 /** 1988 * Used to inform listening {@link InCallService} implementations when the dimensions of the 1989 * peer's video have changed. 1990 * <p> 1991 * This could occur if, for example, the peer rotates their device, changing the aspect 1992 * ratio of the video, or if the user switches between the back and front cameras. 1993 * <p> 1994 * Received by the {@link InCallService} via 1995 * {@link InCallService.VideoCall.Callback#onPeerDimensionsChanged(int, int)}. 1996 * 1997 * @param width The updated peer video width. 1998 * @param height The updated peer video height. 1999 */ changePeerDimensions(int width, int height)2000 public void changePeerDimensions(int width, int height) { 2001 if (mVideoCallbacks != null) { 2002 for (IVideoCallback callback : mVideoCallbacks.values()) { 2003 try { 2004 callback.changePeerDimensions(width, height); 2005 } catch (RemoteException ignored) { 2006 Log.w(this, "changePeerDimensions callback failed", ignored); 2007 } 2008 } 2009 } 2010 } 2011 2012 /** 2013 * Used to inform listening {@link InCallService} implementations when the data usage of the 2014 * video associated with the current {@link Connection} has changed. 2015 * <p> 2016 * This could be in response to a preview request via 2017 * {@link #onRequestConnectionDataUsage()}, or as a periodic update by the 2018 * {@link VideoProvider}. Where periodic updates of data usage are provided, they should be 2019 * provided at most for every 1 MB of data transferred and no more than once every 10 sec. 2020 * <p> 2021 * Received by the {@link InCallService} via 2022 * {@link InCallService.VideoCall.Callback#onCallDataUsageChanged(long)}. 2023 * 2024 * @param dataUsage The updated data usage (in bytes). Reported as the cumulative bytes 2025 * used since the start of the call. 2026 */ setCallDataUsage(long dataUsage)2027 public void setCallDataUsage(long dataUsage) { 2028 if (mVideoCallbacks != null) { 2029 for (IVideoCallback callback : mVideoCallbacks.values()) { 2030 try { 2031 callback.changeCallDataUsage(dataUsage); 2032 } catch (RemoteException ignored) { 2033 Log.w(this, "setCallDataUsage callback failed", ignored); 2034 } 2035 } 2036 } 2037 } 2038 2039 /** 2040 * @see #setCallDataUsage(long) 2041 * 2042 * @param dataUsage The updated data usage (in byes). 2043 * @deprecated - Use {@link #setCallDataUsage(long)} instead. 2044 * @hide 2045 */ changeCallDataUsage(long dataUsage)2046 public void changeCallDataUsage(long dataUsage) { 2047 setCallDataUsage(dataUsage); 2048 } 2049 2050 /** 2051 * Used to inform listening {@link InCallService} implementations when the capabilities of 2052 * the current camera have changed. 2053 * <p> 2054 * The {@link VideoProvider} should call this in response to 2055 * {@link VideoProvider#onRequestCameraCapabilities()}, or when the current camera is 2056 * changed via {@link VideoProvider#onSetCamera(String)}. 2057 * <p> 2058 * Received by the {@link InCallService} via 2059 * {@link InCallService.VideoCall.Callback#onCameraCapabilitiesChanged( 2060 * VideoProfile.CameraCapabilities)}. 2061 * 2062 * @param cameraCapabilities The new camera capabilities. 2063 */ changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities)2064 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) { 2065 if (mVideoCallbacks != null) { 2066 for (IVideoCallback callback : mVideoCallbacks.values()) { 2067 try { 2068 callback.changeCameraCapabilities(cameraCapabilities); 2069 } catch (RemoteException ignored) { 2070 Log.w(this, "changeCameraCapabilities callback failed", ignored); 2071 } 2072 } 2073 } 2074 } 2075 2076 /** 2077 * Used to inform listening {@link InCallService} implementations when the video quality 2078 * of the call has changed. 2079 * <p> 2080 * Received by the {@link InCallService} via 2081 * {@link InCallService.VideoCall.Callback#onVideoQualityChanged(int)}. 2082 * 2083 * @param videoQuality The updated video quality. Valid values: 2084 * {@link VideoProfile#QUALITY_HIGH}, 2085 * {@link VideoProfile#QUALITY_MEDIUM}, 2086 * {@link VideoProfile#QUALITY_LOW}, 2087 * {@link VideoProfile#QUALITY_DEFAULT}. 2088 */ changeVideoQuality(int videoQuality)2089 public void changeVideoQuality(int videoQuality) { 2090 if (mVideoCallbacks != null) { 2091 for (IVideoCallback callback : mVideoCallbacks.values()) { 2092 try { 2093 callback.changeVideoQuality(videoQuality); 2094 } catch (RemoteException ignored) { 2095 Log.w(this, "changeVideoQuality callback failed", ignored); 2096 } 2097 } 2098 } 2099 } 2100 2101 /** 2102 * Returns a string representation of a call session event. 2103 * 2104 * @param event A call session event passed to {@link #handleCallSessionEvent(int)}. 2105 * @return String representation of the call session event. 2106 * @hide 2107 */ sessionEventToString(int event)2108 public static String sessionEventToString(int event) { 2109 switch (event) { 2110 case SESSION_EVENT_CAMERA_FAILURE: 2111 return SESSION_EVENT_CAMERA_FAILURE_STR; 2112 case SESSION_EVENT_CAMERA_READY: 2113 return SESSION_EVENT_CAMERA_READY_STR; 2114 case SESSION_EVENT_RX_PAUSE: 2115 return SESSION_EVENT_RX_PAUSE_STR; 2116 case SESSION_EVENT_RX_RESUME: 2117 return SESSION_EVENT_RX_RESUME_STR; 2118 case SESSION_EVENT_TX_START: 2119 return SESSION_EVENT_TX_START_STR; 2120 case SESSION_EVENT_TX_STOP: 2121 return SESSION_EVENT_TX_STOP_STR; 2122 case SESSION_EVENT_CAMERA_PERMISSION_ERROR: 2123 return SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR; 2124 default: 2125 return SESSION_EVENT_UNKNOWN_STR + " " + event; 2126 } 2127 } 2128 } 2129 2130 private final Listener mConnectionDeathListener = new Listener() { 2131 @Override 2132 public void onDestroyed(Connection c) { 2133 if (mConferenceables.remove(c)) { 2134 fireOnConferenceableConnectionsChanged(); 2135 } 2136 } 2137 }; 2138 2139 private final Conference.Listener mConferenceDeathListener = new Conference.Listener() { 2140 @Override 2141 public void onDestroyed(Conference c) { 2142 if (mConferenceables.remove(c)) { 2143 fireOnConferenceableConnectionsChanged(); 2144 } 2145 } 2146 }; 2147 2148 /** 2149 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 2150 * load factor before resizing, 1 means we only expect a single thread to 2151 * access the map so make only a single shard 2152 */ 2153 private final Set<Listener> mListeners = Collections.newSetFromMap( 2154 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 2155 private final List<Conferenceable> mConferenceables = new ArrayList<>(); 2156 private final List<Conferenceable> mUnmodifiableConferenceables = 2157 Collections.unmodifiableList(mConferenceables); 2158 2159 // The internal telecom call ID associated with this connection. 2160 private String mTelecomCallId; 2161 // The PhoneAccountHandle associated with this connection. 2162 private PhoneAccountHandle mPhoneAccountHandle; 2163 private int mState = STATE_NEW; 2164 private CallAudioState mCallAudioState; 2165 private CallEndpoint mCallEndpoint; 2166 private Uri mAddress; 2167 private int mAddressPresentation; 2168 private String mCallerDisplayName; 2169 private int mCallerDisplayNamePresentation; 2170 private boolean mRingbackRequested = false; 2171 private int mConnectionCapabilities; 2172 private int mConnectionProperties; 2173 private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; 2174 private VideoProvider mVideoProvider; 2175 private boolean mAudioModeIsVoip; 2176 private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; 2177 private long mConnectElapsedTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; 2178 private StatusHints mStatusHints; 2179 private int mVideoState; 2180 private DisconnectCause mDisconnectCause; 2181 private Conference mConference; 2182 private ConnectionService mConnectionService; 2183 private Bundle mExtras; 2184 private final Object mExtrasLock = new Object(); 2185 /** 2186 * The direction of the connection; used where an existing connection is created and we need to 2187 * communicate to Telecom whether its incoming or outgoing. 2188 */ 2189 private @Call.Details.CallDirection int mCallDirection = Call.Details.DIRECTION_UNKNOWN; 2190 2191 /** 2192 * Tracks the key set for the extras bundle provided on the last invocation of 2193 * {@link #setExtras(Bundle)}. Used so that on subsequent invocations we can remove any extras 2194 * keys which were set previously but are no longer present in the replacement Bundle. 2195 */ 2196 private Set<String> mPreviousExtraKeys; 2197 2198 /** 2199 * The verification status for an incoming call's phone number. 2200 */ 2201 private @VerificationStatus int mCallerNumberVerificationStatus; 2202 2203 2204 /** 2205 * Create a new Connection. 2206 */ Connection()2207 public Connection() {} 2208 2209 /** 2210 * Returns the Telecom internal call ID associated with this connection. Should only be used 2211 * for debugging and tracing purposes. 2212 * <p> 2213 * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is 2214 * provided to facilitate debugging of the Telephony stack only. 2215 * 2216 * @return The Telecom call ID, or {@code null} if it was not set. 2217 * @hide 2218 */ 2219 @SystemApi getTelecomCallId()2220 public final @Nullable String getTelecomCallId() { 2221 return mTelecomCallId; 2222 } 2223 2224 /** 2225 * @return The address (e.g., phone number) to which this Connection is currently communicating. 2226 */ getAddress()2227 public final Uri getAddress() { 2228 return mAddress; 2229 } 2230 2231 /** 2232 * @return The presentation requirements for the address. 2233 * See {@link TelecomManager} for valid values. 2234 */ getAddressPresentation()2235 public final int getAddressPresentation() { 2236 return mAddressPresentation; 2237 } 2238 2239 /** 2240 * @return The caller display name (CNAP). 2241 */ getCallerDisplayName()2242 public final String getCallerDisplayName() { 2243 return mCallerDisplayName; 2244 } 2245 2246 /** 2247 * @return The presentation requirements for the handle. 2248 * See {@link TelecomManager} for valid values. 2249 */ getCallerDisplayNamePresentation()2250 public final int getCallerDisplayNamePresentation() { 2251 return mCallerDisplayNamePresentation; 2252 } 2253 2254 /** 2255 * @return The state of this Connection. 2256 */ getState()2257 public final int getState() { 2258 return mState; 2259 } 2260 2261 /** 2262 * Returns the video state of the connection. 2263 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 2264 * {@link VideoProfile#STATE_BIDIRECTIONAL}, 2265 * {@link VideoProfile#STATE_TX_ENABLED}, 2266 * {@link VideoProfile#STATE_RX_ENABLED}. 2267 * 2268 * @return The video state of the connection. 2269 */ getVideoState()2270 public final @VideoProfile.VideoState int getVideoState() { 2271 return mVideoState; 2272 } 2273 2274 /** 2275 * @return The audio state of the connection, describing how its audio is currently 2276 * being routed by the system. This is {@code null} if this Connection 2277 * does not directly know about its audio state. 2278 * @deprecated Use {@link #getCallAudioState()} instead. 2279 * @hide 2280 */ 2281 @SystemApi 2282 @Deprecated getAudioState()2283 public final AudioState getAudioState() { 2284 if (mCallAudioState == null) { 2285 return null; 2286 } 2287 return new AudioState(mCallAudioState); 2288 } 2289 2290 /** 2291 * @return The audio state of the connection, describing how its audio is currently 2292 * being routed by the system. This is {@code null} if this Connection 2293 * does not directly know about its audio state. 2294 * @deprecated Use {@link #getCurrentCallEndpoint()}, 2295 * {@link #onAvailableCallEndpointsChanged(List)} and 2296 * {@link #onMuteStateChanged(boolean)} instead. 2297 */ 2298 @Deprecated getCallAudioState()2299 public final CallAudioState getCallAudioState() { 2300 return mCallAudioState; 2301 } 2302 2303 /** 2304 * @return The conference that this connection is a part of. Null if it is not part of any 2305 * conference. 2306 */ getConference()2307 public final Conference getConference() { 2308 return mConference; 2309 } 2310 2311 /** 2312 * Returns whether this connection is requesting that the system play a ringback tone 2313 * on its behalf. 2314 */ isRingbackRequested()2315 public final boolean isRingbackRequested() { 2316 return mRingbackRequested; 2317 } 2318 2319 /** 2320 * @return True if the connection's audio mode is VOIP. 2321 */ getAudioModeIsVoip()2322 public final boolean getAudioModeIsVoip() { 2323 return mAudioModeIsVoip; 2324 } 2325 2326 /** 2327 * Retrieves the connection start time of the {@code Connnection}, if specified. A value of 2328 * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the 2329 * start time of the conference. 2330 * <p> 2331 * Note: This is an implementation detail specific to IMS conference calls over a mobile 2332 * network. 2333 * 2334 * @return The time at which the {@code Connnection} was connected. Will be a value as retrieved 2335 * from {@link System#currentTimeMillis()}. 2336 * 2337 * @hide 2338 */ 2339 @SystemApi getConnectTimeMillis()2340 public final @IntRange(from = 0) long getConnectTimeMillis() { 2341 return mConnectTimeMillis; 2342 } 2343 2344 /** 2345 * Retrieves the connection start time of the {@link Connection}, if specified. A value of 2346 * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the 2347 * start time of the connection. 2348 * <p> 2349 * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock 2350 * changes do not impact the call duration. 2351 * <p> 2352 * Used internally in Telephony when migrating conference participant data for IMS conferences. 2353 * <p> 2354 * The value returned is the same one set using 2355 * {@link #setConnectionStartElapsedRealtimeMillis(long)}. This value is never updated from 2356 * the Telecom framework, so no permission enforcement occurs when retrieving the value with 2357 * this method. 2358 * 2359 * @return The time at which the {@link Connection} was connected. 2360 * 2361 * @hide 2362 */ 2363 @SystemApi getConnectionStartElapsedRealtimeMillis()2364 public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() { 2365 return mConnectElapsedTimeMillis; 2366 } 2367 2368 /** 2369 * @return The status hints for this connection. 2370 */ getStatusHints()2371 public final StatusHints getStatusHints() { 2372 return mStatusHints; 2373 } 2374 2375 /** 2376 * Returns the extras associated with this connection. 2377 * <p> 2378 * Extras should be updated using {@link #putExtras(Bundle)}. 2379 * <p> 2380 * Telecom or an {@link InCallService} can also update the extras via 2381 * {@link android.telecom.Call#putExtras(Bundle)}, and 2382 * {@link Call#removeExtras(List)}. 2383 * <p> 2384 * The connection is notified of changes to the extras made by Telecom or an 2385 * {@link InCallService} by {@link #onExtrasChanged(Bundle)}. 2386 * 2387 * @return The extras associated with this connection. 2388 */ getExtras()2389 public final Bundle getExtras() { 2390 Bundle extras = null; 2391 synchronized (mExtrasLock) { 2392 if (mExtras != null) { 2393 extras = new Bundle(mExtras); 2394 } 2395 } 2396 return extras; 2397 } 2398 2399 /** 2400 * Assign a listener to be notified of state changes. 2401 * 2402 * @param l A listener. 2403 * @return This Connection. 2404 * 2405 * @hide 2406 */ addConnectionListener(Listener l)2407 final Connection addConnectionListener(Listener l) { 2408 mListeners.add(l); 2409 return this; 2410 } 2411 2412 /** 2413 * Remove a previously assigned listener that was being notified of state changes. 2414 * 2415 * @param l A Listener. 2416 * @return This Connection. 2417 * 2418 * @hide 2419 */ removeConnectionListener(Listener l)2420 final Connection removeConnectionListener(Listener l) { 2421 if (l != null) { 2422 mListeners.remove(l); 2423 } 2424 return this; 2425 } 2426 2427 /** 2428 * @return The {@link DisconnectCause} for this connection. 2429 */ getDisconnectCause()2430 public final DisconnectCause getDisconnectCause() { 2431 return mDisconnectCause; 2432 } 2433 2434 /** 2435 * Sets the telecom call ID associated with this Connection. The Telecom Call ID should be used 2436 * ONLY for debugging purposes. 2437 * <p> 2438 * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is 2439 * provided to facilitate debugging of the Telephony stack only. Changing the ID via this 2440 * method does NOT change any functionality in Telephony or Telecom and impacts only logging. 2441 * 2442 * @param callId The telecom call ID. 2443 * @hide 2444 */ 2445 @SystemApi setTelecomCallId(@onNull String callId)2446 public void setTelecomCallId(@NonNull String callId) { 2447 mTelecomCallId = callId; 2448 } 2449 2450 /** 2451 * Inform this Connection that the state of its audio output has been changed externally. 2452 * 2453 * @param state The new audio state. 2454 * @hide 2455 */ setCallAudioState(CallAudioState state)2456 final void setCallAudioState(CallAudioState state) { 2457 checkImmutable(); 2458 Log.d(this, "setAudioState %s", state); 2459 mCallAudioState = state; 2460 onAudioStateChanged(getAudioState()); 2461 onCallAudioStateChanged(state); 2462 } 2463 2464 /** 2465 * Inform this Connection that the audio endpoint has been changed. 2466 * 2467 * @param endpoint The new call endpoint. 2468 * @hide 2469 */ setCallEndpoint(CallEndpoint endpoint)2470 final void setCallEndpoint(CallEndpoint endpoint) { 2471 checkImmutable(); 2472 Log.d(this, "setCallEndpoint %s", endpoint); 2473 mCallEndpoint = endpoint; 2474 onCallEndpointChanged(endpoint); 2475 } 2476 2477 /** 2478 * Inform this Connection that the available call endpoints have been changed. 2479 * 2480 * @param availableEndpoints The available call endpoints. 2481 * @hide 2482 */ setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints)2483 final void setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints) { 2484 checkImmutable(); 2485 Log.d(this, "setAvailableCallEndpoints"); 2486 onAvailableCallEndpointsChanged(availableEndpoints); 2487 } 2488 2489 /** 2490 * Inform this Connection that its audio mute state has been changed. 2491 * 2492 * @param isMuted The new mute state. 2493 * @hide 2494 */ setMuteState(boolean isMuted)2495 final void setMuteState(boolean isMuted) { 2496 checkImmutable(); 2497 Log.d(this, "setMuteState %s", isMuted); 2498 onMuteStateChanged(isMuted); 2499 } 2500 2501 /** 2502 * @param state An integer value of a {@code STATE_*} constant. 2503 * @return A string representation of the value. 2504 */ stateToString(int state)2505 public static String stateToString(int state) { 2506 switch (state) { 2507 case STATE_INITIALIZING: 2508 return "INITIALIZING"; 2509 case STATE_NEW: 2510 return "NEW"; 2511 case STATE_RINGING: 2512 return "RINGING"; 2513 case STATE_DIALING: 2514 return "DIALING"; 2515 case STATE_PULLING_CALL: 2516 return "PULLING_CALL"; 2517 case STATE_ACTIVE: 2518 return "ACTIVE"; 2519 case STATE_HOLDING: 2520 return "HOLDING"; 2521 case STATE_DISCONNECTED: 2522 return "DISCONNECTED"; 2523 default: 2524 Log.wtf(Connection.class, "Unknown state %d", state); 2525 return "UNKNOWN"; 2526 } 2527 } 2528 2529 /** 2530 * Returns the connection's capabilities, as a bit mask of the {@code CAPABILITY_*} constants. 2531 */ getConnectionCapabilities()2532 public final int getConnectionCapabilities() { 2533 return mConnectionCapabilities; 2534 } 2535 2536 /** 2537 * Returns the connection's properties, as a bit mask of the {@code PROPERTY_*} constants. 2538 */ getConnectionProperties()2539 public final int getConnectionProperties() { 2540 return mConnectionProperties; 2541 } 2542 2543 /** 2544 * Returns the connection's supported audio routes. 2545 * 2546 * @hide 2547 */ getSupportedAudioRoutes()2548 public final int getSupportedAudioRoutes() { 2549 return mSupportedAudioRoutes; 2550 } 2551 2552 /** 2553 * Sets the value of the {@link #getAddress()} property. 2554 * 2555 * @param address The new address. 2556 * @param presentation The presentation requirements for the address. 2557 * See {@link TelecomManager} for valid values. 2558 */ setAddress(Uri address, int presentation)2559 public final void setAddress(Uri address, int presentation) { 2560 Log.d(this, "setAddress %s", address); 2561 mAddress = address; 2562 mAddressPresentation = presentation; 2563 for (Listener l : mListeners) { 2564 l.onAddressChanged(this, address, presentation); 2565 } 2566 } 2567 2568 /** 2569 * Sets the caller display name (CNAP). 2570 * 2571 * @param callerDisplayName The new display name. 2572 * @param presentation The presentation requirements for the handle. 2573 * See {@link TelecomManager} for valid values. 2574 */ setCallerDisplayName(String callerDisplayName, int presentation)2575 public final void setCallerDisplayName(String callerDisplayName, int presentation) { 2576 checkImmutable(); 2577 boolean nameChanged = !Objects.equals(mCallerDisplayName, callerDisplayName); 2578 boolean presentationChanged = mCallerDisplayNamePresentation != presentation; 2579 if (nameChanged) { 2580 // Ensure the new name is not clobbering the old one with a null value due to the caller 2581 // wanting to only set the presentation and not knowing the display name. 2582 mCallerDisplayName = callerDisplayName; 2583 } 2584 if (presentationChanged) { 2585 mCallerDisplayNamePresentation = presentation; 2586 } 2587 if (nameChanged || presentationChanged) { 2588 for (Listener l : mListeners) { 2589 l.onCallerDisplayNameChanged(this, mCallerDisplayName, 2590 mCallerDisplayNamePresentation); 2591 } 2592 } 2593 } 2594 2595 /** 2596 * Set the video state for the connection. 2597 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 2598 * {@link VideoProfile#STATE_BIDIRECTIONAL}, 2599 * {@link VideoProfile#STATE_TX_ENABLED}, 2600 * {@link VideoProfile#STATE_RX_ENABLED}. 2601 * 2602 * @param videoState The new video state. 2603 */ setVideoState(int videoState)2604 public final void setVideoState(int videoState) { 2605 checkImmutable(); 2606 Log.d(this, "setVideoState %d", videoState); 2607 mVideoState = videoState; 2608 for (Listener l : mListeners) { 2609 l.onVideoStateChanged(this, mVideoState); 2610 } 2611 } 2612 2613 /** 2614 * Sets state to active (e.g., an ongoing connection where two or more parties can actively 2615 * communicate). 2616 */ setActive()2617 public final void setActive() { 2618 checkImmutable(); 2619 setRingbackRequested(false); 2620 setState(STATE_ACTIVE); 2621 } 2622 2623 /** 2624 * Sets state to ringing (e.g., an inbound ringing connection). 2625 */ setRinging()2626 public final void setRinging() { 2627 checkImmutable(); 2628 setState(STATE_RINGING); 2629 } 2630 2631 /** 2632 * Sets state to initializing (this Connection is not yet ready to be used). 2633 */ setInitializing()2634 public final void setInitializing() { 2635 checkImmutable(); 2636 setState(STATE_INITIALIZING); 2637 } 2638 2639 /** 2640 * Sets state to initialized (the Connection has been set up and is now ready to be used). 2641 */ setInitialized()2642 public final void setInitialized() { 2643 checkImmutable(); 2644 setState(STATE_NEW); 2645 } 2646 2647 /** 2648 * Sets state to dialing (e.g., dialing an outbound connection). 2649 */ setDialing()2650 public final void setDialing() { 2651 checkImmutable(); 2652 setState(STATE_DIALING); 2653 } 2654 2655 /** 2656 * Sets state to pulling (e.g. the connection is being pulled to the local device from another 2657 * device). Only applicable for {@link Connection}s with 2658 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} and {@link Connection#CAPABILITY_CAN_PULL_CALL}. 2659 */ setPulling()2660 public final void setPulling() { 2661 checkImmutable(); 2662 setState(STATE_PULLING_CALL); 2663 } 2664 2665 /** 2666 * Sets state to be on hold. 2667 */ setOnHold()2668 public final void setOnHold() { 2669 checkImmutable(); 2670 setState(STATE_HOLDING); 2671 } 2672 2673 /** 2674 * Sets the video connection provider. 2675 * @param videoProvider The video provider. 2676 */ setVideoProvider(VideoProvider videoProvider)2677 public final void setVideoProvider(VideoProvider videoProvider) { 2678 checkImmutable(); 2679 mVideoProvider = videoProvider; 2680 for (Listener l : mListeners) { 2681 l.onVideoProviderChanged(this, videoProvider); 2682 } 2683 } 2684 getVideoProvider()2685 public final VideoProvider getVideoProvider() { 2686 return mVideoProvider; 2687 } 2688 2689 /** 2690 * Sets state to disconnected. 2691 * 2692 * @param disconnectCause The reason for the disconnection, as specified by 2693 * {@link DisconnectCause}. 2694 */ setDisconnected(DisconnectCause disconnectCause)2695 public final void setDisconnected(DisconnectCause disconnectCause) { 2696 checkImmutable(); 2697 mDisconnectCause = disconnectCause; 2698 setState(STATE_DISCONNECTED); 2699 Log.d(this, "Disconnected with cause %s", disconnectCause); 2700 for (Listener l : mListeners) { 2701 l.onDisconnected(this, disconnectCause); 2702 } 2703 } 2704 2705 /** 2706 * Informs listeners that this {@code Connection} is in a post-dial wait state. This is done 2707 * when (a) the {@code Connection} is issuing a DTMF sequence; (b) it has encountered a "wait" 2708 * character; and (c) it wishes to inform the In-Call app that it is waiting for the end-user 2709 * to send an {@link #onPostDialContinue(boolean)} signal. 2710 * 2711 * @param remaining The DTMF character sequence remaining to be emitted once the 2712 * {@link #onPostDialContinue(boolean)} is received, including any "wait" characters 2713 * that remaining sequence may contain. 2714 */ setPostDialWait(String remaining)2715 public final void setPostDialWait(String remaining) { 2716 checkImmutable(); 2717 for (Listener l : mListeners) { 2718 l.onPostDialWait(this, remaining); 2719 } 2720 } 2721 2722 /** 2723 * Informs listeners that this {@code Connection} has processed a character in the post-dial 2724 * started state. This is done when (a) the {@code Connection} is issuing a DTMF sequence; 2725 * and (b) it wishes to signal Telecom to play the corresponding DTMF tone locally. 2726 * 2727 * @param nextChar The DTMF character that was just processed by the {@code Connection}. 2728 */ setNextPostDialChar(char nextChar)2729 public final void setNextPostDialChar(char nextChar) { 2730 checkImmutable(); 2731 for (Listener l : mListeners) { 2732 l.onPostDialChar(this, nextChar); 2733 } 2734 } 2735 2736 /** 2737 * Requests that the framework play a ringback tone. This is to be invoked by implementations 2738 * that do not play a ringback tone themselves in the connection's audio stream. 2739 * 2740 * @param ringback Whether the ringback tone is to be played. 2741 */ setRingbackRequested(boolean ringback)2742 public final void setRingbackRequested(boolean ringback) { 2743 checkImmutable(); 2744 if (mRingbackRequested != ringback) { 2745 mRingbackRequested = ringback; 2746 for (Listener l : mListeners) { 2747 l.onRingbackRequested(this, ringback); 2748 } 2749 } 2750 } 2751 2752 /** 2753 * Sets the connection's capabilities as a bit mask of the {@code CAPABILITY_*} constants. 2754 * 2755 * @param connectionCapabilities The new connection capabilities. 2756 */ setConnectionCapabilities(int connectionCapabilities)2757 public final void setConnectionCapabilities(int connectionCapabilities) { 2758 checkImmutable(); 2759 if (mConnectionCapabilities != connectionCapabilities) { 2760 mConnectionCapabilities = connectionCapabilities; 2761 for (Listener l : mListeners) { 2762 l.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); 2763 } 2764 } 2765 } 2766 2767 /** 2768 * Sets the connection's properties as a bit mask of the {@code PROPERTY_*} constants. 2769 * 2770 * @param connectionProperties The new connection properties. 2771 */ setConnectionProperties(int connectionProperties)2772 public final void setConnectionProperties(int connectionProperties) { 2773 checkImmutable(); 2774 if (mConnectionProperties != connectionProperties) { 2775 mConnectionProperties = connectionProperties; 2776 for (Listener l : mListeners) { 2777 l.onConnectionPropertiesChanged(this, mConnectionProperties); 2778 } 2779 } 2780 } 2781 2782 /** 2783 * Sets the supported audio routes. 2784 * 2785 * @param supportedAudioRoutes the supported audio routes as a bitmask. 2786 * See {@link CallAudioState} 2787 * @hide 2788 */ setSupportedAudioRoutes(int supportedAudioRoutes)2789 public final void setSupportedAudioRoutes(int supportedAudioRoutes) { 2790 if ((supportedAudioRoutes 2791 & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER)) == 0) { 2792 throw new IllegalArgumentException( 2793 "supported audio routes must include either speaker or earpiece"); 2794 } 2795 2796 if (mSupportedAudioRoutes != supportedAudioRoutes) { 2797 mSupportedAudioRoutes = supportedAudioRoutes; 2798 for (Listener l : mListeners) { 2799 l.onSupportedAudioRoutesChanged(this, mSupportedAudioRoutes); 2800 } 2801 } 2802 } 2803 2804 /** 2805 * Tears down the Connection object. 2806 */ destroy()2807 public final void destroy() { 2808 for (Listener l : mListeners) { 2809 l.onDestroyed(this); 2810 } 2811 } 2812 2813 /** 2814 * Requests that the framework use VOIP audio mode for this connection. 2815 * 2816 * @param isVoip True if the audio mode is VOIP. 2817 */ setAudioModeIsVoip(boolean isVoip)2818 public final void setAudioModeIsVoip(boolean isVoip) { 2819 if (!isVoip && (mConnectionProperties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) { 2820 Log.i(this, 2821 "setAudioModeIsVoip: Ignored request to set a self-managed connection's" 2822 + " audioModeIsVoip to false. Doing so can cause unwanted behavior."); 2823 return; 2824 } 2825 checkImmutable(); 2826 mAudioModeIsVoip = isVoip; 2827 for (Listener l : mListeners) { 2828 l.onAudioModeIsVoipChanged(this, isVoip); 2829 } 2830 } 2831 2832 /** 2833 * Sets the time at which a call became active on this Connection. This is set only 2834 * when a conference call becomes active on this connection. 2835 * <p> 2836 * This time corresponds to the date/time of connection and is stored in the call log in 2837 * {@link android.provider.CallLog.Calls#DATE}. 2838 * <p> 2839 * Used by telephony to maintain calls associated with an IMS Conference. 2840 * 2841 * @param connectTimeMillis The connection time, in milliseconds. Should be set using a value 2842 * obtained from {@link System#currentTimeMillis()}. 2843 * 2844 * @hide 2845 */ 2846 @SystemApi 2847 @RequiresPermission(MODIFY_PHONE_STATE) setConnectTimeMillis(@ntRangefrom = 0) long connectTimeMillis)2848 public final void setConnectTimeMillis(@IntRange(from = 0) long connectTimeMillis) { 2849 mConnectTimeMillis = connectTimeMillis; 2850 } 2851 2852 /** 2853 * Sets the time at which a call became active on this Connection. This is set only 2854 * when a conference call becomes active on this connection. 2855 * <p> 2856 * This time is used to establish the duration of a call. It uses 2857 * {@link SystemClock#elapsedRealtime()} to ensure that the call duration is not impacted by 2858 * time zone changes during a call. The difference between the current 2859 * {@link SystemClock#elapsedRealtime()} and the value set at the connection start time is used 2860 * to populate {@link android.provider.CallLog.Calls#DURATION} in the call log. 2861 * <p> 2862 * Used by telephony to maintain calls associated with an IMS Conference. 2863 * 2864 * @param connectElapsedTimeMillis The connection time, in milliseconds. Stored in the format 2865 * {@link SystemClock#elapsedRealtime()}. 2866 * @hide 2867 */ 2868 @SystemApi 2869 @RequiresPermission(MODIFY_PHONE_STATE) setConnectionStartElapsedRealtimeMillis( @lapsedRealtimeLong long connectElapsedTimeMillis)2870 public final void setConnectionStartElapsedRealtimeMillis( 2871 @ElapsedRealtimeLong long connectElapsedTimeMillis) { 2872 mConnectElapsedTimeMillis = connectElapsedTimeMillis; 2873 } 2874 2875 /** 2876 * Sets the label and icon status to display in the in-call UI. 2877 * 2878 * @param statusHints The status label and icon to set. 2879 */ setStatusHints(StatusHints statusHints)2880 public final void setStatusHints(StatusHints statusHints) { 2881 checkImmutable(); 2882 mStatusHints = statusHints; 2883 for (Listener l : mListeners) { 2884 l.onStatusHintsChanged(this, statusHints); 2885 } 2886 } 2887 2888 /** 2889 * Sets the connections with which this connection can be conferenced. 2890 * 2891 * @param conferenceableConnections The set of connections this connection can conference with. 2892 */ setConferenceableConnections(List<Connection> conferenceableConnections)2893 public final void setConferenceableConnections(List<Connection> conferenceableConnections) { 2894 checkImmutable(); 2895 clearConferenceableList(); 2896 for (Connection c : conferenceableConnections) { 2897 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 2898 // small amount of items here. 2899 if (!mConferenceables.contains(c)) { 2900 c.addConnectionListener(mConnectionDeathListener); 2901 mConferenceables.add(c); 2902 } 2903 } 2904 fireOnConferenceableConnectionsChanged(); 2905 } 2906 2907 /** 2908 * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections 2909 * or conferences with which this connection can be conferenced. 2910 * 2911 * @param conferenceables The conferenceables. 2912 */ setConferenceables(List<Conferenceable> conferenceables)2913 public final void setConferenceables(List<Conferenceable> conferenceables) { 2914 clearConferenceableList(); 2915 for (Conferenceable c : conferenceables) { 2916 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 2917 // small amount of items here. 2918 if (!mConferenceables.contains(c)) { 2919 if (c instanceof Connection) { 2920 Connection connection = (Connection) c; 2921 connection.addConnectionListener(mConnectionDeathListener); 2922 } else if (c instanceof Conference) { 2923 Conference conference = (Conference) c; 2924 conference.addListener(mConferenceDeathListener); 2925 } 2926 mConferenceables.add(c); 2927 } 2928 } 2929 fireOnConferenceableConnectionsChanged(); 2930 } 2931 2932 /** 2933 * Resets the CDMA connection time. 2934 * <p> 2935 * This is an implementation detail specific to legacy CDMA calls on mobile networks. 2936 * @hide 2937 */ 2938 @SystemApi resetConnectionTime()2939 public final void resetConnectionTime() { 2940 for (Listener l : mListeners) { 2941 l.onConnectionTimeReset(this); 2942 } 2943 } 2944 2945 /** 2946 * Returns the connections or conferences with which this connection can be conferenced. 2947 */ getConferenceables()2948 public final List<Conferenceable> getConferenceables() { 2949 return mUnmodifiableConferenceables; 2950 } 2951 2952 /** 2953 * @hide 2954 */ setConnectionService(ConnectionService connectionService)2955 public final void setConnectionService(ConnectionService connectionService) { 2956 checkImmutable(); 2957 if (mConnectionService != null) { 2958 Log.e(this, new Exception(), "Trying to set ConnectionService on a connection " + 2959 "which is already associated with another ConnectionService."); 2960 } else { 2961 mConnectionService = connectionService; 2962 } 2963 } 2964 2965 /** 2966 * @hide 2967 */ unsetConnectionService(ConnectionService connectionService)2968 public final void unsetConnectionService(ConnectionService connectionService) { 2969 if (mConnectionService != connectionService) { 2970 Log.e(this, new Exception(), "Trying to remove ConnectionService from a Connection " + 2971 "that does not belong to the ConnectionService."); 2972 } else { 2973 mConnectionService = null; 2974 } 2975 } 2976 2977 /** 2978 * Sets the conference that this connection is a part of. This will fail if the connection is 2979 * already part of a conference. {@link #resetConference} to un-set the conference first. 2980 * 2981 * @param conference The conference. 2982 * @return {@code true} if the conference was successfully set. 2983 * @hide 2984 */ setConference(Conference conference)2985 public final boolean setConference(Conference conference) { 2986 checkImmutable(); 2987 // We check to see if it is already part of another conference. 2988 if (mConference == null) { 2989 mConference = conference; 2990 if (mConnectionService != null && mConnectionService.containsConference(conference)) { 2991 fireConferenceChanged(); 2992 } 2993 return true; 2994 } 2995 return false; 2996 } 2997 2998 /** 2999 * Resets the conference that this connection is a part of. 3000 * @hide 3001 */ resetConference()3002 public final void resetConference() { 3003 if (mConference != null) { 3004 Log.d(this, "Conference reset"); 3005 mConference = null; 3006 fireConferenceChanged(); 3007 } 3008 } 3009 3010 /** 3011 * Set some extras that can be associated with this {@code Connection}. 3012 * <p> 3013 * New or existing keys are replaced in the {@code Connection} extras. Keys which are no longer 3014 * in the new extras, but were present the last time {@code setExtras} was called are removed. 3015 * <p> 3016 * Alternatively you may use the {@link #putExtras(Bundle)}, and 3017 * {@link #removeExtras(String...)} methods to modify the extras. 3018 * <p> 3019 * No assumptions should be made as to how an In-Call UI or service will handle these extras. 3020 * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts. 3021 * 3022 * @param extras The extras associated with this {@code Connection}. 3023 */ setExtras(@ullable Bundle extras)3024 public final void setExtras(@Nullable Bundle extras) { 3025 checkImmutable(); 3026 3027 // Add/replace any new or changed extras values. 3028 putExtras(extras); 3029 3030 // If we have used "setExtras" in the past, compare the key set from the last invocation to 3031 // the current one and remove any keys that went away. 3032 if (mPreviousExtraKeys != null) { 3033 List<String> toRemove = new ArrayList<String>(); 3034 for (String oldKey : mPreviousExtraKeys) { 3035 if (extras == null || !extras.containsKey(oldKey)) { 3036 toRemove.add(oldKey); 3037 } 3038 } 3039 if (!toRemove.isEmpty()) { 3040 removeExtras(toRemove); 3041 } 3042 } 3043 3044 // Track the keys the last time set called setExtras. This way, the next time setExtras is 3045 // called we can see if the caller has removed any extras values. 3046 if (mPreviousExtraKeys == null) { 3047 mPreviousExtraKeys = new ArraySet<String>(); 3048 } 3049 mPreviousExtraKeys.clear(); 3050 if (extras != null) { 3051 mPreviousExtraKeys.addAll(extras.keySet()); 3052 } 3053 } 3054 3055 /** 3056 * Adds some extras to this {@code Connection}. Existing keys are replaced and new ones are 3057 * added. 3058 * <p> 3059 * No assumptions should be made as to how an In-Call UI or service will handle these extras. 3060 * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts. 3061 * 3062 * @param extras The extras to add. 3063 */ putExtras(@onNull Bundle extras)3064 public final void putExtras(@NonNull Bundle extras) { 3065 checkImmutable(); 3066 if (extras == null) { 3067 return; 3068 } 3069 // Creating a duplicate bundle so we don't have to synchronize on mExtrasLock while calling 3070 // the listeners. 3071 Bundle listenerExtras; 3072 synchronized (mExtrasLock) { 3073 if (mExtras == null) { 3074 mExtras = new Bundle(); 3075 } 3076 mExtras.putAll(extras); 3077 listenerExtras = new Bundle(mExtras); 3078 } 3079 for (Listener l : mListeners) { 3080 // Create a new clone of the extras for each listener so that they don't clobber 3081 // each other 3082 l.onExtrasChanged(this, new Bundle(listenerExtras)); 3083 } 3084 } 3085 3086 /** 3087 * Removes extras from this {@code Connection}. 3088 * 3089 * @param keys The keys of the extras to remove. 3090 */ removeExtras(List<String> keys)3091 public final void removeExtras(List<String> keys) { 3092 synchronized (mExtrasLock) { 3093 if (mExtras != null) { 3094 for (String key : keys) { 3095 mExtras.remove(key); 3096 } 3097 } 3098 } 3099 List<String> unmodifiableKeys = Collections.unmodifiableList(keys); 3100 for (Listener l : mListeners) { 3101 l.onExtrasRemoved(this, unmodifiableKeys); 3102 } 3103 } 3104 3105 /** 3106 * Removes extras from this {@code Connection}. 3107 * 3108 * @param keys The keys of the extras to remove. 3109 */ removeExtras(String .... keys)3110 public final void removeExtras(String ... keys) { 3111 removeExtras(Arrays.asList(keys)); 3112 } 3113 3114 /** 3115 * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will 3116 * be change to the {@link #getCallAudioState()}. 3117 * <p> 3118 * Used by self-managed {@link ConnectionService}s which wish to change the audio route for a 3119 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3120 * <p> 3121 * See also {@link InCallService#setAudioRoute(int)}. 3122 * 3123 * @param route The audio route to use (one of {@link CallAudioState#ROUTE_BLUETOOTH}, 3124 * {@link CallAudioState#ROUTE_EARPIECE}, {@link CallAudioState#ROUTE_SPEAKER}, or 3125 * {@link CallAudioState#ROUTE_WIRED_HEADSET}). 3126 * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)} 3127 * instead. 3128 */ 3129 @Deprecated setAudioRoute(int route)3130 public final void setAudioRoute(int route) { 3131 for (Listener l : mListeners) { 3132 l.onAudioRouteChanged(this, route, null); 3133 } 3134 } 3135 3136 /** 3137 * Request audio routing to a specific bluetooth device. Calling this method may result in 3138 * the device routing audio to a different bluetooth device than the one specified if the 3139 * bluetooth stack is unable to route audio to the requested device. 3140 * A list of available devices can be obtained via 3141 * {@link CallAudioState#getSupportedBluetoothDevices()} 3142 * 3143 * <p> 3144 * Used by self-managed {@link ConnectionService}s which wish to use bluetooth audio for a 3145 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3146 * <p> 3147 * See also {@link InCallService#requestBluetoothAudio(BluetoothDevice)} 3148 * @param bluetoothDevice The bluetooth device to connect to. 3149 * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)} 3150 * instead. 3151 */ 3152 @Deprecated requestBluetoothAudio(@onNull BluetoothDevice bluetoothDevice)3153 public void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) { 3154 for (Listener l : mListeners) { 3155 l.onAudioRouteChanged(this, CallAudioState.ROUTE_BLUETOOTH, 3156 bluetoothDevice.getAddress()); 3157 } 3158 } 3159 3160 /** 3161 * Request audio routing to a specific CallEndpoint. Clients should not define their own 3162 * CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid 3163 * endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}. 3164 * When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}. 3165 * <p> 3166 * Used by self-managed {@link ConnectionService}s which wish to change the CallEndpoint for a 3167 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3168 * <p> 3169 * See also 3170 * {@link InCallService#requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}. 3171 * 3172 * @param endpoint The call endpoint to use. 3173 * @param executor The executor of where the callback will execute. 3174 * @param callback The callback to notify the result of the endpoint change. 3175 */ requestCallEndpointChange(@onNull CallEndpoint endpoint, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, CallEndpointException> callback)3176 public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint, 3177 @NonNull @CallbackExecutor Executor executor, 3178 @NonNull OutcomeReceiver<Void, CallEndpointException> callback) { 3179 for (Listener l : mListeners) { 3180 l.onEndpointChanged(this, endpoint, executor, callback); 3181 } 3182 } 3183 3184 /** 3185 * Obtains the current CallEndpoint. 3186 * 3187 * @return An object encapsulating the CallEndpoint. 3188 */ 3189 @NonNull getCurrentCallEndpoint()3190 public final CallEndpoint getCurrentCallEndpoint() { 3191 return mCallEndpoint; 3192 } 3193 3194 /** 3195 * Informs listeners that a previously requested RTT session via 3196 * {@link ConnectionRequest#isRequestingRtt()} or 3197 * {@link #onStartRtt(RttTextStream)} has succeeded. 3198 */ sendRttInitiationSuccess()3199 public final void sendRttInitiationSuccess() { 3200 mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this)); 3201 } 3202 3203 /** 3204 * Informs listeners that a previously requested RTT session via 3205 * {@link ConnectionRequest#isRequestingRtt()} or {@link #onStartRtt(RttTextStream)} 3206 * has failed. 3207 * @param reason One of the reason codes defined in {@link RttModifyStatus}, with the 3208 * exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. 3209 */ sendRttInitiationFailure(int reason)3210 public final void sendRttInitiationFailure(int reason) { 3211 mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason)); 3212 } 3213 3214 /** 3215 * Informs listeners that a currently active RTT session has been terminated by the remote 3216 * side of the coll. 3217 */ sendRttSessionRemotelyTerminated()3218 public final void sendRttSessionRemotelyTerminated() { 3219 mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this)); 3220 } 3221 3222 /** 3223 * Informs listeners that the remote side of the call has requested an upgrade to include an 3224 * RTT session in the call. 3225 */ sendRemoteRttRequest()3226 public final void sendRemoteRttRequest() { 3227 mListeners.forEach((l) -> l.onRemoteRttRequest(Connection.this)); 3228 } 3229 3230 /** 3231 * Query the device's location in order to place an Emergency Call. 3232 * Only SIM call managers can call this method for Connections representing Emergency calls. 3233 * If a previous location query request is not completed, the new location query request will 3234 * be rejected and return a QueryLocationException with 3235 * {@code QueryLocationException#ERROR_PREVIOUS_REQUEST_EXISTS} 3236 * 3237 * @param timeoutMillis long: Timeout in millis waiting for query response (MAX:5000, MIN:100). 3238 * @param provider String: the location provider name, This value cannot be null. 3239 * It is the caller's responsibility to select an enabled provider. The caller 3240 * can use {@link android.location.LocationManager#getProviders(boolean)} 3241 * to choose one of the enabled providers and pass it in. 3242 * @param executor The executor of where the callback will execute. 3243 * @param callback The callback to notify the result of queryLocation. 3244 */ queryLocationForEmergency( @ntRangefrom = 100, to = 5000) long timeoutMillis, @NonNull String provider, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Location, QueryLocationException> callback)3245 public final void queryLocationForEmergency( 3246 @IntRange(from = 100, to = 5000) long timeoutMillis, 3247 @NonNull String provider, 3248 @NonNull @CallbackExecutor Executor executor, 3249 @NonNull OutcomeReceiver<Location, QueryLocationException> callback) { 3250 if (provider == null || executor == null || callback == null) { 3251 throw new IllegalArgumentException("There are arguments that must not be null"); 3252 } 3253 if (timeoutMillis < 100 || timeoutMillis > 5000) { 3254 throw new IllegalArgumentException("The timeoutMillis should be min 100, max 5000"); 3255 } 3256 mListeners.forEach((l) -> 3257 l.onQueryLocation(this, timeoutMillis, provider, executor, callback)); 3258 } 3259 3260 /** 3261 * Notifies this Connection that the {@link #getAudioState()} property has a new value. 3262 * 3263 * @param state The new connection audio state. 3264 * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState)} instead. 3265 * @hide 3266 */ 3267 @SystemApi 3268 @Deprecated onAudioStateChanged(AudioState state)3269 public void onAudioStateChanged(AudioState state) {} 3270 3271 /** 3272 * Notifies this Connection that the {@link #getCallAudioState()} property has a new value. 3273 * 3274 * @param state The new connection audio state. 3275 * @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)}, 3276 * {@link #onAvailableCallEndpointsChanged(List)} and 3277 * {@link #onMuteStateChanged(boolean)} instead. 3278 */ 3279 @Deprecated onCallAudioStateChanged(CallAudioState state)3280 public void onCallAudioStateChanged(CallAudioState state) {} 3281 3282 /** 3283 * Notifies this Connection that the audio endpoint has been changed. 3284 * 3285 * @param callEndpoint The current CallEndpoint. 3286 */ onCallEndpointChanged(@onNull CallEndpoint callEndpoint)3287 public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {} 3288 3289 /** 3290 * Notifies this Connection that the available call endpoints have been changed. 3291 * 3292 * @param availableEndpoints The set of available CallEndpoint. 3293 */ onAvailableCallEndpointsChanged(@onNull List<CallEndpoint> availableEndpoints)3294 public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {} 3295 3296 /** 3297 * Notifies this Connection that its audio mute state has been changed. 3298 * 3299 * @param isMuted The current mute state. 3300 */ onMuteStateChanged(boolean isMuted)3301 public void onMuteStateChanged(boolean isMuted) {} 3302 3303 /** 3304 * Inform this Connection when it will or will not be tracked by an {@link InCallService} which 3305 * can provide an InCall UI. 3306 * This is primarily intended for use by Connections reported by self-managed 3307 * {@link ConnectionService} which typically maintain their own UI. 3308 * 3309 * @param isUsingAlternativeUi Indicates whether an InCallService that can provide InCall UI is 3310 * currently tracking the self-managed call. 3311 */ onUsingAlternativeUi(boolean isUsingAlternativeUi)3312 public void onUsingAlternativeUi(boolean isUsingAlternativeUi) {} 3313 3314 /** 3315 * Inform this Conenection when it will or will not be tracked by an non-UI 3316 * {@link InCallService}. 3317 * 3318 * @param isTracked Indicates whether an non-UI InCallService is currently tracking the 3319 * self-managed call. 3320 */ onTrackedByNonUiService(boolean isTracked)3321 public void onTrackedByNonUiService(boolean isTracked) {} 3322 3323 /** 3324 * Notifies this Connection of an internal state change. This method is called after the 3325 * state is changed. 3326 * 3327 * @param state The new state, one of the {@code STATE_*} constants. 3328 */ onStateChanged(int state)3329 public void onStateChanged(int state) {} 3330 3331 /** 3332 * Notifies this Connection of a request to play a DTMF tone. 3333 * 3334 * @param c A DTMF character. 3335 */ onPlayDtmfTone(char c)3336 public void onPlayDtmfTone(char c) {} 3337 3338 /** 3339 * Notifies this Connection of a request to stop any currently playing DTMF tones. 3340 */ onStopDtmfTone()3341 public void onStopDtmfTone() {} 3342 3343 /** 3344 * Notifies this Connection of a request to disconnect. 3345 */ onDisconnect()3346 public void onDisconnect() {} 3347 3348 /** 3349 * Notifies this Connection of a request to separate from its parent conference. 3350 */ onSeparate()3351 public void onSeparate() {} 3352 3353 /** 3354 * Supports initiation of a conference call by directly adding participants to an ongoing call. 3355 * 3356 * @param participants with which conference call will be formed. 3357 */ onAddConferenceParticipants(@onNull List<Uri> participants)3358 public void onAddConferenceParticipants(@NonNull List<Uri> participants) {} 3359 3360 /** 3361 * Notifies this Connection of a request to abort. 3362 */ onAbort()3363 public void onAbort() {} 3364 3365 /** 3366 * Notifies this Connection of a request to hold. {@link Connection#setOnHold} should be within 3367 * the onHold() body in order to transition the call state to {@link Connection#STATE_HOLDING}. 3368 * <p> 3369 * Note: If the Connection does not transition to {@link Connection#STATE_HOLDING} within 2 3370 * seconds, the call will be disconnected. 3371 */ onHold()3372 public void onHold() {} 3373 3374 /** 3375 * Notifies this Connection of a request to exit a hold state. 3376 */ onUnhold()3377 public void onUnhold() {} 3378 3379 /** 3380 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3381 * a request to accept. 3382 * <p> 3383 * For managed {@link ConnectionService}s, this will be called when the user answers a call via 3384 * the default dialer's {@link InCallService}. 3385 * <p> 3386 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3387 * Telecom framework may request that the call is answered in the following circumstances: 3388 * <ul> 3389 * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> 3390 * <li>A car mode {@link InCallService} is in use which has declared 3391 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3392 * {@link InCallService} will be able to see calls from self-managed 3393 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3394 * behalf.</li> 3395 * </ul> 3396 * @param videoState The video state in which to answer the connection. 3397 */ onAnswer(int videoState)3398 public void onAnswer(int videoState) {} 3399 3400 /** 3401 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3402 * a request to accept. 3403 * <p> 3404 * For managed {@link ConnectionService}s, this will be called when the user answers a call via 3405 * the default dialer's {@link InCallService}. 3406 * <p> 3407 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3408 * Telecom framework may request that the call is answered in the following circumstances: 3409 * <ul> 3410 * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> 3411 * <li>A car mode {@link InCallService} is in use which has declared 3412 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3413 * {@link InCallService} will be able to see calls from self-managed 3414 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3415 * behalf.</li> 3416 * </ul> 3417 */ onAnswer()3418 public void onAnswer() { 3419 onAnswer(VideoProfile.STATE_AUDIO_ONLY); 3420 } 3421 3422 /** 3423 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3424 * a request to deflect. 3425 */ onDeflect(Uri address)3426 public void onDeflect(Uri address) {} 3427 3428 /** 3429 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3430 * a request to reject. 3431 * <p> 3432 * For managed {@link ConnectionService}s, this will be called when the user rejects a call via 3433 * the default dialer's {@link InCallService}. 3434 * <p> 3435 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3436 * Telecom framework may request that the call is rejected in the following circumstances: 3437 * <ul> 3438 * <li>The user chooses to reject an incoming call via a Bluetooth device.</li> 3439 * <li>A car mode {@link InCallService} is in use which has declared 3440 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3441 * {@link InCallService} will be able to see calls from self-managed 3442 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3443 * behalf.</li> 3444 * </ul> 3445 */ onReject()3446 public void onReject() {} 3447 3448 /** 3449 * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject. 3450 * <p> 3451 * For managed {@link ConnectionService}s, this will be called when the user rejects a call via 3452 * the default dialer's {@link InCallService} using {@link Call#reject(int)}. 3453 * @param rejectReason the reason the user provided for rejecting the call. 3454 */ onReject(@ndroid.telecom.Call.RejectReason int rejectReason)3455 public void onReject(@android.telecom.Call.RejectReason int rejectReason) { 3456 // to be implemented by ConnectionService. 3457 } 3458 3459 /** 3460 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3461 * a request to reject with a message. 3462 */ onReject(String replyMessage)3463 public void onReject(String replyMessage) {} 3464 3465 /** 3466 * Notifies this Connection, a request to transfer to a target number. 3467 * @param number the number to transfer this {@link Connection} to. 3468 * @param isConfirmationRequired when {@code true}, the {@link ConnectionService} 3469 * should wait until the transfer has successfully completed before disconnecting 3470 * the current {@link Connection}. 3471 * When {@code false}, the {@link ConnectionService} should signal the network to 3472 * perform the transfer, but should immediately disconnect the call regardless of 3473 * the outcome of the transfer. 3474 * @hide 3475 */ onTransfer(@onNull Uri number, boolean isConfirmationRequired)3476 public void onTransfer(@NonNull Uri number, boolean isConfirmationRequired) {} 3477 3478 /** 3479 * Notifies this Connection, a request to transfer to another Connection. 3480 * @param otherConnection the {@link Connection} to transfer this call to. 3481 * @hide 3482 */ onTransfer(@onNull Connection otherConnection)3483 public void onTransfer(@NonNull Connection otherConnection) {} 3484 3485 /** 3486 * Notifies this Connection of a request to silence the ringer. 3487 * <p> 3488 * The ringer may be silenced by any of the following methods: 3489 * <ul> 3490 * <li>{@link TelecomManager#silenceRinger()}</li> 3491 * <li>The user presses the volume-down button while a call is ringing.</li> 3492 * </ul> 3493 * <p> 3494 * Self-managed {@link ConnectionService} implementations should override this method in their 3495 * {@link Connection} implementation and implement logic to silence their app's ringtone. If 3496 * your app set the ringtone as part of the incoming call {@link Notification} (see 3497 * {@link #onShowIncomingCallUi()}), it should re-post the notification now, except call 3498 * {@link android.app.Notification.Builder#setOnlyAlertOnce(boolean)} with {@code true}. This 3499 * will ensure the ringtone sound associated with your {@link android.app.NotificationChannel} 3500 * stops playing. 3501 */ onSilence()3502 public void onSilence() {} 3503 3504 /** 3505 * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes. 3506 */ onPostDialContinue(boolean proceed)3507 public void onPostDialContinue(boolean proceed) {} 3508 3509 /** 3510 * Notifies this Connection of a request to pull an external call to the local device. 3511 * <p> 3512 * The {@link InCallService} issues a request to pull an external call to the local device via 3513 * {@link Call#pullExternalCall()}. 3514 * <p> 3515 * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} 3516 * capability and {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property bits must be set. 3517 * <p> 3518 * For more information on external calls, see {@link Connection#PROPERTY_IS_EXTERNAL_CALL}. 3519 */ onPullExternalCall()3520 public void onPullExternalCall() {} 3521 3522 /** 3523 * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}. 3524 * <p> 3525 * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}. 3526 * <p> 3527 * Where possible, the Connection should make an attempt to handle {@link Call} events which 3528 * are part of the {@code android.telecom.*} namespace. The Connection should ignore any events 3529 * it does not wish to handle. Unexpected events should be handled gracefully, as it is 3530 * possible that a {@link InCallService} has defined its own Call events which a Connection is 3531 * not aware of. 3532 * <p> 3533 * See also {@link Call#sendCallEvent(String, Bundle)}. 3534 * 3535 * @param event The call event. 3536 * @param extras Extras associated with the call event. 3537 */ onCallEvent(String event, Bundle extras)3538 public void onCallEvent(String event, Bundle extras) {} 3539 3540 /** 3541 * Notifies this {@link Connection} that a handover has completed. 3542 * <p> 3543 * A handover is initiated with {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, 3544 * Bundle)} on the initiating side of the handover, and 3545 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}. 3546 */ onHandoverComplete()3547 public void onHandoverComplete() {} 3548 3549 /** 3550 * Notifies this {@link Connection} of a change to the extras made outside the 3551 * {@link ConnectionService}. 3552 * <p> 3553 * These extras changes can originate from Telecom itself, or from an {@link InCallService} via 3554 * the {@link android.telecom.Call#putExtras(Bundle)} and 3555 * {@link Call#removeExtras(List)}. 3556 * 3557 * @param extras The new extras bundle. 3558 */ onExtrasChanged(Bundle extras)3559 public void onExtrasChanged(Bundle extras) {} 3560 3561 /** 3562 * Notifies this {@link Connection} that its {@link ConnectionService} is responsible for 3563 * displaying its incoming call user interface for the {@link Connection}. 3564 * <p> 3565 * Will only be called for incoming calls added via a self-managed {@link ConnectionService} 3566 * (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}), where the {@link ConnectionService} 3567 * should show its own incoming call user interface. 3568 * <p> 3569 * Where there are ongoing calls in other self-managed {@link ConnectionService}s, or in a 3570 * regular {@link ConnectionService}, and it is not possible to hold these other calls, the 3571 * Telecom framework will display its own incoming call user interface to allow the user to 3572 * choose whether to answer the new incoming call and disconnect other ongoing calls, or to 3573 * reject the new incoming call. 3574 * <p> 3575 * You should trigger the display of the incoming call user interface for your application by 3576 * showing a {@link Notification} with a full-screen {@link Intent} specified. 3577 * 3578 * In your application code, you should create a {@link android.app.NotificationChannel} for 3579 * incoming call notifications from your app: 3580 * <pre><code> 3581 * NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls", 3582 * NotificationManager.IMPORTANCE_MAX); 3583 * // other channel setup stuff goes here. 3584 * 3585 * // We'll use the default system ringtone for our incoming call notification channel. You can 3586 * // use your own audio resource here. 3587 * Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); 3588 * channel.setSound(ringtoneUri, new AudioAttributes.Builder() 3589 * // Setting the AudioAttributes is important as it identifies the purpose of your 3590 * // notification sound. 3591 * .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) 3592 * .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 3593 * .build()); 3594 * 3595 * NotificationManager mgr = getSystemService(NotificationManager.class); 3596 * mgr.createNotificationChannel(channel); 3597 * </code></pre> 3598 * When it comes time to post a notification for your incoming call, ensure it uses your 3599 * incoming call {@link android.app.NotificationChannel}. 3600 * <pre><code> 3601 * // Create an intent which triggers your fullscreen incoming call user interface. 3602 * Intent intent = new Intent(Intent.ACTION_MAIN, null); 3603 * intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK); 3604 * intent.setClass(context, YourIncomingCallActivity.class); 3605 * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED); 3606 * 3607 * // Build the notification as an ongoing high priority item; this ensures it will show as 3608 * // a heads up notification which slides down over top of the current content. 3609 * final Notification.Builder builder = new Notification.Builder(context); 3610 * builder.setOngoing(true); 3611 * builder.setPriority(Notification.PRIORITY_HIGH); 3612 * 3613 * // Set notification content intent to take user to fullscreen UI if user taps on the 3614 * // notification body. 3615 * builder.setContentIntent(pendingIntent); 3616 * // Set full screen intent to trigger display of the fullscreen UI when the notification 3617 * // manager deems it appropriate. 3618 * builder.setFullScreenIntent(pendingIntent, true); 3619 * 3620 * // Setup notification content. 3621 * builder.setSmallIcon( yourIconResourceId ); 3622 * builder.setContentTitle("Your notification title"); 3623 * builder.setContentText("Your notification content."); 3624 * 3625 * // Set notification as insistent to cause your ringtone to loop. 3626 * Notification notification = builder.build(); 3627 * notification.flags |= Notification.FLAG_INSISTENT; 3628 * 3629 * // Use builder.addAction(..) to add buttons to answer or reject the call. 3630 * NotificationManager notificationManager = mContext.getSystemService( 3631 * NotificationManager.class); 3632 * notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, notification); 3633 * </code></pre> 3634 */ onShowIncomingCallUi()3635 public void onShowIncomingCallUi() {} 3636 3637 /** 3638 * Notifies this {@link Connection} that the user has requested an RTT session. 3639 * The connection service should call {@link #sendRttInitiationSuccess} or 3640 * {@link #sendRttInitiationFailure} to inform Telecom of the success or failure of the 3641 * request, respectively. 3642 * @param rttTextStream The object that should be used to send text to or receive text from 3643 * the in-call app. 3644 */ onStartRtt(@onNull RttTextStream rttTextStream)3645 public void onStartRtt(@NonNull RttTextStream rttTextStream) {} 3646 3647 /** 3648 * Notifies this {@link Connection} that it should terminate any existing RTT communication 3649 * channel. No response to Telecom is needed for this method. 3650 */ onStopRtt()3651 public void onStopRtt() {} 3652 3653 /** 3654 * Notifies this connection of a response to a previous remotely-initiated RTT upgrade 3655 * request sent via {@link #sendRemoteRttRequest}. Acceptance of the request is 3656 * indicated by the supplied {@link RttTextStream} being non-null, and rejection is 3657 * indicated by {@code rttTextStream} being {@code null} 3658 * @param rttTextStream The object that should be used to send text to or receive text from 3659 * the in-call app. 3660 */ handleRttUpgradeResponse(@ullable RttTextStream rttTextStream)3661 public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {} 3662 3663 /** 3664 * Information provided to a {@link Connection} upon completion of call filtering in Telecom. 3665 * 3666 * @hide 3667 */ 3668 @SystemApi 3669 public static final class CallFilteringCompletionInfo implements Parcelable { 3670 private final boolean mIsBlocked; 3671 private final boolean mIsInContacts; 3672 private final CallScreeningService.CallResponse mCallResponse; 3673 private final ComponentName mCallScreeningComponent; 3674 3675 /** 3676 * Constructor for {@link CallFilteringCompletionInfo} 3677 * 3678 * @param isBlocked Whether any part of the call filtering process indicated that this call 3679 * should be blocked. 3680 * @param isInContacts Whether the caller is in the user's contacts. 3681 * @param callResponse The instance of {@link CallScreeningService.CallResponse} provided 3682 * by the {@link CallScreeningService} that processed this call, or 3683 * {@code null} if no call screening service ran. 3684 * @param callScreeningComponent The component of the {@link CallScreeningService} 3685 * that processed this call, or {@link null} if no 3686 * call screening service ran. 3687 */ CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts, @Nullable CallScreeningService.CallResponse callResponse, @Nullable ComponentName callScreeningComponent)3688 public CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts, 3689 @Nullable CallScreeningService.CallResponse callResponse, 3690 @Nullable ComponentName callScreeningComponent) { 3691 mIsBlocked = isBlocked; 3692 mIsInContacts = isInContacts; 3693 mCallResponse = callResponse; 3694 mCallScreeningComponent = callScreeningComponent; 3695 } 3696 3697 /** @hide */ CallFilteringCompletionInfo(Parcel in)3698 protected CallFilteringCompletionInfo(Parcel in) { 3699 mIsBlocked = in.readByte() != 0; 3700 mIsInContacts = in.readByte() != 0; 3701 CallScreeningService.ParcelableCallResponse response 3702 = in.readParcelable(CallScreeningService.class.getClassLoader(), android.telecom.CallScreeningService.ParcelableCallResponse.class); 3703 mCallResponse = response == null ? null : response.toCallResponse(); 3704 mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader(), android.content.ComponentName.class); 3705 } 3706 3707 @NonNull 3708 public static final Creator<CallFilteringCompletionInfo> CREATOR = 3709 new Creator<CallFilteringCompletionInfo>() { 3710 @Override 3711 public CallFilteringCompletionInfo createFromParcel(Parcel in) { 3712 return new CallFilteringCompletionInfo(in); 3713 } 3714 3715 @Override 3716 public CallFilteringCompletionInfo[] newArray(int size) { 3717 return new CallFilteringCompletionInfo[size]; 3718 } 3719 }; 3720 3721 /** 3722 * @return Whether any part of the call filtering process indicated that this call should be 3723 * blocked. 3724 */ isBlocked()3725 public boolean isBlocked() { 3726 return mIsBlocked; 3727 } 3728 3729 /** 3730 * @return Whether the caller is in the user's contacts. 3731 */ isInContacts()3732 public boolean isInContacts() { 3733 return mIsInContacts; 3734 } 3735 3736 /** 3737 * @return The instance of {@link CallScreeningService.CallResponse} provided 3738 * by the {@link CallScreeningService} that processed this 3739 * call, or {@code null} if no call screening service ran. 3740 */ getCallResponse()3741 public @Nullable CallScreeningService.CallResponse getCallResponse() { 3742 return mCallResponse; 3743 } 3744 3745 /** 3746 * @return The component of the {@link CallScreeningService} 3747 * that processed this call, or {@code null} if no call screening service ran. 3748 */ getCallScreeningComponent()3749 public @Nullable ComponentName getCallScreeningComponent() { 3750 return mCallScreeningComponent; 3751 } 3752 3753 @Override describeContents()3754 public int describeContents() { 3755 return 0; 3756 } 3757 3758 @Override toString()3759 public String toString() { 3760 return "CallFilteringCompletionInfo{" + 3761 "mIsBlocked=" + mIsBlocked + 3762 ", mIsInContacts=" + mIsInContacts + 3763 ", mCallResponse=" + mCallResponse + 3764 ", mCallScreeningPackageName='" + mCallScreeningComponent + '\'' + 3765 '}'; 3766 } 3767 3768 /** @hide */ 3769 @Override writeToParcel(Parcel dest, int flags)3770 public void writeToParcel(Parcel dest, int flags) { 3771 dest.writeByte((byte) (mIsBlocked ? 1 : 0)); 3772 dest.writeByte((byte) (mIsInContacts ? 1 : 0)); 3773 dest.writeParcelable(mCallResponse == null ? null : mCallResponse.toParcelable(), 0); 3774 dest.writeParcelable(mCallScreeningComponent, 0); 3775 } 3776 } 3777 3778 /** 3779 * Indicates that call filtering in Telecom is complete 3780 * 3781 * This method is called for a connection created via 3782 * {@link ConnectionService#onCreateIncomingConnection} when call filtering completes in 3783 * Telecom, including checking the blocked number db, per-contact settings, and custom call 3784 * filtering apps. 3785 * 3786 * @param callFilteringCompletionInfo Info provided by Telecom on the results of call filtering. 3787 * @hide 3788 */ 3789 @SystemApi 3790 @RequiresPermission(Manifest.permission.READ_CONTACTS) onCallFilteringCompleted( @onNull CallFilteringCompletionInfo callFilteringCompletionInfo)3791 public void onCallFilteringCompleted( 3792 @NonNull CallFilteringCompletionInfo callFilteringCompletionInfo) { } 3793 toLogSafePhoneNumber(String number)3794 static String toLogSafePhoneNumber(String number) { 3795 // For unknown number, log empty string. 3796 if (number == null) { 3797 return ""; 3798 } 3799 3800 if (PII_DEBUG) { 3801 // When PII_DEBUG is true we emit PII. 3802 return number; 3803 } 3804 3805 // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare 3806 // sanitized phone numbers. 3807 StringBuilder builder = new StringBuilder(); 3808 for (int i = 0; i < number.length(); i++) { 3809 char c = number.charAt(i); 3810 if (c == '-' || c == '@' || c == '.') { 3811 builder.append(c); 3812 } else { 3813 builder.append('x'); 3814 } 3815 } 3816 return builder.toString(); 3817 } 3818 setState(int state)3819 private void setState(int state) { 3820 checkImmutable(); 3821 if (mState == STATE_DISCONNECTED && mState != state) { 3822 Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state."); 3823 return; 3824 } 3825 if (mState != state) { 3826 Log.d(this, "setState: %s", stateToString(state)); 3827 mState = state; 3828 onStateChanged(state); 3829 for (Listener l : mListeners) { 3830 l.onStateChanged(this, state); 3831 } 3832 } 3833 } 3834 3835 private static class FailureSignalingConnection extends Connection { 3836 private boolean mImmutable = false; FailureSignalingConnection(DisconnectCause disconnectCause)3837 public FailureSignalingConnection(DisconnectCause disconnectCause) { 3838 setDisconnected(disconnectCause); 3839 mImmutable = true; 3840 } 3841 checkImmutable()3842 public void checkImmutable() { 3843 if (mImmutable) { 3844 throw new UnsupportedOperationException("Connection is immutable"); 3845 } 3846 } 3847 } 3848 3849 /** 3850 * Return a {@code Connection} which represents a failed connection attempt. The returned 3851 * {@code Connection} will have a {@link android.telecom.DisconnectCause} and as specified, 3852 * and a {@link #getState()} of {@link #STATE_DISCONNECTED}. 3853 * <p> 3854 * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate, 3855 * so users of this method need not maintain a reference to its return value to destroy it. 3856 * 3857 * @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}). 3858 * @return A {@code Connection} which indicates failure. 3859 */ createFailedConnection(DisconnectCause disconnectCause)3860 public static Connection createFailedConnection(DisconnectCause disconnectCause) { 3861 return new FailureSignalingConnection(disconnectCause); 3862 } 3863 3864 /** 3865 * Override to throw an {@link UnsupportedOperationException} if this {@code Connection} is 3866 * not intended to be mutated, e.g., if it is a marker for failure. Only for framework use; 3867 * this should never be un-@hide-den. 3868 * 3869 * @hide 3870 */ checkImmutable()3871 public void checkImmutable() {} 3872 3873 /** 3874 * Return a {@code Connection} which represents a canceled connection attempt. The returned 3875 * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of 3876 * that state. This connection should not be used for anything, and no other 3877 * {@code Connection}s should be attempted. 3878 * <p> 3879 * so users of this method need not maintain a reference to its return value to destroy it. 3880 * 3881 * @return A {@code Connection} which indicates that the underlying connection should 3882 * be canceled. 3883 */ createCanceledConnection()3884 public static Connection createCanceledConnection() { 3885 return new FailureSignalingConnection(new DisconnectCause(DisconnectCause.CANCELED)); 3886 } 3887 fireOnConferenceableConnectionsChanged()3888 private final void fireOnConferenceableConnectionsChanged() { 3889 for (Listener l : mListeners) { 3890 l.onConferenceablesChanged(this, getConferenceables()); 3891 } 3892 } 3893 fireConferenceChanged()3894 private final void fireConferenceChanged() { 3895 for (Listener l : mListeners) { 3896 l.onConferenceChanged(this, mConference); 3897 } 3898 } 3899 clearConferenceableList()3900 private final void clearConferenceableList() { 3901 for (Conferenceable c : mConferenceables) { 3902 if (c instanceof Connection) { 3903 Connection connection = (Connection) c; 3904 connection.removeConnectionListener(mConnectionDeathListener); 3905 } else if (c instanceof Conference) { 3906 Conference conference = (Conference) c; 3907 conference.removeListener(mConferenceDeathListener); 3908 } 3909 } 3910 mConferenceables.clear(); 3911 } 3912 3913 /** 3914 * Handles a change to extras received from Telecom. 3915 * 3916 * @param extras The new extras. 3917 * @hide 3918 */ handleExtrasChanged(Bundle extras)3919 final void handleExtrasChanged(Bundle extras) { 3920 Bundle b = null; 3921 synchronized (mExtrasLock) { 3922 mExtras = extras; 3923 if (mExtras != null) { 3924 b = new Bundle(mExtras); 3925 } 3926 } 3927 onExtrasChanged(b); 3928 } 3929 3930 /** 3931 * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()} 3932 * request failed. 3933 */ notifyConferenceMergeFailed()3934 public final void notifyConferenceMergeFailed() { 3935 for (Listener l : mListeners) { 3936 l.onConferenceMergeFailed(this); 3937 } 3938 } 3939 3940 /** 3941 * Notifies listeners when phone account is changed. For example, when the PhoneAccount is 3942 * changed due to an emergency call being redialed. 3943 * @param pHandle The new PhoneAccountHandle for this connection. 3944 * @hide 3945 */ notifyPhoneAccountChanged(PhoneAccountHandle pHandle)3946 public void notifyPhoneAccountChanged(PhoneAccountHandle pHandle) { 3947 for (Listener l : mListeners) { 3948 l.onPhoneAccountChanged(this, pHandle); 3949 } 3950 } 3951 3952 /** 3953 * Sets the {@link PhoneAccountHandle} associated with this connection. 3954 * <p> 3955 * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount} 3956 * which take place after call initiation (important for emergency calling scenarios). 3957 * 3958 * @param phoneAccountHandle the phone account handle to set. 3959 * @hide 3960 */ 3961 @SystemApi setPhoneAccountHandle(@onNull PhoneAccountHandle phoneAccountHandle)3962 public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) { 3963 if (mPhoneAccountHandle != phoneAccountHandle) { 3964 mPhoneAccountHandle = phoneAccountHandle; 3965 notifyPhoneAccountChanged(phoneAccountHandle); 3966 } 3967 } 3968 3969 /** 3970 * Returns the {@link PhoneAccountHandle} associated with this connection. 3971 * <p> 3972 * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount} 3973 * which take place after call initiation (important for emergency calling scenarios). 3974 * 3975 * @return the phone account handle specified via 3976 * {@link #setPhoneAccountHandle(PhoneAccountHandle)}, or {@code null} if none was set. 3977 * @hide 3978 */ 3979 @SystemApi getPhoneAccountHandle()3980 public @Nullable PhoneAccountHandle getPhoneAccountHandle() { 3981 return mPhoneAccountHandle; 3982 } 3983 3984 /** 3985 * Sends an event associated with this {@code Connection} with associated event extras to the 3986 * {@link InCallService}. 3987 * <p> 3988 * Connection events are used to communicate point in time information from a 3989 * {@link ConnectionService} to a {@link InCallService} implementations. An example of a 3990 * custom connection event includes notifying the UI when a WIFI call has been handed over to 3991 * LTE, which the InCall UI might use to inform the user that billing charges may apply. The 3992 * Android Telephony framework will send the {@link #EVENT_CALL_MERGE_FAILED} connection event 3993 * when a call to {@link Call#mergeConference()} has failed to complete successfully. A 3994 * connection event could also be used to trigger UI in the {@link InCallService} which prompts 3995 * the user to make a choice (e.g. whether they want to incur roaming costs for making a call), 3996 * which is communicated back via {@link Call#sendCallEvent(String, Bundle)}. 3997 * <p> 3998 * Events are exposed to {@link InCallService} implementations via 3999 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}. 4000 * <p> 4001 * No assumptions should be made as to how an In-Call UI or service will handle these events. 4002 * The {@link ConnectionService} must assume that the In-Call UI could even chose to ignore 4003 * some events altogether. 4004 * <p> 4005 * Events should be fully qualified (e.g. {@code com.example.event.MY_EVENT}) to avoid 4006 * conflicts between {@link ConnectionService} implementations. Further, custom 4007 * {@link ConnectionService} implementations shall not re-purpose events in the 4008 * {@code android.*} namespace, nor shall they define new event types in this namespace. When 4009 * defining a custom event type, ensure the contents of the extras {@link Bundle} is clearly 4010 * defined. Extra keys for this bundle should be named similar to the event type (e.g. 4011 * {@code com.example.extra.MY_EXTRA}). 4012 * <p> 4013 * When defining events and the associated extras, it is important to keep their behavior 4014 * consistent when the associated {@link ConnectionService} is updated. Support for deprecated 4015 * events/extras should me maintained to ensure backwards compatibility with older 4016 * {@link InCallService} implementations which were built to support the older behavior. 4017 * 4018 * @param event The connection event. 4019 * @param extras Optional bundle containing extra information associated with the event. 4020 */ sendConnectionEvent(String event, Bundle extras)4021 public void sendConnectionEvent(String event, Bundle extras) { 4022 for (Listener l : mListeners) { 4023 l.onConnectionEvent(this, event, extras); 4024 } 4025 } 4026 4027 /** 4028 * Retrieves the direction of this connection. 4029 * @return The direction of the call. 4030 * @hide 4031 */ 4032 @SystemApi 4033 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) getCallDirection()4034 public final @Call.Details.CallDirection int getCallDirection() { 4035 return mCallDirection; 4036 } 4037 4038 /** 4039 * Sets the direction of this connection. 4040 * <p> 4041 * Used when calling {@link ConnectionService#addExistingConnection} to specify the existing 4042 * call direction. 4043 * 4044 * @param callDirection The direction of this connection. 4045 * @hide 4046 */ 4047 @SystemApi setCallDirection(@all.Details.CallDirection int callDirection)4048 public void setCallDirection(@Call.Details.CallDirection int callDirection) { 4049 mCallDirection = callDirection; 4050 } 4051 4052 /** 4053 * Gets the verification status for the phone number of an incoming call as identified in 4054 * ATIS-1000082. 4055 * @return the verification status. 4056 */ getCallerNumberVerificationStatus()4057 public final @VerificationStatus int getCallerNumberVerificationStatus() { 4058 return mCallerNumberVerificationStatus; 4059 } 4060 4061 /** 4062 * Sets the verification status for the phone number of an incoming call as identified in 4063 * ATIS-1000082. 4064 * <p> 4065 * This property can only be set at the time of creation of a {@link Connection} being returned 4066 * by 4067 * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}. 4068 */ setCallerNumberVerificationStatus( @erificationStatus int callerNumberVerificationStatus)4069 public final void setCallerNumberVerificationStatus( 4070 @VerificationStatus int callerNumberVerificationStatus) { 4071 mCallerNumberVerificationStatus = callerNumberVerificationStatus; 4072 } 4073 } 4074