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 resume 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 @FlaggedApi(Flags.FLAG_CALL_SEQUENCING_CALL_RESUME_FAILED) 921 public static final String EVENT_CALL_RESUME_FAILED = 922 "android.telecom.event.CALL_RESUME_FAILED"; 923 924 /** 925 * Connection event used to inform Telecom when a switch operation on a call has failed. 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_CALL_SWITCH_FAILED = 931 "android.telecom.event.CALL_SWITCH_FAILED"; 932 933 /** 934 * Connection event used to inform {@link InCallService}s when the process of merging a 935 * Connection into a conference has begun. 936 * <p> 937 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 938 * expected to be null when this connection event is used. 939 */ 940 public static final String EVENT_MERGE_START = "android.telecom.event.MERGE_START"; 941 942 /** 943 * Connection event used to inform {@link InCallService}s when the process of merging a 944 * Connection into a conference has completed. 945 * <p> 946 * Sent via {@link #sendConnectionEvent(String, Bundle)}. The {@link Bundle} parameter is 947 * expected to be null when this connection event is used. 948 */ 949 public static final String EVENT_MERGE_COMPLETE = "android.telecom.event.MERGE_COMPLETE"; 950 951 /** 952 * Connection event used to inform {@link InCallService}s when a call has been put on hold by 953 * the remote party. 954 * <p> 955 * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the 956 * call is being held locally on the device. When a capable {@link ConnectionService} receives 957 * signalling to indicate that the remote party has put the call on hold, it can send this 958 * connection event. 959 */ 960 public static final String EVENT_CALL_REMOTELY_HELD = 961 "android.telecom.event.CALL_REMOTELY_HELD"; 962 963 /** 964 * Connection event used to inform {@link InCallService}s when a call which was remotely held 965 * (see {@link #EVENT_CALL_REMOTELY_HELD}) has been un-held by the remote party. 966 * <p> 967 * This is different than the {@link Connection#STATE_HOLDING} state which indicates that the 968 * call is being held locally on the device. When a capable {@link ConnectionService} receives 969 * signalling to indicate that the remote party has taken the call off hold, it can send this 970 * connection event. 971 */ 972 public static final String EVENT_CALL_REMOTELY_UNHELD = 973 "android.telecom.event.CALL_REMOTELY_UNHELD"; 974 975 /** 976 * String Connection extra key used to store SIP invite fields for an incoming call for IMS call 977 */ 978 public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE"; 979 980 /** 981 * Connection event used to inform an {@link InCallService} that the RTT audio indication 982 * has changed. 983 */ 984 public static final String EVENT_RTT_AUDIO_INDICATION_CHANGED = 985 "android.telecom.event.RTT_AUDIO_INDICATION_CHANGED"; 986 987 /** 988 * Connection event used to signal between the telephony {@link ConnectionService} and Telecom 989 * when device to device messages are sent/received. 990 * <p> 991 * Device to device messages originating from the network are sent by telephony using 992 * {@link Connection#sendConnectionEvent(String, Bundle)} and are routed up to any active 993 * {@link CallDiagnosticService} implementation which is active. 994 * <p> 995 * Likewise, if a {@link CallDiagnosticService} sends a message using 996 * {@link CallDiagnostics#sendDeviceToDeviceMessage(int, int)}, it will be routed to telephony 997 * via {@link Connection#onCallEvent(String, Bundle)}. The telephony stack will relay the 998 * message to the other device. 999 * @hide 1000 */ 1001 @SystemApi 1002 public static final String EVENT_DEVICE_TO_DEVICE_MESSAGE = 1003 "android.telecom.event.DEVICE_TO_DEVICE_MESSAGE"; 1004 1005 /** 1006 * Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device 1007 * message type. 1008 * 1009 * See {@link CallDiagnostics} for more information. 1010 * @hide 1011 */ 1012 @SystemApi 1013 public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_TYPE = 1014 "android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_TYPE"; 1015 1016 /** 1017 * Sent along with {@link #EVENT_DEVICE_TO_DEVICE_MESSAGE} to indicate the device to device 1018 * message value. 1019 * <p> 1020 * See {@link CallDiagnostics} for more information. 1021 * @hide 1022 */ 1023 @SystemApi 1024 public static final String EXTRA_DEVICE_TO_DEVICE_MESSAGE_VALUE = 1025 "android.telecom.extra.DEVICE_TO_DEVICE_MESSAGE_VALUE"; 1026 1027 /** 1028 * Connection event used to communicate a {@link android.telephony.CallQuality} report from 1029 * telephony to Telecom for relaying to 1030 * {@link CallDiagnostics#onCallQualityReceived(CallQuality)}. 1031 * @hide 1032 */ 1033 @SystemApi 1034 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) 1035 public static final String EVENT_CALL_QUALITY_REPORT = 1036 "android.telecom.event.CALL_QUALITY_REPORT"; 1037 1038 /** 1039 * Extra sent with {@link #EVENT_CALL_QUALITY_REPORT} containing the 1040 * {@link android.telephony.CallQuality} data. 1041 * @hide 1042 */ 1043 @SystemApi 1044 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) 1045 public static final String EXTRA_CALL_QUALITY_REPORT = 1046 "android.telecom.extra.CALL_QUALITY_REPORT"; 1047 1048 /** 1049 * Key to obtain location as a result of ({@code queryLocationForEmergency} from Bundle 1050 * @hide 1051 */ 1052 public static final String EXTRA_KEY_QUERY_LOCATION = 1053 "android.telecom.extra.KEY_QUERY_LOCATION"; 1054 1055 // Flag controlling whether PII is emitted into the logs 1056 private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); 1057 1058 /** 1059 * Renders a set of capability bits ({@code CAPABILITY_*}) as a human readable string. 1060 * 1061 * @param capabilities A capability bit field. 1062 * @return A human readable string representation. 1063 */ capabilitiesToString(int capabilities)1064 public static String capabilitiesToString(int capabilities) { 1065 return capabilitiesToStringInternal(capabilities, true /* isLong */); 1066 } 1067 1068 /** 1069 * Renders a set of capability bits ({@code CAPABILITY_*}) as a *short* human readable 1070 * string. 1071 * 1072 * @param capabilities A capability bit field. 1073 * @return A human readable string representation. 1074 * @hide 1075 */ capabilitiesToStringShort(int capabilities)1076 public static String capabilitiesToStringShort(int capabilities) { 1077 return capabilitiesToStringInternal(capabilities, false /* isLong */); 1078 } 1079 capabilitiesToStringInternal(int capabilities, boolean isLong)1080 private static String capabilitiesToStringInternal(int capabilities, boolean isLong) { 1081 StringBuilder builder = new StringBuilder(); 1082 builder.append("["); 1083 if (isLong) { 1084 builder.append("Capabilities:"); 1085 } 1086 1087 if ((capabilities & CAPABILITY_HOLD) == CAPABILITY_HOLD) { 1088 builder.append(isLong ? " CAPABILITY_HOLD" : " hld"); 1089 } 1090 if ((capabilities & CAPABILITY_SUPPORT_HOLD) == CAPABILITY_SUPPORT_HOLD) { 1091 builder.append(isLong ? " CAPABILITY_SUPPORT_HOLD" : " sup_hld"); 1092 } 1093 if ((capabilities & CAPABILITY_MERGE_CONFERENCE) == CAPABILITY_MERGE_CONFERENCE) { 1094 builder.append(isLong ? " CAPABILITY_MERGE_CONFERENCE" : " mrg_cnf"); 1095 } 1096 if ((capabilities & CAPABILITY_SWAP_CONFERENCE) == CAPABILITY_SWAP_CONFERENCE) { 1097 builder.append(isLong ? " CAPABILITY_SWAP_CONFERENCE" : " swp_cnf"); 1098 } 1099 if ((capabilities & CAPABILITY_RESPOND_VIA_TEXT) == CAPABILITY_RESPOND_VIA_TEXT) { 1100 builder.append(isLong ? " CAPABILITY_RESPOND_VIA_TEXT" : " txt"); 1101 } 1102 if ((capabilities & CAPABILITY_MUTE) == CAPABILITY_MUTE) { 1103 builder.append(isLong ? " CAPABILITY_MUTE" : " mut"); 1104 } 1105 if ((capabilities & CAPABILITY_MANAGE_CONFERENCE) == CAPABILITY_MANAGE_CONFERENCE) { 1106 builder.append(isLong ? " CAPABILITY_MANAGE_CONFERENCE" : " mng_cnf"); 1107 } 1108 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_RX) == CAPABILITY_SUPPORTS_VT_LOCAL_RX) { 1109 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_RX" : " VTlrx"); 1110 } 1111 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_TX) == CAPABILITY_SUPPORTS_VT_LOCAL_TX) { 1112 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_TX" : " VTltx"); 1113 } 1114 if ((capabilities & CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) 1115 == CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) { 1116 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL" : " VTlbi"); 1117 } 1118 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_RX) == CAPABILITY_SUPPORTS_VT_REMOTE_RX) { 1119 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_RX" : " VTrrx"); 1120 } 1121 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_TX) == CAPABILITY_SUPPORTS_VT_REMOTE_TX) { 1122 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_TX" : " VTrtx"); 1123 } 1124 if ((capabilities & CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) 1125 == CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) { 1126 builder.append(isLong ? " CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL" : " VTrbi"); 1127 } 1128 if ((capabilities & CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) 1129 == CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) { 1130 builder.append(isLong ? " CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO" : " !v2a"); 1131 } 1132 if ((capabilities & CAPABILITY_SPEED_UP_MT_AUDIO) == CAPABILITY_SPEED_UP_MT_AUDIO) { 1133 builder.append(isLong ? " CAPABILITY_SPEED_UP_MT_AUDIO" : " spd_aud"); 1134 } 1135 if ((capabilities & CAPABILITY_CAN_UPGRADE_TO_VIDEO) == CAPABILITY_CAN_UPGRADE_TO_VIDEO) { 1136 builder.append(isLong ? " CAPABILITY_CAN_UPGRADE_TO_VIDEO" : " a2v"); 1137 } 1138 if ((capabilities & CAPABILITY_CAN_PAUSE_VIDEO) == CAPABILITY_CAN_PAUSE_VIDEO) { 1139 builder.append(isLong ? " CAPABILITY_CAN_PAUSE_VIDEO" : " paus_VT"); 1140 } 1141 if ((capabilities & CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) 1142 == CAPABILITY_CONFERENCE_HAS_NO_CHILDREN) { 1143 builder.append(isLong ? " CAPABILITY_SINGLE_PARTY_CONFERENCE" : " 1p_cnf"); 1144 } 1145 if ((capabilities & CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) 1146 == CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION) { 1147 builder.append(isLong ? " CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION" : " rsp_by_con"); 1148 } 1149 if ((capabilities & CAPABILITY_CAN_PULL_CALL) == CAPABILITY_CAN_PULL_CALL) { 1150 builder.append(isLong ? " CAPABILITY_CAN_PULL_CALL" : " pull"); 1151 } 1152 if ((capabilities & CAPABILITY_SUPPORT_DEFLECT) == CAPABILITY_SUPPORT_DEFLECT) { 1153 builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def"); 1154 } 1155 if ((capabilities & CAPABILITY_ADD_PARTICIPANT) == CAPABILITY_ADD_PARTICIPANT) { 1156 builder.append(isLong ? " CAPABILITY_ADD_PARTICIPANT" : " add_participant"); 1157 } 1158 if ((capabilities & CAPABILITY_TRANSFER) == CAPABILITY_TRANSFER) { 1159 builder.append(isLong ? " CAPABILITY_TRANSFER" : " sup_trans"); 1160 } 1161 if ((capabilities & CAPABILITY_TRANSFER_CONSULTATIVE) 1162 == CAPABILITY_TRANSFER_CONSULTATIVE) { 1163 builder.append(isLong ? " CAPABILITY_TRANSFER_CONSULTATIVE" : " sup_cTrans"); 1164 } 1165 if ((capabilities & CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT) 1166 == CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT) { 1167 builder.append(isLong ? " CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT" : " sup_rtt"); 1168 } 1169 builder.append("]"); 1170 return builder.toString(); 1171 } 1172 1173 /** 1174 * Renders a set of property bits ({@code PROPERTY_*}) as a human readable string. 1175 * 1176 * @param properties A property bit field. 1177 * @return A human readable string representation. 1178 */ propertiesToString(int properties)1179 public static String propertiesToString(int properties) { 1180 return propertiesToStringInternal(properties, true /* isLong */); 1181 } 1182 1183 /** 1184 * Renders a set of property bits ({@code PROPERTY_*}) as a *short* human readable string. 1185 * 1186 * @param properties A property bit field. 1187 * @return A human readable string representation. 1188 * @hide 1189 */ propertiesToStringShort(int properties)1190 public static String propertiesToStringShort(int properties) { 1191 return propertiesToStringInternal(properties, false /* isLong */); 1192 } 1193 propertiesToStringInternal(int properties, boolean isLong)1194 private static String propertiesToStringInternal(int properties, boolean isLong) { 1195 StringBuilder builder = new StringBuilder(); 1196 builder.append("["); 1197 if (isLong) { 1198 builder.append("Properties:"); 1199 } 1200 1201 if ((properties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) { 1202 builder.append(isLong ? " PROPERTY_SELF_MANAGED" : " self_mng"); 1203 } 1204 1205 if ((properties & PROPERTY_EMERGENCY_CALLBACK_MODE) == PROPERTY_EMERGENCY_CALLBACK_MODE) { 1206 builder.append(isLong ? " PROPERTY_EMERGENCY_CALLBACK_MODE" : " ecbm"); 1207 } 1208 1209 if ((properties & PROPERTY_HIGH_DEF_AUDIO) == PROPERTY_HIGH_DEF_AUDIO) { 1210 builder.append(isLong ? " PROPERTY_HIGH_DEF_AUDIO" : " HD"); 1211 } 1212 1213 if ((properties & PROPERTY_WIFI) == PROPERTY_WIFI) { 1214 builder.append(isLong ? " PROPERTY_WIFI" : " wifi"); 1215 } 1216 1217 if ((properties & PROPERTY_GENERIC_CONFERENCE) == PROPERTY_GENERIC_CONFERENCE) { 1218 builder.append(isLong ? " PROPERTY_GENERIC_CONFERENCE" : " gen_conf"); 1219 } 1220 1221 if ((properties & PROPERTY_IS_EXTERNAL_CALL) == PROPERTY_IS_EXTERNAL_CALL) { 1222 builder.append(isLong ? " PROPERTY_IS_EXTERNAL_CALL" : " xtrnl"); 1223 } 1224 1225 if ((properties & PROPERTY_HAS_CDMA_VOICE_PRIVACY) == PROPERTY_HAS_CDMA_VOICE_PRIVACY) { 1226 builder.append(isLong ? " PROPERTY_HAS_CDMA_VOICE_PRIVACY" : " priv"); 1227 } 1228 1229 if ((properties & PROPERTY_IS_RTT) == PROPERTY_IS_RTT) { 1230 builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt"); 1231 } 1232 1233 if ((properties & PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) 1234 == PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL) { 1235 builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall"); 1236 } 1237 1238 if ((properties & PROPERTY_REMOTELY_HOSTED) == PROPERTY_REMOTELY_HOSTED) { 1239 builder.append(isLong ? " PROPERTY_REMOTELY_HOSTED" : " remote_hst"); 1240 } 1241 1242 if ((properties & PROPERTY_IS_ADHOC_CONFERENCE) == PROPERTY_IS_ADHOC_CONFERENCE) { 1243 builder.append(isLong ? " PROPERTY_IS_ADHOC_CONFERENCE" : " adhoc_conf"); 1244 } 1245 1246 if ((properties & PROPERTY_IS_DOWNGRADED_CONFERENCE) == PROPERTY_IS_DOWNGRADED_CONFERENCE) { 1247 builder.append(isLong ? " PROPERTY_IS_DOWNGRADED_CONFERENCE" : " dngrd_conf"); 1248 } 1249 1250 if ((properties & PROPERTY_CROSS_SIM) == PROPERTY_CROSS_SIM) { 1251 builder.append(isLong ? " PROPERTY_CROSS_SIM" : " xsim"); 1252 } 1253 1254 builder.append("]"); 1255 return builder.toString(); 1256 } 1257 1258 /** @hide */ 1259 abstract static class Listener { onStateChanged(Connection c, int state)1260 public void onStateChanged(Connection c, int state) {} onAddressChanged(Connection c, Uri newAddress, int presentation)1261 public void onAddressChanged(Connection c, Uri newAddress, int presentation) {} onCallerDisplayNameChanged( Connection c, String callerDisplayName, int presentation)1262 public void onCallerDisplayNameChanged( 1263 Connection c, String callerDisplayName, int presentation) {} onVideoStateChanged(Connection c, int videoState)1264 public void onVideoStateChanged(Connection c, int videoState) {} onDisconnected(Connection c, DisconnectCause disconnectCause)1265 public void onDisconnected(Connection c, DisconnectCause disconnectCause) {} onPostDialWait(Connection c, String remaining)1266 public void onPostDialWait(Connection c, String remaining) {} onPostDialChar(Connection c, char nextChar)1267 public void onPostDialChar(Connection c, char nextChar) {} onRingbackRequested(Connection c, boolean ringback)1268 public void onRingbackRequested(Connection c, boolean ringback) {} onDestroyed(Connection c)1269 public void onDestroyed(Connection c) {} onConnectionCapabilitiesChanged(Connection c, int capabilities)1270 public void onConnectionCapabilitiesChanged(Connection c, int capabilities) {} onConnectionPropertiesChanged(Connection c, int properties)1271 public void onConnectionPropertiesChanged(Connection c, int properties) {} onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes)1272 public void onSupportedAudioRoutesChanged(Connection c, int supportedAudioRoutes) {} onVideoProviderChanged( Connection c, VideoProvider videoProvider)1273 public void onVideoProviderChanged( 1274 Connection c, VideoProvider videoProvider) {} onAudioModeIsVoipChanged(Connection c, boolean isVoip)1275 public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {} onStatusHintsChanged(Connection c, StatusHints statusHints)1276 public void onStatusHintsChanged(Connection c, StatusHints statusHints) {} onConferenceablesChanged( Connection c, List<Conferenceable> conferenceables)1277 public void onConferenceablesChanged( 1278 Connection c, List<Conferenceable> conferenceables) {} onConferenceChanged(Connection c, Conference conference)1279 public void onConferenceChanged(Connection c, Conference conference) {} onConferenceMergeFailed(Connection c)1280 public void onConferenceMergeFailed(Connection c) {} onExtrasChanged(Connection c, Bundle extras)1281 public void onExtrasChanged(Connection c, Bundle extras) {} onExtrasRemoved(Connection c, List<String> keys)1282 public void onExtrasRemoved(Connection c, List<String> keys) {} onConnectionEvent(Connection c, String event, Bundle extras)1283 public void onConnectionEvent(Connection c, String event, Bundle extras) {} onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress)1284 public void onAudioRouteChanged(Connection c, int audioRoute, String bluetoothAddress) {} onRttInitiationSuccess(Connection c)1285 public void onRttInitiationSuccess(Connection c) {} onRttInitiationFailure(Connection c, int reason)1286 public void onRttInitiationFailure(Connection c, int reason) {} onRttSessionRemotelyTerminated(Connection c)1287 public void onRttSessionRemotelyTerminated(Connection c) {} onRemoteRttRequest(Connection c)1288 public void onRemoteRttRequest(Connection c) {} 1289 /** @hide */ onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle)1290 public void onPhoneAccountChanged(Connection c, PhoneAccountHandle pHandle) {} onConnectionTimeReset(Connection c)1291 public void onConnectionTimeReset(Connection c) {} onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor, OutcomeReceiver<Void, CallEndpointException> callback)1292 public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor, 1293 OutcomeReceiver<Void, CallEndpointException> callback) {} onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Location, QueryLocationException> callback)1294 public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider, 1295 @NonNull @CallbackExecutor Executor executor, 1296 @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {} 1297 } 1298 1299 /** 1300 * Provides methods to read and write RTT data to/from the in-call app. 1301 */ 1302 public static final class RttTextStream { 1303 private static final int READ_BUFFER_SIZE = 1000; 1304 private final InputStreamReader mPipeFromInCall; 1305 private final OutputStreamWriter mPipeToInCall; 1306 private final ParcelFileDescriptor mFdFromInCall; 1307 private final ParcelFileDescriptor mFdToInCall; 1308 1309 private final FileInputStream mFromInCallFileInputStream; 1310 private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; 1311 1312 /** 1313 * @hide 1314 */ RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall)1315 public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) { 1316 mFdFromInCall = fromInCall; 1317 mFdToInCall = toInCall; 1318 mFromInCallFileInputStream = new FileInputStream(fromInCall.getFileDescriptor()); 1319 1320 // Wrap the FileInputStream in a Channel so that it's interruptible. 1321 mPipeFromInCall = new InputStreamReader( 1322 Channels.newInputStream(Channels.newChannel(mFromInCallFileInputStream))); 1323 mPipeToInCall = new OutputStreamWriter( 1324 new FileOutputStream(toInCall.getFileDescriptor())); 1325 } 1326 1327 /** 1328 * Writes the string {@param input} into the text stream to the UI for this RTT call. Since 1329 * RTT transmits text in real-time, this method should be called as often as text snippets 1330 * are received from the remote user, even if it is only one character. 1331 * <p> 1332 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1333 * lead to interleaved text. 1334 * 1335 * @param input The message to send to the in-call app. 1336 */ write(String input)1337 public void write(String input) throws IOException { 1338 mPipeToInCall.write(input); 1339 mPipeToInCall.flush(); 1340 } 1341 1342 1343 /** 1344 * Reads a string from the in-call app, blocking if there is no data available. Returns 1345 * {@code null} if the RTT conversation has been terminated and there is no further data 1346 * to read. 1347 * <p> 1348 * This method is not thread-safe -- calling it from multiple threads simultaneously may 1349 * lead to interleaved text. 1350 * 1351 * @return A string containing text entered by the user, or {@code null} if the 1352 * conversation has been terminated or if there was an error while reading. 1353 */ read()1354 public String read() throws IOException { 1355 int numRead = mPipeFromInCall.read(mReadBuffer, 0, READ_BUFFER_SIZE); 1356 if (numRead < 0) { 1357 return null; 1358 } 1359 return new String(mReadBuffer, 0, numRead); 1360 } 1361 1362 /** 1363 * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to 1364 * be read. 1365 * 1366 * @return A string containing text entered by the user, or {@code null} if the user has 1367 * not entered any new text yet. 1368 */ readImmediately()1369 public String readImmediately() throws IOException { 1370 if (mFromInCallFileInputStream.available() > 0) { 1371 return read(); 1372 } else { 1373 return null; 1374 } 1375 } 1376 1377 /** @hide */ getFdFromInCall()1378 public ParcelFileDescriptor getFdFromInCall() { 1379 return mFdFromInCall; 1380 } 1381 1382 /** @hide */ getFdToInCall()1383 public ParcelFileDescriptor getFdToInCall() { 1384 return mFdToInCall; 1385 } 1386 } 1387 1388 /** 1389 * Provides constants to represent the results of responses to session modify requests sent via 1390 * {@link Call#sendRttRequest()} 1391 */ 1392 public static final class RttModifyStatus { RttModifyStatus()1393 private RttModifyStatus() {} 1394 /** 1395 * Session modify request was successful. 1396 */ 1397 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; 1398 1399 /** 1400 * Session modify request failed. 1401 */ 1402 public static final int SESSION_MODIFY_REQUEST_FAIL = 2; 1403 1404 /** 1405 * Session modify request ignored due to invalid parameters. 1406 */ 1407 public static final int SESSION_MODIFY_REQUEST_INVALID = 3; 1408 1409 /** 1410 * Session modify request timed out. 1411 */ 1412 public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; 1413 1414 /** 1415 * Session modify request rejected by remote user. 1416 */ 1417 public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; 1418 1419 1420 /**@hide*/ 1421 @Retention(RetentionPolicy.SOURCE) 1422 @IntDef(prefix = "SESSION_MODIFY_REQUEST_", value = { 1423 SESSION_MODIFY_REQUEST_SUCCESS, 1424 SESSION_MODIFY_REQUEST_FAIL, 1425 SESSION_MODIFY_REQUEST_INVALID, 1426 SESSION_MODIFY_REQUEST_TIMED_OUT, 1427 SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE 1428 }) 1429 public @interface RttSessionModifyStatus {} 1430 } 1431 1432 /** 1433 * Provides a means of controlling the video session associated with a {@link Connection}. 1434 * <p> 1435 * Implementations create a custom subclass of {@link VideoProvider} and the 1436 * {@link ConnectionService} creates an instance sets it on the {@link Connection} using 1437 * {@link Connection#setVideoProvider(VideoProvider)}. Any connection which supports video 1438 * should set the {@link VideoProvider}. 1439 * <p> 1440 * The {@link VideoProvider} serves two primary purposes: it provides a means for Telecom and 1441 * {@link InCallService} implementations to issue requests related to the video session; 1442 * it provides a means for the {@link ConnectionService} to report events and information 1443 * related to the video session to Telecom and the {@link InCallService} implementations. 1444 * <p> 1445 * {@link InCallService} implementations interact with the {@link VideoProvider} via 1446 * {@link android.telecom.InCallService.VideoCall}. 1447 */ 1448 public static abstract class VideoProvider { 1449 /** 1450 * Video is not being received (no protocol pause was issued). 1451 * @see #handleCallSessionEvent(int) 1452 */ 1453 public static final int SESSION_EVENT_RX_PAUSE = 1; 1454 1455 /** 1456 * Video reception has resumed after a {@link #SESSION_EVENT_RX_PAUSE}. 1457 * @see #handleCallSessionEvent(int) 1458 */ 1459 public static final int SESSION_EVENT_RX_RESUME = 2; 1460 1461 /** 1462 * Video transmission has begun. This occurs after a negotiated start of video transmission 1463 * when the underlying protocol has actually begun transmitting video to the remote party. 1464 * @see #handleCallSessionEvent(int) 1465 */ 1466 public static final int SESSION_EVENT_TX_START = 3; 1467 1468 /** 1469 * Video transmission has stopped. This occurs after a negotiated stop of video transmission 1470 * when the underlying protocol has actually stopped transmitting video to the remote party. 1471 * @see #handleCallSessionEvent(int) 1472 */ 1473 public static final int SESSION_EVENT_TX_STOP = 4; 1474 1475 /** 1476 * A camera failure has occurred for the selected camera. The {@link VideoProvider} can use 1477 * this as a cue to inform the user the camera is not available. 1478 * @see #handleCallSessionEvent(int) 1479 */ 1480 public static final int SESSION_EVENT_CAMERA_FAILURE = 5; 1481 1482 /** 1483 * Issued after {@link #SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready 1484 * for operation. The {@link VideoProvider} can use this as a cue to inform the user that 1485 * the camera has become available again. 1486 * @see #handleCallSessionEvent(int) 1487 */ 1488 public static final int SESSION_EVENT_CAMERA_READY = 6; 1489 1490 /** 1491 * Session event raised by Telecom when 1492 * {@link android.telecom.InCallService.VideoCall#setCamera(String)} is called and the 1493 * caller does not have the necessary {@link android.Manifest.permission#CAMERA} permission. 1494 * @see #handleCallSessionEvent(int) 1495 */ 1496 public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7; 1497 1498 /** 1499 * Session modify request was successful. 1500 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1501 */ 1502 public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; 1503 1504 /** 1505 * Session modify request failed. 1506 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1507 */ 1508 public static final int SESSION_MODIFY_REQUEST_FAIL = 2; 1509 1510 /** 1511 * Session modify request ignored due to invalid parameters. 1512 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1513 */ 1514 public static final int SESSION_MODIFY_REQUEST_INVALID = 3; 1515 1516 /** 1517 * Session modify request timed out. 1518 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1519 */ 1520 public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; 1521 1522 /** 1523 * Session modify request rejected by remote user. 1524 * @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile) 1525 */ 1526 public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; 1527 1528 private static final int MSG_ADD_VIDEO_CALLBACK = 1; 1529 private static final int MSG_SET_CAMERA = 2; 1530 private static final int MSG_SET_PREVIEW_SURFACE = 3; 1531 private static final int MSG_SET_DISPLAY_SURFACE = 4; 1532 private static final int MSG_SET_DEVICE_ORIENTATION = 5; 1533 private static final int MSG_SET_ZOOM = 6; 1534 private static final int MSG_SEND_SESSION_MODIFY_REQUEST = 7; 1535 private static final int MSG_SEND_SESSION_MODIFY_RESPONSE = 8; 1536 private static final int MSG_REQUEST_CAMERA_CAPABILITIES = 9; 1537 private static final int MSG_REQUEST_CONNECTION_DATA_USAGE = 10; 1538 private static final int MSG_SET_PAUSE_IMAGE = 11; 1539 private static final int MSG_REMOVE_VIDEO_CALLBACK = 12; 1540 1541 private static final String SESSION_EVENT_RX_PAUSE_STR = "RX_PAUSE"; 1542 private static final String SESSION_EVENT_RX_RESUME_STR = "RX_RESUME"; 1543 private static final String SESSION_EVENT_TX_START_STR = "TX_START"; 1544 private static final String SESSION_EVENT_TX_STOP_STR = "TX_STOP"; 1545 private static final String SESSION_EVENT_CAMERA_FAILURE_STR = "CAMERA_FAIL"; 1546 private static final String SESSION_EVENT_CAMERA_READY_STR = "CAMERA_READY"; 1547 private static final String SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR = 1548 "CAMERA_PERMISSION_ERROR"; 1549 private static final String SESSION_EVENT_UNKNOWN_STR = "UNKNOWN"; 1550 1551 private VideoProvider.VideoProviderHandler mMessageHandler; 1552 private final VideoProvider.VideoProviderBinder mBinder; 1553 1554 /** 1555 * Stores a list of the video callbacks, keyed by IBinder. 1556 * 1557 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 1558 * load factor before resizing, 1 means we only expect a single thread to 1559 * access the map so make only a single shard 1560 */ 1561 private ConcurrentHashMap<IBinder, IVideoCallback> mVideoCallbacks = 1562 new ConcurrentHashMap<IBinder, IVideoCallback>(8, 0.9f, 1); 1563 1564 /** 1565 * Default handler used to consolidate binder method calls onto a single thread. 1566 */ 1567 private final class VideoProviderHandler extends Handler { VideoProviderHandler()1568 public VideoProviderHandler() { 1569 super(); 1570 } 1571 VideoProviderHandler(Looper looper)1572 public VideoProviderHandler(Looper looper) { 1573 super(looper); 1574 } 1575 1576 @Override handleMessage(Message msg)1577 public void handleMessage(Message msg) { 1578 switch (msg.what) { 1579 case MSG_ADD_VIDEO_CALLBACK: { 1580 IBinder binder = (IBinder) msg.obj; 1581 IVideoCallback callback = IVideoCallback.Stub 1582 .asInterface((IBinder) msg.obj); 1583 if (callback == null) { 1584 Log.w(this, "addVideoProvider - skipped; callback is null."); 1585 break; 1586 } 1587 1588 if (mVideoCallbacks.containsKey(binder)) { 1589 Log.i(this, "addVideoProvider - skipped; already present."); 1590 break; 1591 } 1592 mVideoCallbacks.put(binder, callback); 1593 break; 1594 } 1595 case MSG_REMOVE_VIDEO_CALLBACK: { 1596 IBinder binder = (IBinder) msg.obj; 1597 IVideoCallback callback = IVideoCallback.Stub 1598 .asInterface((IBinder) msg.obj); 1599 if (!mVideoCallbacks.containsKey(binder)) { 1600 Log.i(this, "removeVideoProvider - skipped; not present."); 1601 break; 1602 } 1603 mVideoCallbacks.remove(binder); 1604 break; 1605 } 1606 case MSG_SET_CAMERA: 1607 { 1608 SomeArgs args = (SomeArgs) msg.obj; 1609 try { 1610 onSetCamera((String) args.arg1); 1611 onSetCamera((String) args.arg1, (String) args.arg2, args.argi1, 1612 args.argi2, args.argi3); 1613 } finally { 1614 args.recycle(); 1615 } 1616 } 1617 break; 1618 case MSG_SET_PREVIEW_SURFACE: 1619 onSetPreviewSurface((Surface) msg.obj); 1620 break; 1621 case MSG_SET_DISPLAY_SURFACE: 1622 onSetDisplaySurface((Surface) msg.obj); 1623 break; 1624 case MSG_SET_DEVICE_ORIENTATION: 1625 onSetDeviceOrientation(msg.arg1); 1626 break; 1627 case MSG_SET_ZOOM: 1628 onSetZoom((Float) msg.obj); 1629 break; 1630 case MSG_SEND_SESSION_MODIFY_REQUEST: { 1631 SomeArgs args = (SomeArgs) msg.obj; 1632 try { 1633 onSendSessionModifyRequest((VideoProfile) args.arg1, 1634 (VideoProfile) args.arg2); 1635 } finally { 1636 args.recycle(); 1637 } 1638 break; 1639 } 1640 case MSG_SEND_SESSION_MODIFY_RESPONSE: 1641 onSendSessionModifyResponse((VideoProfile) msg.obj); 1642 break; 1643 case MSG_REQUEST_CAMERA_CAPABILITIES: 1644 onRequestCameraCapabilities(); 1645 break; 1646 case MSG_REQUEST_CONNECTION_DATA_USAGE: 1647 onRequestConnectionDataUsage(); 1648 break; 1649 case MSG_SET_PAUSE_IMAGE: 1650 onSetPauseImage((Uri) msg.obj); 1651 break; 1652 default: 1653 break; 1654 } 1655 } 1656 } 1657 1658 /** 1659 * IVideoProvider stub implementation. 1660 */ 1661 private final class VideoProviderBinder extends IVideoProvider.Stub { addVideoCallback(IBinder videoCallbackBinder)1662 public void addVideoCallback(IBinder videoCallbackBinder) { 1663 mMessageHandler.obtainMessage( 1664 MSG_ADD_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); 1665 } 1666 removeVideoCallback(IBinder videoCallbackBinder)1667 public void removeVideoCallback(IBinder videoCallbackBinder) { 1668 mMessageHandler.obtainMessage( 1669 MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); 1670 } 1671 setCamera(String cameraId, String callingPackageName, int targetSdkVersion)1672 public void setCamera(String cameraId, String callingPackageName, 1673 int targetSdkVersion) { 1674 1675 SomeArgs args = SomeArgs.obtain(); 1676 args.arg1 = cameraId; 1677 // Propagate the calling package; originally determined in 1678 // android.telecom.InCallService.VideoCall#setCamera(String) from the calling 1679 // process. 1680 args.arg2 = callingPackageName; 1681 // Pass along the uid and pid of the calling app; this gets lost when we put the 1682 // message onto the handler. These are required for Telecom to perform a permission 1683 // check to see if the calling app is able to use the camera. 1684 args.argi1 = Binder.getCallingUid(); 1685 args.argi2 = Binder.getCallingPid(); 1686 // Pass along the target SDK version of the calling InCallService. This is used to 1687 // maintain backwards compatibility of the API for older callers. 1688 args.argi3 = targetSdkVersion; 1689 mMessageHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget(); 1690 } 1691 setPreviewSurface(Surface surface)1692 public void setPreviewSurface(Surface surface) { 1693 mMessageHandler.obtainMessage(MSG_SET_PREVIEW_SURFACE, surface).sendToTarget(); 1694 } 1695 setDisplaySurface(Surface surface)1696 public void setDisplaySurface(Surface surface) { 1697 mMessageHandler.obtainMessage(MSG_SET_DISPLAY_SURFACE, surface).sendToTarget(); 1698 } 1699 setDeviceOrientation(int rotation)1700 public void setDeviceOrientation(int rotation) { 1701 mMessageHandler.obtainMessage( 1702 MSG_SET_DEVICE_ORIENTATION, rotation, 0).sendToTarget(); 1703 } 1704 setZoom(float value)1705 public void setZoom(float value) { 1706 mMessageHandler.obtainMessage(MSG_SET_ZOOM, value).sendToTarget(); 1707 } 1708 sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)1709 public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) { 1710 SomeArgs args = SomeArgs.obtain(); 1711 args.arg1 = fromProfile; 1712 args.arg2 = toProfile; 1713 mMessageHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget(); 1714 } 1715 sendSessionModifyResponse(VideoProfile responseProfile)1716 public void sendSessionModifyResponse(VideoProfile responseProfile) { 1717 mMessageHandler.obtainMessage( 1718 MSG_SEND_SESSION_MODIFY_RESPONSE, responseProfile).sendToTarget(); 1719 } 1720 requestCameraCapabilities()1721 public void requestCameraCapabilities() { 1722 mMessageHandler.obtainMessage(MSG_REQUEST_CAMERA_CAPABILITIES).sendToTarget(); 1723 } 1724 requestCallDataUsage()1725 public void requestCallDataUsage() { 1726 mMessageHandler.obtainMessage(MSG_REQUEST_CONNECTION_DATA_USAGE).sendToTarget(); 1727 } 1728 setPauseImage(Uri uri)1729 public void setPauseImage(Uri uri) { 1730 mMessageHandler.obtainMessage(MSG_SET_PAUSE_IMAGE, uri).sendToTarget(); 1731 } 1732 } 1733 VideoProvider()1734 public VideoProvider() { 1735 mBinder = new VideoProvider.VideoProviderBinder(); 1736 mMessageHandler = new VideoProvider.VideoProviderHandler(Looper.getMainLooper()); 1737 } 1738 1739 /** 1740 * Creates an instance of the {@link VideoProvider}, specifying the looper to use. 1741 * 1742 * @param looper The looper. 1743 * @hide 1744 */ 1745 @UnsupportedAppUsage VideoProvider(Looper looper)1746 public VideoProvider(Looper looper) { 1747 mBinder = new VideoProvider.VideoProviderBinder(); 1748 mMessageHandler = new VideoProvider.VideoProviderHandler(looper); 1749 } 1750 1751 /** 1752 * Returns binder object which can be used across IPC methods. 1753 * @hide 1754 */ getInterface()1755 public final IVideoProvider getInterface() { 1756 return mBinder; 1757 } 1758 1759 /** 1760 * Sets the camera to be used for the outgoing video. 1761 * <p> 1762 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1763 * camera via 1764 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1765 * <p> 1766 * Sent from the {@link InCallService} via 1767 * {@link InCallService.VideoCall#setCamera(String)}. 1768 * 1769 * @param cameraId The id of the camera (use ids as reported by 1770 * {@link CameraManager#getCameraIdList()}). 1771 */ onSetCamera(String cameraId)1772 public abstract void onSetCamera(String cameraId); 1773 1774 /** 1775 * Sets the camera to be used for the outgoing video. 1776 * <p> 1777 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1778 * camera via 1779 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1780 * <p> 1781 * This prototype is used internally to ensure that the calling package name, UID and PID 1782 * are sent to Telecom so that can perform a camera permission check on the caller. 1783 * <p> 1784 * Sent from the {@link InCallService} via 1785 * {@link InCallService.VideoCall#setCamera(String)}. 1786 * 1787 * @param cameraId The id of the camera (use ids as reported by 1788 * {@link CameraManager#getCameraIdList()}). 1789 * @param callingPackageName The AppOpps package name of the caller. 1790 * @param callingUid The UID of the caller. 1791 * @param callingPid The PID of the caller. 1792 * @param targetSdkVersion The target SDK version of the caller. 1793 * @hide 1794 */ onSetCamera(String cameraId, String callingPackageName, int callingUid, int callingPid, int targetSdkVersion)1795 public void onSetCamera(String cameraId, String callingPackageName, int callingUid, 1796 int callingPid, int targetSdkVersion) {} 1797 1798 /** 1799 * Sets the surface to be used for displaying a preview of what the user's camera is 1800 * currently capturing. When video transmission is enabled, this is the video signal which 1801 * is sent to the remote device. 1802 * <p> 1803 * Sent from the {@link InCallService} via 1804 * {@link InCallService.VideoCall#setPreviewSurface(Surface)}. 1805 * 1806 * @param surface The {@link Surface}. 1807 */ onSetPreviewSurface(Surface surface)1808 public abstract void onSetPreviewSurface(Surface surface); 1809 1810 /** 1811 * Sets the surface to be used for displaying the video received from the remote device. 1812 * <p> 1813 * Sent from the {@link InCallService} via 1814 * {@link InCallService.VideoCall#setDisplaySurface(Surface)}. 1815 * 1816 * @param surface The {@link Surface}. 1817 */ onSetDisplaySurface(Surface surface)1818 public abstract void onSetDisplaySurface(Surface surface); 1819 1820 /** 1821 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of 1822 * the device is 0 degrees. 1823 * <p> 1824 * Sent from the {@link InCallService} via 1825 * {@link InCallService.VideoCall#setDeviceOrientation(int)}. 1826 * 1827 * @param rotation The device orientation, in degrees. 1828 */ onSetDeviceOrientation(int rotation)1829 public abstract void onSetDeviceOrientation(int rotation); 1830 1831 /** 1832 * Sets the camera zoom ratio. 1833 * <p> 1834 * Sent from the {@link InCallService} via {@link InCallService.VideoCall#setZoom(float)}. 1835 * 1836 * @param value The camera zoom ratio; for the current camera, should be a value in the 1837 * range defined by 1838 * {@link android.hardware.camera2.CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}. 1839 */ onSetZoom(float value)1840 public abstract void onSetZoom(float value); 1841 1842 /** 1843 * Issues a request to modify the properties of the current video session. 1844 * <p> 1845 * Example scenarios include: requesting an audio-only call to be upgraded to a 1846 * bi-directional video call, turning on or off the user's camera, sending a pause signal 1847 * when the {@link InCallService} is no longer the foreground application. 1848 * <p> 1849 * If the {@link VideoProvider} determines a request to be invalid, it should call 1850 * {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} to report the 1851 * invalid request back to the {@link InCallService}. 1852 * <p> 1853 * Where a request requires confirmation from the user of the peer device, the 1854 * {@link VideoProvider} must communicate the request to the peer device and handle the 1855 * user's response. {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} 1856 * is used to inform the {@link InCallService} of the result of the request. 1857 * <p> 1858 * Sent from the {@link InCallService} via 1859 * {@link InCallService.VideoCall#sendSessionModifyRequest(VideoProfile)}. 1860 * 1861 * @param fromProfile The video profile prior to the request. 1862 * @param toProfile The video profile with the requested changes made. 1863 */ onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile)1864 public abstract void onSendSessionModifyRequest(VideoProfile fromProfile, 1865 VideoProfile toProfile); 1866 1867 /** 1868 * Provides a response to a request to change the current video session properties. 1869 * <p> 1870 * For example, if the peer requests and upgrade from an audio-only call to a bi-directional 1871 * video call, could decline the request and keep the call as audio-only. 1872 * In such a scenario, the {@code responseProfile} would have a video state of 1873 * {@link VideoProfile#STATE_AUDIO_ONLY}. If the user had decided to accept the request, 1874 * the video state would be {@link VideoProfile#STATE_BIDIRECTIONAL}. 1875 * <p> 1876 * Sent from the {@link InCallService} via 1877 * {@link InCallService.VideoCall#sendSessionModifyResponse(VideoProfile)} in response to 1878 * a {@link InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)} 1879 * callback. 1880 * 1881 * @param responseProfile The response video profile. 1882 */ onSendSessionModifyResponse(VideoProfile responseProfile)1883 public abstract void onSendSessionModifyResponse(VideoProfile responseProfile); 1884 1885 /** 1886 * Issues a request to the {@link VideoProvider} to retrieve the camera capabilities. 1887 * <p> 1888 * The {@link VideoProvider} should respond by communicating the capabilities of the chosen 1889 * camera via 1890 * {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}. 1891 * <p> 1892 * Sent from the {@link InCallService} via 1893 * {@link InCallService.VideoCall#requestCameraCapabilities()}. 1894 */ onRequestCameraCapabilities()1895 public abstract void onRequestCameraCapabilities(); 1896 1897 /** 1898 * Issues a request to the {@link VideoProvider} to retrieve the current data usage for the 1899 * video component of the current {@link Connection}. 1900 * <p> 1901 * The {@link VideoProvider} should respond by communicating current data usage, in bytes, 1902 * via {@link VideoProvider#setCallDataUsage(long)}. 1903 * <p> 1904 * Sent from the {@link InCallService} via 1905 * {@link InCallService.VideoCall#requestCallDataUsage()}. 1906 */ onRequestConnectionDataUsage()1907 public abstract void onRequestConnectionDataUsage(); 1908 1909 /** 1910 * Provides the {@link VideoProvider} with the {@link Uri} of an image to be displayed to 1911 * the peer device when the video signal is paused. 1912 * <p> 1913 * Sent from the {@link InCallService} via 1914 * {@link InCallService.VideoCall#setPauseImage(Uri)}. 1915 * 1916 * @param uri URI of image to display. 1917 */ onSetPauseImage(Uri uri)1918 public abstract void onSetPauseImage(Uri uri); 1919 1920 /** 1921 * Used to inform listening {@link InCallService} implementations when the 1922 * {@link VideoProvider} receives a session modification request. 1923 * <p> 1924 * Received by the {@link InCallService} via 1925 * {@link InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)}, 1926 * 1927 * @param videoProfile The requested video profile. 1928 * @see #onSendSessionModifyRequest(VideoProfile, VideoProfile) 1929 */ receiveSessionModifyRequest(VideoProfile videoProfile)1930 public void receiveSessionModifyRequest(VideoProfile videoProfile) { 1931 if (mVideoCallbacks != null) { 1932 for (IVideoCallback callback : mVideoCallbacks.values()) { 1933 try { 1934 callback.receiveSessionModifyRequest(videoProfile); 1935 } catch (RemoteException ignored) { 1936 Log.w(this, "receiveSessionModifyRequest callback failed", ignored); 1937 } 1938 } 1939 } 1940 } 1941 1942 /** 1943 * Used to inform listening {@link InCallService} implementations when the 1944 * {@link VideoProvider} receives a response to a session modification request. 1945 * <p> 1946 * Received by the {@link InCallService} via 1947 * {@link InCallService.VideoCall.Callback#onSessionModifyResponseReceived(int, 1948 * VideoProfile, VideoProfile)}. 1949 * 1950 * @param status Status of the session modify request. Valid values are 1951 * {@link VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS}, 1952 * {@link VideoProvider#SESSION_MODIFY_REQUEST_FAIL}, 1953 * {@link VideoProvider#SESSION_MODIFY_REQUEST_INVALID}, 1954 * {@link VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT}, 1955 * {@link VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE} 1956 * @param requestedProfile The original request which was sent to the peer device. 1957 * @param responseProfile The actual profile changes agreed to by the peer device. 1958 * @see #onSendSessionModifyRequest(VideoProfile, VideoProfile) 1959 */ receiveSessionModifyResponse(int status, VideoProfile requestedProfile, VideoProfile responseProfile)1960 public void receiveSessionModifyResponse(int status, 1961 VideoProfile requestedProfile, VideoProfile responseProfile) { 1962 if (mVideoCallbacks != null) { 1963 for (IVideoCallback callback : mVideoCallbacks.values()) { 1964 try { 1965 callback.receiveSessionModifyResponse(status, requestedProfile, 1966 responseProfile); 1967 } catch (RemoteException ignored) { 1968 Log.w(this, "receiveSessionModifyResponse callback failed", ignored); 1969 } 1970 } 1971 } 1972 } 1973 1974 /** 1975 * Used to inform listening {@link InCallService} implementations when the 1976 * {@link VideoProvider} reports a call session event. 1977 * <p> 1978 * Received by the {@link InCallService} via 1979 * {@link InCallService.VideoCall.Callback#onCallSessionEvent(int)}. 1980 * 1981 * @param event The event. Valid values are: {@link VideoProvider#SESSION_EVENT_RX_PAUSE}, 1982 * {@link VideoProvider#SESSION_EVENT_RX_RESUME}, 1983 * {@link VideoProvider#SESSION_EVENT_TX_START}, 1984 * {@link VideoProvider#SESSION_EVENT_TX_STOP}, 1985 * {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE}, 1986 * {@link VideoProvider#SESSION_EVENT_CAMERA_READY}, 1987 * {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE}. 1988 */ handleCallSessionEvent(int event)1989 public void handleCallSessionEvent(int event) { 1990 if (mVideoCallbacks != null) { 1991 for (IVideoCallback callback : mVideoCallbacks.values()) { 1992 try { 1993 callback.handleCallSessionEvent(event); 1994 } catch (RemoteException ignored) { 1995 Log.w(this, "handleCallSessionEvent callback failed", ignored); 1996 } 1997 } 1998 } 1999 } 2000 2001 /** 2002 * Used to inform listening {@link InCallService} implementations when the dimensions of the 2003 * peer's video have changed. 2004 * <p> 2005 * This could occur if, for example, the peer rotates their device, changing the aspect 2006 * ratio of the video, or if the user switches between the back and front cameras. 2007 * <p> 2008 * Received by the {@link InCallService} via 2009 * {@link InCallService.VideoCall.Callback#onPeerDimensionsChanged(int, int)}. 2010 * 2011 * @param width The updated peer video width. 2012 * @param height The updated peer video height. 2013 */ changePeerDimensions(int width, int height)2014 public void changePeerDimensions(int width, int height) { 2015 if (mVideoCallbacks != null) { 2016 for (IVideoCallback callback : mVideoCallbacks.values()) { 2017 try { 2018 callback.changePeerDimensions(width, height); 2019 } catch (RemoteException ignored) { 2020 Log.w(this, "changePeerDimensions callback failed", ignored); 2021 } 2022 } 2023 } 2024 } 2025 2026 /** 2027 * Used to inform listening {@link InCallService} implementations when the data usage of the 2028 * video associated with the current {@link Connection} has changed. 2029 * <p> 2030 * This could be in response to a preview request via 2031 * {@link #onRequestConnectionDataUsage()}, or as a periodic update by the 2032 * {@link VideoProvider}. Where periodic updates of data usage are provided, they should be 2033 * provided at most for every 1 MB of data transferred and no more than once every 10 sec. 2034 * <p> 2035 * Received by the {@link InCallService} via 2036 * {@link InCallService.VideoCall.Callback#onCallDataUsageChanged(long)}. 2037 * 2038 * @param dataUsage The updated data usage (in bytes). Reported as the cumulative bytes 2039 * used since the start of the call. 2040 */ setCallDataUsage(long dataUsage)2041 public void setCallDataUsage(long dataUsage) { 2042 if (mVideoCallbacks != null) { 2043 for (IVideoCallback callback : mVideoCallbacks.values()) { 2044 try { 2045 callback.changeCallDataUsage(dataUsage); 2046 } catch (RemoteException ignored) { 2047 Log.w(this, "setCallDataUsage callback failed", ignored); 2048 } 2049 } 2050 } 2051 } 2052 2053 /** 2054 * @see #setCallDataUsage(long) 2055 * 2056 * @param dataUsage The updated data usage (in byes). 2057 * @deprecated - Use {@link #setCallDataUsage(long)} instead. 2058 * @hide 2059 */ changeCallDataUsage(long dataUsage)2060 public void changeCallDataUsage(long dataUsage) { 2061 setCallDataUsage(dataUsage); 2062 } 2063 2064 /** 2065 * Used to inform listening {@link InCallService} implementations when the capabilities of 2066 * the current camera have changed. 2067 * <p> 2068 * The {@link VideoProvider} should call this in response to 2069 * {@link VideoProvider#onRequestCameraCapabilities()}, or when the current camera is 2070 * changed via {@link VideoProvider#onSetCamera(String)}. 2071 * <p> 2072 * Received by the {@link InCallService} via 2073 * {@link InCallService.VideoCall.Callback#onCameraCapabilitiesChanged( 2074 * VideoProfile.CameraCapabilities)}. 2075 * 2076 * @param cameraCapabilities The new camera capabilities. 2077 */ changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities)2078 public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) { 2079 if (mVideoCallbacks != null) { 2080 for (IVideoCallback callback : mVideoCallbacks.values()) { 2081 try { 2082 callback.changeCameraCapabilities(cameraCapabilities); 2083 } catch (RemoteException ignored) { 2084 Log.w(this, "changeCameraCapabilities callback failed", ignored); 2085 } 2086 } 2087 } 2088 } 2089 2090 /** 2091 * Used to inform listening {@link InCallService} implementations when the video quality 2092 * of the call has changed. 2093 * <p> 2094 * Received by the {@link InCallService} via 2095 * {@link InCallService.VideoCall.Callback#onVideoQualityChanged(int)}. 2096 * 2097 * @param videoQuality The updated video quality. Valid values: 2098 * {@link VideoProfile#QUALITY_HIGH}, 2099 * {@link VideoProfile#QUALITY_MEDIUM}, 2100 * {@link VideoProfile#QUALITY_LOW}, 2101 * {@link VideoProfile#QUALITY_DEFAULT}. 2102 */ changeVideoQuality(int videoQuality)2103 public void changeVideoQuality(int videoQuality) { 2104 if (mVideoCallbacks != null) { 2105 for (IVideoCallback callback : mVideoCallbacks.values()) { 2106 try { 2107 callback.changeVideoQuality(videoQuality); 2108 } catch (RemoteException ignored) { 2109 Log.w(this, "changeVideoQuality callback failed", ignored); 2110 } 2111 } 2112 } 2113 } 2114 2115 /** 2116 * Returns a string representation of a call session event. 2117 * 2118 * @param event A call session event passed to {@link #handleCallSessionEvent(int)}. 2119 * @return String representation of the call session event. 2120 * @hide 2121 */ sessionEventToString(int event)2122 public static String sessionEventToString(int event) { 2123 switch (event) { 2124 case SESSION_EVENT_CAMERA_FAILURE: 2125 return SESSION_EVENT_CAMERA_FAILURE_STR; 2126 case SESSION_EVENT_CAMERA_READY: 2127 return SESSION_EVENT_CAMERA_READY_STR; 2128 case SESSION_EVENT_RX_PAUSE: 2129 return SESSION_EVENT_RX_PAUSE_STR; 2130 case SESSION_EVENT_RX_RESUME: 2131 return SESSION_EVENT_RX_RESUME_STR; 2132 case SESSION_EVENT_TX_START: 2133 return SESSION_EVENT_TX_START_STR; 2134 case SESSION_EVENT_TX_STOP: 2135 return SESSION_EVENT_TX_STOP_STR; 2136 case SESSION_EVENT_CAMERA_PERMISSION_ERROR: 2137 return SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR; 2138 default: 2139 return SESSION_EVENT_UNKNOWN_STR + " " + event; 2140 } 2141 } 2142 } 2143 2144 private final Listener mConnectionDeathListener = new Listener() { 2145 @Override 2146 public void onDestroyed(Connection c) { 2147 if (mConferenceables.remove(c)) { 2148 fireOnConferenceableConnectionsChanged(); 2149 } 2150 } 2151 }; 2152 2153 private final Conference.Listener mConferenceDeathListener = new Conference.Listener() { 2154 @Override 2155 public void onDestroyed(Conference c) { 2156 if (mConferenceables.remove(c)) { 2157 fireOnConferenceableConnectionsChanged(); 2158 } 2159 } 2160 }; 2161 2162 /** 2163 * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is 2164 * load factor before resizing, 1 means we only expect a single thread to 2165 * access the map so make only a single shard 2166 */ 2167 private final Set<Listener> mListeners = Collections.newSetFromMap( 2168 new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1)); 2169 private final List<Conferenceable> mConferenceables = new ArrayList<>(); 2170 private final List<Conferenceable> mUnmodifiableConferenceables = 2171 Collections.unmodifiableList(mConferenceables); 2172 2173 // The internal telecom call ID associated with this connection. 2174 private String mTelecomCallId; 2175 // The PhoneAccountHandle associated with this connection. 2176 private PhoneAccountHandle mPhoneAccountHandle; 2177 private int mState = STATE_NEW; 2178 private CallAudioState mCallAudioState; 2179 private CallEndpoint mCallEndpoint; 2180 private Uri mAddress; 2181 private int mAddressPresentation = TelecomManager.PRESENTATION_UNKNOWN; 2182 private String mCallerDisplayName; 2183 private int mCallerDisplayNamePresentation; 2184 private boolean mRingbackRequested = false; 2185 private int mConnectionCapabilities; 2186 private int mConnectionProperties; 2187 private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL; 2188 private VideoProvider mVideoProvider; 2189 private boolean mAudioModeIsVoip; 2190 private long mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; 2191 private long mConnectElapsedTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; 2192 private StatusHints mStatusHints; 2193 private int mVideoState; 2194 private DisconnectCause mDisconnectCause; 2195 private Conference mConference; 2196 private ConnectionService mConnectionService; 2197 private Bundle mExtras; 2198 private final Object mExtrasLock = new Object(); 2199 /** 2200 * The direction of the connection; used where an existing connection is created and we need to 2201 * communicate to Telecom whether its incoming or outgoing. 2202 */ 2203 private @Call.Details.CallDirection int mCallDirection = Call.Details.DIRECTION_UNKNOWN; 2204 2205 /** 2206 * Tracks the key set for the extras bundle provided on the last invocation of 2207 * {@link #setExtras(Bundle)}. Used so that on subsequent invocations we can remove any extras 2208 * keys which were set previously but are no longer present in the replacement Bundle. 2209 */ 2210 private Set<String> mPreviousExtraKeys; 2211 2212 /** 2213 * The verification status for an incoming call's phone number. 2214 */ 2215 private @VerificationStatus int mCallerNumberVerificationStatus; 2216 2217 2218 /** 2219 * Create a new Connection. 2220 */ Connection()2221 public Connection() {} 2222 2223 /** 2224 * Returns the Telecom internal call ID associated with this connection. Should only be used 2225 * for debugging and tracing purposes. 2226 * <p> 2227 * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is 2228 * provided to facilitate debugging of the Telephony stack only. 2229 * 2230 * @return The Telecom call ID, or {@code null} if it was not set. 2231 * @hide 2232 */ 2233 @SystemApi getTelecomCallId()2234 public final @Nullable String getTelecomCallId() { 2235 return mTelecomCallId; 2236 } 2237 2238 /** 2239 * @return The address (e.g., phone number) to which this Connection is currently communicating. 2240 */ getAddress()2241 public final Uri getAddress() { 2242 return mAddress; 2243 } 2244 2245 /** 2246 * @return The presentation requirements for the address. 2247 * See {@link TelecomManager} for valid values. 2248 */ getAddressPresentation()2249 public final int getAddressPresentation() { 2250 return mAddressPresentation; 2251 } 2252 2253 /** 2254 * @return The caller display name (CNAP). 2255 */ getCallerDisplayName()2256 public final String getCallerDisplayName() { 2257 return mCallerDisplayName; 2258 } 2259 2260 /** 2261 * @return The presentation requirements for the handle. 2262 * See {@link TelecomManager} for valid values. 2263 */ getCallerDisplayNamePresentation()2264 public final int getCallerDisplayNamePresentation() { 2265 return mCallerDisplayNamePresentation; 2266 } 2267 2268 /** 2269 * @return The state of this Connection. 2270 */ getState()2271 public final int getState() { 2272 return mState; 2273 } 2274 2275 /** 2276 * Returns the video state of the connection. 2277 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 2278 * {@link VideoProfile#STATE_BIDIRECTIONAL}, 2279 * {@link VideoProfile#STATE_TX_ENABLED}, 2280 * {@link VideoProfile#STATE_RX_ENABLED}. 2281 * 2282 * @return The video state of the connection. 2283 */ getVideoState()2284 public final @VideoProfile.VideoState int getVideoState() { 2285 return mVideoState; 2286 } 2287 2288 /** 2289 * @return The audio state of the connection, describing how its audio is currently 2290 * being routed by the system. This is {@code null} if this Connection 2291 * does not directly know about its audio state. 2292 * @deprecated Use {@link #getCallAudioState()} instead. 2293 * @hide 2294 */ 2295 @SystemApi 2296 @Deprecated getAudioState()2297 public final AudioState getAudioState() { 2298 if (mCallAudioState == null) { 2299 return null; 2300 } 2301 return new AudioState(mCallAudioState); 2302 } 2303 2304 /** 2305 * @return The audio state of the connection, describing how its audio is currently 2306 * being routed by the system. This is {@code null} if this Connection 2307 * does not directly know about its audio state. 2308 * @deprecated Use {@link #getCurrentCallEndpoint()}, 2309 * {@link #onAvailableCallEndpointsChanged(List)} and 2310 * {@link #onMuteStateChanged(boolean)} instead. 2311 */ 2312 @Deprecated getCallAudioState()2313 public final CallAudioState getCallAudioState() { 2314 return mCallAudioState; 2315 } 2316 2317 /** 2318 * @return The conference that this connection is a part of. Null if it is not part of any 2319 * conference. 2320 */ getConference()2321 public final Conference getConference() { 2322 return mConference; 2323 } 2324 2325 /** 2326 * Returns whether this connection is requesting that the system play a ringback tone 2327 * on its behalf. 2328 */ isRingbackRequested()2329 public final boolean isRingbackRequested() { 2330 return mRingbackRequested; 2331 } 2332 2333 /** 2334 * @return True if the connection's audio mode is VOIP. 2335 */ getAudioModeIsVoip()2336 public final boolean getAudioModeIsVoip() { 2337 return mAudioModeIsVoip; 2338 } 2339 2340 /** 2341 * Retrieves the connection start time of the {@code Connnection}, if specified. A value of 2342 * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the 2343 * start time of the conference. 2344 * <p> 2345 * Note: This is an implementation detail specific to IMS conference calls over a mobile 2346 * network. 2347 * 2348 * @return The time at which the {@code Connnection} was connected. Will be a value as retrieved 2349 * from {@link System#currentTimeMillis()}. 2350 * 2351 * @hide 2352 */ 2353 @SystemApi getConnectTimeMillis()2354 public final @IntRange(from = 0) long getConnectTimeMillis() { 2355 return mConnectTimeMillis; 2356 } 2357 2358 /** 2359 * Retrieves the connection start time of the {@link Connection}, if specified. A value of 2360 * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the 2361 * start time of the connection. 2362 * <p> 2363 * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock 2364 * changes do not impact the call duration. 2365 * <p> 2366 * Used internally in Telephony when migrating conference participant data for IMS conferences. 2367 * <p> 2368 * The value returned is the same one set using 2369 * {@link #setConnectionStartElapsedRealtimeMillis(long)}. This value is never updated from 2370 * the Telecom framework, so no permission enforcement occurs when retrieving the value with 2371 * this method. 2372 * 2373 * @return The time at which the {@link Connection} was connected. 2374 * 2375 * @hide 2376 */ 2377 @SystemApi getConnectionStartElapsedRealtimeMillis()2378 public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() { 2379 return mConnectElapsedTimeMillis; 2380 } 2381 2382 /** 2383 * @return The status hints for this connection. 2384 */ getStatusHints()2385 public final StatusHints getStatusHints() { 2386 return mStatusHints; 2387 } 2388 2389 /** 2390 * Returns the extras associated with this connection. 2391 * <p> 2392 * Extras should be updated using {@link #putExtras(Bundle)}. 2393 * <p> 2394 * Telecom or an {@link InCallService} can also update the extras via 2395 * {@link android.telecom.Call#putExtras(Bundle)}, and 2396 * {@link Call#removeExtras(List)}. 2397 * <p> 2398 * The connection is notified of changes to the extras made by Telecom or an 2399 * {@link InCallService} by {@link #onExtrasChanged(Bundle)}. 2400 * 2401 * @return The extras associated with this connection. 2402 */ getExtras()2403 public final Bundle getExtras() { 2404 Bundle extras = null; 2405 synchronized (mExtrasLock) { 2406 if (mExtras != null) { 2407 extras = new Bundle(mExtras); 2408 } 2409 } 2410 return extras; 2411 } 2412 2413 /** 2414 * Assign a listener to be notified of state changes. 2415 * 2416 * @param l A listener. 2417 * @return This Connection. 2418 * 2419 * @hide 2420 */ addConnectionListener(Listener l)2421 final Connection addConnectionListener(Listener l) { 2422 mListeners.add(l); 2423 return this; 2424 } 2425 2426 /** 2427 * Remove a previously assigned listener that was being notified of state changes. 2428 * 2429 * @param l A Listener. 2430 * @return This Connection. 2431 * 2432 * @hide 2433 */ removeConnectionListener(Listener l)2434 final Connection removeConnectionListener(Listener l) { 2435 if (l != null) { 2436 mListeners.remove(l); 2437 } 2438 return this; 2439 } 2440 2441 /** 2442 * @return The {@link DisconnectCause} for this connection. 2443 */ getDisconnectCause()2444 public final DisconnectCause getDisconnectCause() { 2445 return mDisconnectCause; 2446 } 2447 2448 /** 2449 * Sets the telecom call ID associated with this Connection. The Telecom Call ID should be used 2450 * ONLY for debugging purposes. 2451 * <p> 2452 * Note: Access to the Telecom internal call ID is used for logging purposes only; this API is 2453 * provided to facilitate debugging of the Telephony stack only. Changing the ID via this 2454 * method does NOT change any functionality in Telephony or Telecom and impacts only logging. 2455 * 2456 * @param callId The telecom call ID. 2457 * @hide 2458 */ 2459 @SystemApi setTelecomCallId(@onNull String callId)2460 public void setTelecomCallId(@NonNull String callId) { 2461 mTelecomCallId = callId; 2462 } 2463 2464 /** 2465 * Inform this Connection that the state of its audio output has been changed externally. 2466 * 2467 * @param state The new audio state. 2468 * @hide 2469 */ setCallAudioState(CallAudioState state)2470 final void setCallAudioState(CallAudioState state) { 2471 checkImmutable(); 2472 Log.d(this, "setAudioState %s", state); 2473 mCallAudioState = state; 2474 onAudioStateChanged(getAudioState()); 2475 onCallAudioStateChanged(state); 2476 } 2477 2478 /** 2479 * Inform this Connection that the audio endpoint has been changed. 2480 * 2481 * @param endpoint The new call endpoint. 2482 * @hide 2483 */ setCallEndpoint(CallEndpoint endpoint)2484 final void setCallEndpoint(CallEndpoint endpoint) { 2485 checkImmutable(); 2486 Log.d(this, "setCallEndpoint %s", endpoint); 2487 mCallEndpoint = endpoint; 2488 onCallEndpointChanged(endpoint); 2489 } 2490 2491 /** 2492 * Inform this Connection that the available call endpoints have been changed. 2493 * 2494 * @param availableEndpoints The available call endpoints. 2495 * @hide 2496 */ setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints)2497 final void setAvailableCallEndpoints(List<CallEndpoint> availableEndpoints) { 2498 checkImmutable(); 2499 Log.d(this, "setAvailableCallEndpoints"); 2500 onAvailableCallEndpointsChanged(availableEndpoints); 2501 } 2502 2503 /** 2504 * Inform this Connection that its audio mute state has been changed. 2505 * 2506 * @param isMuted The new mute state. 2507 * @hide 2508 */ setMuteState(boolean isMuted)2509 final void setMuteState(boolean isMuted) { 2510 checkImmutable(); 2511 Log.d(this, "setMuteState %s", isMuted); 2512 onMuteStateChanged(isMuted); 2513 } 2514 2515 /** 2516 * @param state An integer value of a {@code STATE_*} constant. 2517 * @return A string representation of the value. 2518 */ stateToString(int state)2519 public static String stateToString(int state) { 2520 switch (state) { 2521 case STATE_INITIALIZING: 2522 return "INITIALIZING"; 2523 case STATE_NEW: 2524 return "NEW"; 2525 case STATE_RINGING: 2526 return "RINGING"; 2527 case STATE_DIALING: 2528 return "DIALING"; 2529 case STATE_PULLING_CALL: 2530 return "PULLING_CALL"; 2531 case STATE_ACTIVE: 2532 return "ACTIVE"; 2533 case STATE_HOLDING: 2534 return "HOLDING"; 2535 case STATE_DISCONNECTED: 2536 return "DISCONNECTED"; 2537 default: 2538 Log.wtf(Connection.class, "Unknown state %d", state); 2539 return "UNKNOWN"; 2540 } 2541 } 2542 2543 /** 2544 * Returns the connection's capabilities, as a bit mask of the {@code CAPABILITY_*} constants. 2545 */ getConnectionCapabilities()2546 public final int getConnectionCapabilities() { 2547 return mConnectionCapabilities; 2548 } 2549 2550 /** 2551 * Returns the connection's properties, as a bit mask of the {@code PROPERTY_*} constants. 2552 */ getConnectionProperties()2553 public final int getConnectionProperties() { 2554 return mConnectionProperties; 2555 } 2556 2557 /** 2558 * Returns the connection's supported audio routes. 2559 * 2560 * @hide 2561 */ getSupportedAudioRoutes()2562 public final int getSupportedAudioRoutes() { 2563 return mSupportedAudioRoutes; 2564 } 2565 2566 /** 2567 * Sets the value of the {@link #getAddress()} property. 2568 * 2569 * @param address The new address. 2570 * @param presentation The presentation requirements for the address. 2571 * See {@link TelecomManager} for valid values. 2572 */ setAddress(Uri address, int presentation)2573 public final void setAddress(Uri address, int presentation) { 2574 Log.d(this, "setAddress %s", address); 2575 mAddress = address; 2576 mAddressPresentation = presentation; 2577 for (Listener l : mListeners) { 2578 l.onAddressChanged(this, address, presentation); 2579 } 2580 } 2581 2582 /** 2583 * Sets the caller display name (CNAP). 2584 * 2585 * @param callerDisplayName The new display name. 2586 * @param presentation The presentation requirements for the handle. 2587 * See {@link TelecomManager} for valid values. 2588 */ setCallerDisplayName(String callerDisplayName, int presentation)2589 public final void setCallerDisplayName(String callerDisplayName, int presentation) { 2590 checkImmutable(); 2591 boolean nameChanged = !Objects.equals(mCallerDisplayName, callerDisplayName); 2592 boolean presentationChanged = mCallerDisplayNamePresentation != presentation; 2593 if (nameChanged) { 2594 // Ensure the new name is not clobbering the old one with a null value due to the caller 2595 // wanting to only set the presentation and not knowing the display name. 2596 mCallerDisplayName = callerDisplayName; 2597 } 2598 if (presentationChanged) { 2599 mCallerDisplayNamePresentation = presentation; 2600 } 2601 if (nameChanged || presentationChanged) { 2602 for (Listener l : mListeners) { 2603 l.onCallerDisplayNameChanged(this, mCallerDisplayName, 2604 mCallerDisplayNamePresentation); 2605 } 2606 } 2607 } 2608 2609 /** 2610 * Set the video state for the connection. 2611 * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY}, 2612 * {@link VideoProfile#STATE_BIDIRECTIONAL}, 2613 * {@link VideoProfile#STATE_TX_ENABLED}, 2614 * {@link VideoProfile#STATE_RX_ENABLED}. 2615 * 2616 * @param videoState The new video state. 2617 */ setVideoState(int videoState)2618 public final void setVideoState(int videoState) { 2619 checkImmutable(); 2620 Log.d(this, "setVideoState %d", videoState); 2621 mVideoState = videoState; 2622 for (Listener l : mListeners) { 2623 l.onVideoStateChanged(this, mVideoState); 2624 } 2625 } 2626 2627 /** 2628 * Sets state to active (e.g., an ongoing connection where two or more parties can actively 2629 * communicate). 2630 */ setActive()2631 public final void setActive() { 2632 checkImmutable(); 2633 setRingbackRequested(false); 2634 setState(STATE_ACTIVE); 2635 } 2636 2637 /** 2638 * Sets state to ringing (e.g., an inbound ringing connection). The Connection should not be 2639 * in STATE_RINGING for more than 60 seconds. After 60 seconds, the Connection will 2640 * be disconnected. 2641 */ setRinging()2642 public final void setRinging() { 2643 checkImmutable(); 2644 setState(STATE_RINGING); 2645 } 2646 2647 /** 2648 * Sets state to initializing (this Connection is not yet ready to be used). 2649 */ setInitializing()2650 public final void setInitializing() { 2651 checkImmutable(); 2652 setState(STATE_INITIALIZING); 2653 } 2654 2655 /** 2656 * Sets state to initialized (the Connection has been set up and is now ready to be used). 2657 */ setInitialized()2658 public final void setInitialized() { 2659 checkImmutable(); 2660 setState(STATE_NEW); 2661 } 2662 2663 /** 2664 * Sets state to dialing (e.g., dialing an outbound connection). The Connection should not be 2665 * in STATE_DIALING for more than 60 seconds. After 60 seconds, the Connection will 2666 * be disconnected. 2667 */ setDialing()2668 public final void setDialing() { 2669 checkImmutable(); 2670 setState(STATE_DIALING); 2671 } 2672 2673 /** 2674 * Sets state to pulling (e.g. the connection is being pulled to the local device from another 2675 * device). Only applicable for {@link Connection}s with 2676 * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} and {@link Connection#CAPABILITY_CAN_PULL_CALL}. 2677 */ setPulling()2678 public final void setPulling() { 2679 checkImmutable(); 2680 setState(STATE_PULLING_CALL); 2681 } 2682 2683 /** 2684 * Sets state to be on hold. 2685 */ setOnHold()2686 public final void setOnHold() { 2687 checkImmutable(); 2688 setState(STATE_HOLDING); 2689 } 2690 2691 /** 2692 * Sets the video connection provider. 2693 * @param videoProvider The video provider. 2694 */ setVideoProvider(VideoProvider videoProvider)2695 public final void setVideoProvider(VideoProvider videoProvider) { 2696 checkImmutable(); 2697 mVideoProvider = videoProvider; 2698 for (Listener l : mListeners) { 2699 l.onVideoProviderChanged(this, videoProvider); 2700 } 2701 } 2702 getVideoProvider()2703 public final VideoProvider getVideoProvider() { 2704 return mVideoProvider; 2705 } 2706 2707 /** 2708 * Sets state to disconnected. 2709 * 2710 * @param disconnectCause The reason for the disconnection, as specified by 2711 * {@link DisconnectCause}. 2712 */ setDisconnected(DisconnectCause disconnectCause)2713 public final void setDisconnected(DisconnectCause disconnectCause) { 2714 checkImmutable(); 2715 mDisconnectCause = disconnectCause; 2716 setState(STATE_DISCONNECTED); 2717 Log.d(this, "Disconnected with cause %s", disconnectCause); 2718 for (Listener l : mListeners) { 2719 l.onDisconnected(this, disconnectCause); 2720 } 2721 } 2722 2723 /** 2724 * Informs listeners that this {@code Connection} is in a post-dial wait state. This is done 2725 * when (a) the {@code Connection} is issuing a DTMF sequence; (b) it has encountered a "wait" 2726 * character; and (c) it wishes to inform the In-Call app that it is waiting for the end-user 2727 * to send an {@link #onPostDialContinue(boolean)} signal. 2728 * 2729 * @param remaining The DTMF character sequence remaining to be emitted once the 2730 * {@link #onPostDialContinue(boolean)} is received, including any "wait" characters 2731 * that remaining sequence may contain. 2732 */ setPostDialWait(String remaining)2733 public final void setPostDialWait(String remaining) { 2734 checkImmutable(); 2735 for (Listener l : mListeners) { 2736 l.onPostDialWait(this, remaining); 2737 } 2738 } 2739 2740 /** 2741 * Informs listeners that this {@code Connection} has processed a character in the post-dial 2742 * started state. This is done when (a) the {@code Connection} is issuing a DTMF sequence; 2743 * and (b) it wishes to signal Telecom to play the corresponding DTMF tone locally. 2744 * 2745 * @param nextChar The DTMF character that was just processed by the {@code Connection}. 2746 */ setNextPostDialChar(char nextChar)2747 public final void setNextPostDialChar(char nextChar) { 2748 checkImmutable(); 2749 for (Listener l : mListeners) { 2750 l.onPostDialChar(this, nextChar); 2751 } 2752 } 2753 2754 /** 2755 * Requests that the framework play a ringback tone. This is to be invoked by implementations 2756 * that do not play a ringback tone themselves in the connection's audio stream. 2757 * 2758 * @param ringback Whether the ringback tone is to be played. 2759 */ setRingbackRequested(boolean ringback)2760 public final void setRingbackRequested(boolean ringback) { 2761 checkImmutable(); 2762 if (mRingbackRequested != ringback) { 2763 mRingbackRequested = ringback; 2764 for (Listener l : mListeners) { 2765 l.onRingbackRequested(this, ringback); 2766 } 2767 } 2768 } 2769 2770 /** 2771 * Sets the connection's capabilities as a bit mask of the {@code CAPABILITY_*} constants. 2772 * 2773 * @param connectionCapabilities The new connection capabilities. 2774 */ setConnectionCapabilities(int connectionCapabilities)2775 public final void setConnectionCapabilities(int connectionCapabilities) { 2776 checkImmutable(); 2777 if (mConnectionCapabilities != connectionCapabilities) { 2778 mConnectionCapabilities = connectionCapabilities; 2779 for (Listener l : mListeners) { 2780 l.onConnectionCapabilitiesChanged(this, mConnectionCapabilities); 2781 } 2782 } 2783 } 2784 2785 /** 2786 * Sets the connection's properties as a bit mask of the {@code PROPERTY_*} constants. 2787 * 2788 * @param connectionProperties The new connection properties. 2789 */ setConnectionProperties(int connectionProperties)2790 public final void setConnectionProperties(int connectionProperties) { 2791 checkImmutable(); 2792 if (mConnectionProperties != connectionProperties) { 2793 mConnectionProperties = connectionProperties; 2794 for (Listener l : mListeners) { 2795 l.onConnectionPropertiesChanged(this, mConnectionProperties); 2796 } 2797 } 2798 } 2799 2800 /** 2801 * Sets the supported audio routes. 2802 * 2803 * @param supportedAudioRoutes the supported audio routes as a bitmask. 2804 * See {@link CallAudioState} 2805 * @hide 2806 */ setSupportedAudioRoutes(int supportedAudioRoutes)2807 public final void setSupportedAudioRoutes(int supportedAudioRoutes) { 2808 if ((supportedAudioRoutes 2809 & (CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER)) == 0) { 2810 throw new IllegalArgumentException( 2811 "supported audio routes must include either speaker or earpiece"); 2812 } 2813 2814 if (mSupportedAudioRoutes != supportedAudioRoutes) { 2815 mSupportedAudioRoutes = supportedAudioRoutes; 2816 for (Listener l : mListeners) { 2817 l.onSupportedAudioRoutesChanged(this, mSupportedAudioRoutes); 2818 } 2819 } 2820 } 2821 2822 /** 2823 * Tears down the Connection object. 2824 */ destroy()2825 public final void destroy() { 2826 for (Listener l : mListeners) { 2827 l.onDestroyed(this); 2828 } 2829 } 2830 2831 /** 2832 * Requests that the framework use VOIP audio mode for this connection. 2833 * 2834 * @param isVoip True if the audio mode is VOIP. 2835 */ setAudioModeIsVoip(boolean isVoip)2836 public final void setAudioModeIsVoip(boolean isVoip) { 2837 if (!isVoip && (mConnectionProperties & PROPERTY_SELF_MANAGED) == PROPERTY_SELF_MANAGED) { 2838 Log.i(this, 2839 "setAudioModeIsVoip: Ignored request to set a self-managed connection's" 2840 + " audioModeIsVoip to false. Doing so can cause unwanted behavior."); 2841 return; 2842 } 2843 checkImmutable(); 2844 mAudioModeIsVoip = isVoip; 2845 for (Listener l : mListeners) { 2846 l.onAudioModeIsVoipChanged(this, isVoip); 2847 } 2848 } 2849 2850 /** 2851 * Sets the time at which a call became active on this Connection. This is set only 2852 * when a conference call becomes active on this connection. 2853 * <p> 2854 * This time corresponds to the date/time of connection and is stored in the call log in 2855 * {@link android.provider.CallLog.Calls#DATE}. 2856 * <p> 2857 * Used by telephony to maintain calls associated with an IMS Conference. 2858 * 2859 * @param connectTimeMillis The connection time, in milliseconds. Should be set using a value 2860 * obtained from {@link System#currentTimeMillis()}. 2861 * 2862 * @hide 2863 */ 2864 @SystemApi 2865 @RequiresPermission(MODIFY_PHONE_STATE) setConnectTimeMillis(@ntRangefrom = 0) long connectTimeMillis)2866 public final void setConnectTimeMillis(@IntRange(from = 0) long connectTimeMillis) { 2867 mConnectTimeMillis = connectTimeMillis; 2868 } 2869 2870 /** 2871 * Sets the time at which a call became active on this Connection. This is set only 2872 * when a conference call becomes active on this connection. 2873 * <p> 2874 * This time is used to establish the duration of a call. It uses 2875 * {@link SystemClock#elapsedRealtime()} to ensure that the call duration is not impacted by 2876 * time zone changes during a call. The difference between the current 2877 * {@link SystemClock#elapsedRealtime()} and the value set at the connection start time is used 2878 * to populate {@link android.provider.CallLog.Calls#DURATION} in the call log. 2879 * <p> 2880 * Used by telephony to maintain calls associated with an IMS Conference. 2881 * 2882 * @param connectElapsedTimeMillis The connection time, in milliseconds. Stored in the format 2883 * {@link SystemClock#elapsedRealtime()}. 2884 * @hide 2885 */ 2886 @SystemApi 2887 @RequiresPermission(MODIFY_PHONE_STATE) setConnectionStartElapsedRealtimeMillis( @lapsedRealtimeLong long connectElapsedTimeMillis)2888 public final void setConnectionStartElapsedRealtimeMillis( 2889 @ElapsedRealtimeLong long connectElapsedTimeMillis) { 2890 mConnectElapsedTimeMillis = connectElapsedTimeMillis; 2891 } 2892 2893 /** 2894 * Sets the label and icon status to display in the in-call UI. 2895 * 2896 * @param statusHints The status label and icon to set. 2897 */ setStatusHints(StatusHints statusHints)2898 public final void setStatusHints(StatusHints statusHints) { 2899 checkImmutable(); 2900 mStatusHints = statusHints; 2901 for (Listener l : mListeners) { 2902 l.onStatusHintsChanged(this, statusHints); 2903 } 2904 } 2905 2906 /** 2907 * Sets the connections with which this connection can be conferenced. 2908 * 2909 * @param conferenceableConnections The set of connections this connection can conference with. 2910 */ setConferenceableConnections(List<Connection> conferenceableConnections)2911 public final void setConferenceableConnections(List<Connection> conferenceableConnections) { 2912 checkImmutable(); 2913 clearConferenceableList(); 2914 for (Connection c : conferenceableConnections) { 2915 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 2916 // small amount of items here. 2917 if (!mConferenceables.contains(c)) { 2918 c.addConnectionListener(mConnectionDeathListener); 2919 mConferenceables.add(c); 2920 } 2921 } 2922 fireOnConferenceableConnectionsChanged(); 2923 } 2924 2925 /** 2926 * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections 2927 * or conferences with which this connection can be conferenced. 2928 * 2929 * @param conferenceables The conferenceables. 2930 */ setConferenceables(List<Conferenceable> conferenceables)2931 public final void setConferenceables(List<Conferenceable> conferenceables) { 2932 clearConferenceableList(); 2933 for (Conferenceable c : conferenceables) { 2934 // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a 2935 // small amount of items here. 2936 if (!mConferenceables.contains(c)) { 2937 if (c instanceof Connection) { 2938 Connection connection = (Connection) c; 2939 connection.addConnectionListener(mConnectionDeathListener); 2940 } else if (c instanceof Conference) { 2941 Conference conference = (Conference) c; 2942 conference.addListener(mConferenceDeathListener); 2943 } 2944 mConferenceables.add(c); 2945 } 2946 } 2947 fireOnConferenceableConnectionsChanged(); 2948 } 2949 2950 /** 2951 * Resets the CDMA connection time. 2952 * <p> 2953 * This is an implementation detail specific to legacy CDMA calls on mobile networks. 2954 * @hide 2955 */ 2956 @SystemApi resetConnectionTime()2957 public final void resetConnectionTime() { 2958 for (Listener l : mListeners) { 2959 l.onConnectionTimeReset(this); 2960 } 2961 } 2962 2963 /** 2964 * Returns the connections or conferences with which this connection can be conferenced. 2965 */ getConferenceables()2966 public final List<Conferenceable> getConferenceables() { 2967 return mUnmodifiableConferenceables; 2968 } 2969 2970 /** 2971 * @hide 2972 */ setConnectionService(ConnectionService connectionService)2973 public final void setConnectionService(ConnectionService connectionService) { 2974 checkImmutable(); 2975 if (mConnectionService != null) { 2976 Log.e(this, new Exception(), "Trying to set ConnectionService on a connection " + 2977 "which is already associated with another ConnectionService."); 2978 } else { 2979 mConnectionService = connectionService; 2980 } 2981 } 2982 2983 /** 2984 * @hide 2985 */ unsetConnectionService(ConnectionService connectionService)2986 public final void unsetConnectionService(ConnectionService connectionService) { 2987 if (mConnectionService != connectionService) { 2988 Log.e(this, new Exception(), "Trying to remove ConnectionService from a Connection " + 2989 "that does not belong to the ConnectionService."); 2990 } else { 2991 mConnectionService = null; 2992 } 2993 } 2994 2995 /** 2996 * Sets the conference that this connection is a part of. This will fail if the connection is 2997 * already part of a conference. {@link #resetConference} to un-set the conference first. 2998 * 2999 * @param conference The conference. 3000 * @return {@code true} if the conference was successfully set. 3001 * @hide 3002 */ setConference(Conference conference)3003 public final boolean setConference(Conference conference) { 3004 checkImmutable(); 3005 // We check to see if it is already part of another conference. 3006 if (mConference == null) { 3007 mConference = conference; 3008 if (mConnectionService != null && mConnectionService.containsConference(conference)) { 3009 fireConferenceChanged(); 3010 } 3011 return true; 3012 } 3013 return false; 3014 } 3015 3016 /** 3017 * Resets the conference that this connection is a part of. 3018 * @hide 3019 */ resetConference()3020 public final void resetConference() { 3021 if (mConference != null) { 3022 Log.d(this, "Conference reset"); 3023 mConference = null; 3024 fireConferenceChanged(); 3025 } 3026 } 3027 3028 /** 3029 * Set some extras that can be associated with this {@code Connection}. 3030 * <p> 3031 * New or existing keys are replaced in the {@code Connection} extras. Keys which are no longer 3032 * in the new extras, but were present the last time {@code setExtras} was called are removed. 3033 * <p> 3034 * Alternatively you may use the {@link #putExtras(Bundle)}, and 3035 * {@link #removeExtras(String...)} methods to modify the extras. 3036 * <p> 3037 * No assumptions should be made as to how an In-Call UI or service will handle these extras. 3038 * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts. 3039 * 3040 * @param extras The extras associated with this {@code Connection}. 3041 */ setExtras(@ullable Bundle extras)3042 public final void setExtras(@Nullable Bundle extras) { 3043 checkImmutable(); 3044 3045 // Add/replace any new or changed extras values. 3046 putExtras(extras); 3047 3048 // If we have used "setExtras" in the past, compare the key set from the last invocation to 3049 // the current one and remove any keys that went away. 3050 if (mPreviousExtraKeys != null) { 3051 List<String> toRemove = new ArrayList<String>(); 3052 for (String oldKey : mPreviousExtraKeys) { 3053 if (extras == null || !extras.containsKey(oldKey)) { 3054 toRemove.add(oldKey); 3055 } 3056 } 3057 if (!toRemove.isEmpty()) { 3058 removeExtras(toRemove); 3059 } 3060 } 3061 3062 // Track the keys the last time set called setExtras. This way, the next time setExtras is 3063 // called we can see if the caller has removed any extras values. 3064 if (mPreviousExtraKeys == null) { 3065 mPreviousExtraKeys = new ArraySet<String>(); 3066 } 3067 mPreviousExtraKeys.clear(); 3068 if (extras != null) { 3069 mPreviousExtraKeys.addAll(extras.keySet()); 3070 } 3071 } 3072 3073 /** 3074 * Adds some extras to this {@code Connection}. Existing keys are replaced and new ones are 3075 * added. 3076 * <p> 3077 * No assumptions should be made as to how an In-Call UI or service will handle these extras. 3078 * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts. 3079 * 3080 * @param extras The extras to add. 3081 */ putExtras(@onNull Bundle extras)3082 public final void putExtras(@NonNull Bundle extras) { 3083 checkImmutable(); 3084 if (extras == null) { 3085 return; 3086 } 3087 // Creating a duplicate bundle so we don't have to synchronize on mExtrasLock while calling 3088 // the listeners. 3089 Bundle listenerExtras; 3090 synchronized (mExtrasLock) { 3091 if (mExtras == null) { 3092 mExtras = new Bundle(); 3093 } 3094 mExtras.putAll(extras); 3095 listenerExtras = new Bundle(mExtras); 3096 } 3097 for (Listener l : mListeners) { 3098 // Create a new clone of the extras for each listener so that they don't clobber 3099 // each other 3100 l.onExtrasChanged(this, new Bundle(listenerExtras)); 3101 } 3102 } 3103 3104 /** 3105 * Removes extras from this {@code Connection}. 3106 * 3107 * @param keys The keys of the extras to remove. 3108 */ removeExtras(List<String> keys)3109 public final void removeExtras(List<String> keys) { 3110 synchronized (mExtrasLock) { 3111 if (mExtras != null) { 3112 for (String key : keys) { 3113 mExtras.remove(key); 3114 } 3115 } 3116 } 3117 List<String> unmodifiableKeys = Collections.unmodifiableList(keys); 3118 for (Listener l : mListeners) { 3119 l.onExtrasRemoved(this, unmodifiableKeys); 3120 } 3121 } 3122 3123 /** 3124 * Removes extras from this {@code Connection}. 3125 * 3126 * @param keys The keys of the extras to remove. 3127 */ removeExtras(String .... keys)3128 public final void removeExtras(String ... keys) { 3129 removeExtras(Arrays.asList(keys)); 3130 } 3131 3132 /** 3133 * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will 3134 * be change to the {@link #getCallAudioState()}. 3135 * <p> 3136 * Used by self-managed {@link ConnectionService}s which wish to change the audio route for a 3137 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3138 * <p> 3139 * See also {@link InCallService#setAudioRoute(int)}. 3140 * 3141 * @param route The audio route to use (one of {@link CallAudioState#ROUTE_BLUETOOTH}, 3142 * {@link CallAudioState#ROUTE_EARPIECE}, {@link CallAudioState#ROUTE_SPEAKER}, or 3143 * {@link CallAudioState#ROUTE_WIRED_HEADSET}). 3144 * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)} 3145 * instead. 3146 */ 3147 @Deprecated setAudioRoute(int route)3148 public final void setAudioRoute(int route) { 3149 for (Listener l : mListeners) { 3150 l.onAudioRouteChanged(this, route, null); 3151 } 3152 } 3153 3154 /** 3155 * Request audio routing to a specific bluetooth device. Calling this method may result in 3156 * the device routing audio to a different bluetooth device than the one specified if the 3157 * bluetooth stack is unable to route audio to the requested device. 3158 * A list of available devices can be obtained via 3159 * {@link CallAudioState#getSupportedBluetoothDevices()} 3160 * 3161 * <p> 3162 * Used by self-managed {@link ConnectionService}s which wish to use bluetooth audio for a 3163 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3164 * <p> 3165 * See also {@link InCallService#requestBluetoothAudio(BluetoothDevice)} 3166 * @param bluetoothDevice The bluetooth device to connect to. 3167 * @deprecated Use {@link #requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)} 3168 * instead. 3169 */ 3170 @Deprecated requestBluetoothAudio(@onNull BluetoothDevice bluetoothDevice)3171 public void requestBluetoothAudio(@NonNull BluetoothDevice bluetoothDevice) { 3172 for (Listener l : mListeners) { 3173 l.onAudioRouteChanged(this, CallAudioState.ROUTE_BLUETOOTH, 3174 bluetoothDevice.getAddress()); 3175 } 3176 } 3177 3178 /** 3179 * Request audio routing to a specific CallEndpoint. Clients should not define their own 3180 * CallEndpoint when requesting a change. Instead, the new endpoint should be one of the valid 3181 * endpoints provided by {@link #onAvailableCallEndpointsChanged(List)}. 3182 * When this request is honored, there will be change to the {@link #getCurrentCallEndpoint()}. 3183 * <p> 3184 * Used by self-managed {@link ConnectionService}s which wish to change the CallEndpoint for a 3185 * self-managed {@link Connection} (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}.) 3186 * <p> 3187 * See also 3188 * {@link InCallService#requestCallEndpointChange(CallEndpoint, Executor, OutcomeReceiver)}. 3189 * 3190 * @param endpoint The call endpoint to use. 3191 * @param executor The executor of where the callback will execute. 3192 * @param callback The callback to notify the result of the endpoint change. 3193 */ requestCallEndpointChange(@onNull CallEndpoint endpoint, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Void, CallEndpointException> callback)3194 public final void requestCallEndpointChange(@NonNull CallEndpoint endpoint, 3195 @NonNull @CallbackExecutor Executor executor, 3196 @NonNull OutcomeReceiver<Void, CallEndpointException> callback) { 3197 for (Listener l : mListeners) { 3198 l.onEndpointChanged(this, endpoint, executor, callback); 3199 } 3200 } 3201 3202 /** 3203 * Obtains the current CallEndpoint. 3204 * 3205 * @return An object encapsulating the CallEndpoint. 3206 */ 3207 @NonNull getCurrentCallEndpoint()3208 public final CallEndpoint getCurrentCallEndpoint() { 3209 return mCallEndpoint; 3210 } 3211 3212 /** 3213 * Informs listeners that a previously requested RTT session via 3214 * {@link ConnectionRequest#isRequestingRtt()} or 3215 * {@link #onStartRtt(RttTextStream)} has succeeded. 3216 */ sendRttInitiationSuccess()3217 public final void sendRttInitiationSuccess() { 3218 mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this)); 3219 } 3220 3221 /** 3222 * Informs listeners that a previously requested RTT session via 3223 * {@link ConnectionRequest#isRequestingRtt()} or {@link #onStartRtt(RttTextStream)} 3224 * has failed. 3225 * @param reason One of the reason codes defined in {@link RttModifyStatus}, with the 3226 * exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. 3227 */ sendRttInitiationFailure(int reason)3228 public final void sendRttInitiationFailure(int reason) { 3229 mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason)); 3230 } 3231 3232 /** 3233 * Informs listeners that a currently active RTT session has been terminated by the remote 3234 * side of the coll. 3235 */ sendRttSessionRemotelyTerminated()3236 public final void sendRttSessionRemotelyTerminated() { 3237 mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this)); 3238 } 3239 3240 /** 3241 * Informs listeners that the remote side of the call has requested an upgrade to include an 3242 * RTT session in the call. 3243 */ sendRemoteRttRequest()3244 public final void sendRemoteRttRequest() { 3245 mListeners.forEach((l) -> l.onRemoteRttRequest(Connection.this)); 3246 } 3247 3248 /** 3249 * Query the device's location in order to place an Emergency Call. 3250 * Only SIM call managers can call this method for Connections representing Emergency calls. 3251 * If a previous location query request is not completed, the new location query request will 3252 * be rejected and return a QueryLocationException with 3253 * {@code QueryLocationException#ERROR_PREVIOUS_REQUEST_EXISTS} 3254 * 3255 * @param timeoutMillis long: Timeout in millis waiting for query response (MAX:5000, MIN:100). 3256 * @param provider String: the location provider name, This value cannot be null. 3257 * It is the caller's responsibility to select an enabled provider. The caller 3258 * can use {@link android.location.LocationManager#getProviders(boolean)} 3259 * to choose one of the enabled providers and pass it in. 3260 * @param executor The executor of where the callback will execute. 3261 * @param callback The callback to notify the result of queryLocation. 3262 */ queryLocationForEmergency( @ntRangefrom = 100, to = 5000) long timeoutMillis, @NonNull String provider, @NonNull @CallbackExecutor Executor executor, @NonNull OutcomeReceiver<Location, QueryLocationException> callback)3263 public final void queryLocationForEmergency( 3264 @IntRange(from = 100, to = 5000) long timeoutMillis, 3265 @NonNull String provider, 3266 @NonNull @CallbackExecutor Executor executor, 3267 @NonNull OutcomeReceiver<Location, QueryLocationException> callback) { 3268 if (provider == null || executor == null || callback == null) { 3269 throw new IllegalArgumentException("There are arguments that must not be null"); 3270 } 3271 if (timeoutMillis < 100 || timeoutMillis > 5000) { 3272 throw new IllegalArgumentException("The timeoutMillis should be min 100, max 5000"); 3273 } 3274 mListeners.forEach((l) -> 3275 l.onQueryLocation(this, timeoutMillis, provider, executor, callback)); 3276 } 3277 3278 /** 3279 * Notifies this Connection that the {@link #getAudioState()} property has a new value. 3280 * 3281 * @param state The new connection audio state. 3282 * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState)} instead. 3283 * @hide 3284 */ 3285 @SystemApi 3286 @Deprecated onAudioStateChanged(AudioState state)3287 public void onAudioStateChanged(AudioState state) {} 3288 3289 /** 3290 * Notifies this Connection that the {@link #getCallAudioState()} property has a new value. 3291 * 3292 * @param state The new connection audio state. 3293 * @deprecated Use {@link #onCallEndpointChanged(CallEndpoint)}, 3294 * {@link #onAvailableCallEndpointsChanged(List)} and 3295 * {@link #onMuteStateChanged(boolean)} instead. 3296 */ 3297 @Deprecated onCallAudioStateChanged(CallAudioState state)3298 public void onCallAudioStateChanged(CallAudioState state) {} 3299 3300 /** 3301 * Notifies this Connection that the audio endpoint has been changed. 3302 * 3303 * @param callEndpoint The current CallEndpoint. 3304 */ onCallEndpointChanged(@onNull CallEndpoint callEndpoint)3305 public void onCallEndpointChanged(@NonNull CallEndpoint callEndpoint) {} 3306 3307 /** 3308 * Notifies this Connection that the available call endpoints have been changed. 3309 * 3310 * @param availableEndpoints The set of available CallEndpoint. 3311 */ onAvailableCallEndpointsChanged(@onNull List<CallEndpoint> availableEndpoints)3312 public void onAvailableCallEndpointsChanged(@NonNull List<CallEndpoint> availableEndpoints) {} 3313 3314 /** 3315 * Notifies this Connection that its audio mute state has been changed. 3316 * 3317 * @param isMuted The current mute state. 3318 */ onMuteStateChanged(boolean isMuted)3319 public void onMuteStateChanged(boolean isMuted) {} 3320 3321 /** 3322 * Inform this Connection when it will or will not be tracked by an {@link InCallService} which 3323 * can provide an InCall UI. 3324 * This is primarily intended for use by Connections reported by self-managed 3325 * {@link ConnectionService} which typically maintain their own UI. 3326 * 3327 * @param isUsingAlternativeUi Indicates whether an InCallService that can provide InCall UI is 3328 * currently tracking the self-managed call. 3329 */ onUsingAlternativeUi(boolean isUsingAlternativeUi)3330 public void onUsingAlternativeUi(boolean isUsingAlternativeUi) {} 3331 3332 /** 3333 * Inform this Conenection when it will or will not be tracked by an non-UI 3334 * {@link InCallService}. 3335 * 3336 * @param isTracked Indicates whether an non-UI InCallService is currently tracking the 3337 * self-managed call. 3338 */ onTrackedByNonUiService(boolean isTracked)3339 public void onTrackedByNonUiService(boolean isTracked) {} 3340 3341 /** 3342 * Notifies this Connection of an internal state change. This method is called after the 3343 * state is changed. 3344 * 3345 * @param state The new state, one of the {@code STATE_*} constants. 3346 */ onStateChanged(int state)3347 public void onStateChanged(int state) {} 3348 3349 /** 3350 * Notifies this Connection of a request to play a DTMF tone. 3351 * 3352 * @param c A DTMF character. 3353 */ onPlayDtmfTone(char c)3354 public void onPlayDtmfTone(char c) {} 3355 3356 /** 3357 * Notifies this Connection of a request to stop any currently playing DTMF tones. 3358 */ onStopDtmfTone()3359 public void onStopDtmfTone() {} 3360 3361 /** 3362 * Notifies this Connection of a request to disconnect. 3363 */ onDisconnect()3364 public void onDisconnect() {} 3365 3366 /** 3367 * Notifies this Connection of a request to separate from its parent conference. 3368 */ onSeparate()3369 public void onSeparate() {} 3370 3371 /** 3372 * Supports initiation of a conference call by directly adding participants to an ongoing call. 3373 * 3374 * @param participants with which conference call will be formed. 3375 */ onAddConferenceParticipants(@onNull List<Uri> participants)3376 public void onAddConferenceParticipants(@NonNull List<Uri> participants) {} 3377 3378 /** 3379 * Notifies this Connection of a request to abort. 3380 */ onAbort()3381 public void onAbort() {} 3382 3383 /** 3384 * Notifies this Connection of a request to hold. {@link Connection#setOnHold} should be within 3385 * the onHold() body in order to transition the call state to {@link Connection#STATE_HOLDING}. 3386 * <p> 3387 * Note: If the Connection does not transition to {@link Connection#STATE_HOLDING} within 2 3388 * seconds, the call will be disconnected. 3389 */ onHold()3390 public void onHold() {} 3391 3392 /** 3393 * Notifies this Connection of a request to exit a hold state. 3394 */ onUnhold()3395 public void onUnhold() {} 3396 3397 /** 3398 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3399 * a request to accept. 3400 * <p> 3401 * For managed {@link ConnectionService}s, this will be called when the user answers a call via 3402 * the default dialer's {@link InCallService}. 3403 * <p> 3404 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3405 * Telecom framework may request that the call is answered in the following circumstances: 3406 * <ul> 3407 * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> 3408 * <li>A car mode {@link InCallService} is in use which has declared 3409 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3410 * {@link InCallService} will be able to see calls from self-managed 3411 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3412 * behalf.</li> 3413 * </ul> 3414 * @param videoState The video state in which to answer the connection. 3415 */ onAnswer(int videoState)3416 public void onAnswer(int videoState) {} 3417 3418 /** 3419 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3420 * a request to accept. 3421 * <p> 3422 * For managed {@link ConnectionService}s, this will be called when the user answers a call via 3423 * the default dialer's {@link InCallService}. 3424 * <p> 3425 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3426 * Telecom framework may request that the call is answered in the following circumstances: 3427 * <ul> 3428 * <li>The user chooses to answer an incoming call via a Bluetooth device.</li> 3429 * <li>A car mode {@link InCallService} is in use which has declared 3430 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3431 * {@link InCallService} will be able to see calls from self-managed 3432 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3433 * behalf.</li> 3434 * </ul> 3435 */ onAnswer()3436 public void onAnswer() { 3437 onAnswer(VideoProfile.STATE_AUDIO_ONLY); 3438 } 3439 3440 /** 3441 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3442 * a request to deflect. 3443 */ onDeflect(Uri address)3444 public void onDeflect(Uri address) {} 3445 3446 /** 3447 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3448 * a request to reject. 3449 * <p> 3450 * For managed {@link ConnectionService}s, this will be called when the user rejects a call via 3451 * the default dialer's {@link InCallService}. 3452 * <p> 3453 * Although a self-managed {@link ConnectionService} provides its own incoming call UI, the 3454 * Telecom framework may request that the call is rejected in the following circumstances: 3455 * <ul> 3456 * <li>The user chooses to reject an incoming call via a Bluetooth device.</li> 3457 * <li>A car mode {@link InCallService} is in use which has declared 3458 * {@link TelecomManager#METADATA_INCLUDE_SELF_MANAGED_CALLS} in its manifest. Such an 3459 * {@link InCallService} will be able to see calls from self-managed 3460 * {@link ConnectionService}s, and will be able to display an incoming call UI on their 3461 * behalf.</li> 3462 * </ul> 3463 */ onReject()3464 public void onReject() {} 3465 3466 /** 3467 * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject. 3468 * <p> 3469 * For managed {@link ConnectionService}s, this will be called when the user rejects a call via 3470 * the default dialer's {@link InCallService} using {@link Call#reject(int)}. 3471 * @param rejectReason the reason the user provided for rejecting the call. 3472 */ onReject(@ndroid.telecom.Call.RejectReason int rejectReason)3473 public void onReject(@android.telecom.Call.RejectReason int rejectReason) { 3474 // to be implemented by ConnectionService. 3475 } 3476 3477 /** 3478 * Notifies this Connection, which is in {@link #STATE_RINGING}, of 3479 * a request to reject with a message. 3480 */ onReject(String replyMessage)3481 public void onReject(String replyMessage) {} 3482 3483 /** 3484 * Notifies this Connection, a request to transfer to a target number. 3485 * @param number the number to transfer this {@link Connection} to. 3486 * @param isConfirmationRequired when {@code true}, the {@link ConnectionService} 3487 * should wait until the transfer has successfully completed before disconnecting 3488 * the current {@link Connection}. 3489 * When {@code false}, the {@link ConnectionService} should signal the network to 3490 * perform the transfer, but should immediately disconnect the call regardless of 3491 * the outcome of the transfer. 3492 * @hide 3493 */ onTransfer(@onNull Uri number, boolean isConfirmationRequired)3494 public void onTransfer(@NonNull Uri number, boolean isConfirmationRequired) {} 3495 3496 /** 3497 * Notifies this Connection, a request to transfer to another Connection. 3498 * @param otherConnection the {@link Connection} to transfer this call to. 3499 * @hide 3500 */ onTransfer(@onNull Connection otherConnection)3501 public void onTransfer(@NonNull Connection otherConnection) {} 3502 3503 /** 3504 * Notifies this Connection of a request to silence the ringer. 3505 * <p> 3506 * The ringer may be silenced by any of the following methods: 3507 * <ul> 3508 * <li>{@link TelecomManager#silenceRinger()}</li> 3509 * <li>The user presses the volume-down button while a call is ringing.</li> 3510 * </ul> 3511 * <p> 3512 * Self-managed {@link ConnectionService} implementations should override this method in their 3513 * {@link Connection} implementation and implement logic to silence their app's ringtone. If 3514 * your app set the ringtone as part of the incoming call {@link Notification} (see 3515 * {@link #onShowIncomingCallUi()}), it should re-post the notification now, except call 3516 * {@link android.app.Notification.Builder#setOnlyAlertOnce(boolean)} with {@code true}. This 3517 * will ensure the ringtone sound associated with your {@link android.app.NotificationChannel} 3518 * stops playing. 3519 */ onSilence()3520 public void onSilence() {} 3521 3522 /** 3523 * Notifies this Connection whether the user wishes to proceed with the post-dial DTMF codes. 3524 */ onPostDialContinue(boolean proceed)3525 public void onPostDialContinue(boolean proceed) {} 3526 3527 /** 3528 * Notifies this Connection of a request to pull an external call to the local device. 3529 * <p> 3530 * The {@link InCallService} issues a request to pull an external call to the local device via 3531 * {@link Call#pullExternalCall()}. 3532 * <p> 3533 * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} 3534 * capability and {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property bits must be set. 3535 * <p> 3536 * For more information on external calls, see {@link Connection#PROPERTY_IS_EXTERNAL_CALL}. 3537 */ onPullExternalCall()3538 public void onPullExternalCall() {} 3539 3540 /** 3541 * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}. 3542 * <p> 3543 * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}. 3544 * <p> 3545 * Where possible, the Connection should make an attempt to handle {@link Call} events which 3546 * are part of the {@code android.telecom.*} namespace. The Connection should ignore any events 3547 * it does not wish to handle. Unexpected events should be handled gracefully, as it is 3548 * possible that a {@link InCallService} has defined its own Call events which a Connection is 3549 * not aware of. 3550 * <p> 3551 * See also {@link Call#sendCallEvent(String, Bundle)}. 3552 * 3553 * @param event The call event. 3554 * @param extras Extras associated with the call event. 3555 */ onCallEvent(String event, Bundle extras)3556 public void onCallEvent(String event, Bundle extras) {} 3557 3558 /** 3559 * Notifies this {@link Connection} that a handover has completed. 3560 * <p> 3561 * A handover is initiated with {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, 3562 * Bundle)} on the initiating side of the handover, and 3563 * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}. 3564 */ onHandoverComplete()3565 public void onHandoverComplete() {} 3566 3567 /** 3568 * Notifies this {@link Connection} of a change to the extras made outside the 3569 * {@link ConnectionService}. 3570 * <p> 3571 * These extras changes can originate from Telecom itself, or from an {@link InCallService} via 3572 * the {@link android.telecom.Call#putExtras(Bundle)} and 3573 * {@link Call#removeExtras(List)}. 3574 * 3575 * @param extras The new extras bundle. 3576 */ onExtrasChanged(Bundle extras)3577 public void onExtrasChanged(Bundle extras) {} 3578 3579 /** 3580 * Notifies this {@link Connection} that its {@link ConnectionService} is responsible for 3581 * displaying its incoming call user interface for the {@link Connection}. 3582 * <p> 3583 * Will only be called for incoming calls added via a self-managed {@link ConnectionService} 3584 * (see {@link PhoneAccount#CAPABILITY_SELF_MANAGED}), where the {@link ConnectionService} 3585 * should show its own incoming call user interface. 3586 * <p> 3587 * Where there are ongoing calls in other self-managed {@link ConnectionService}s, or in a 3588 * regular {@link ConnectionService}, and it is not possible to hold these other calls, the 3589 * Telecom framework will display its own incoming call user interface to allow the user to 3590 * choose whether to answer the new incoming call and disconnect other ongoing calls, or to 3591 * reject the new incoming call. 3592 * <p> 3593 * You should trigger the display of the incoming call user interface for your application by 3594 * showing a {@link Notification} with a full-screen {@link Intent} specified. 3595 * 3596 * In your application code, you should create a {@link android.app.NotificationChannel} for 3597 * incoming call notifications from your app: 3598 * <pre><code> 3599 * NotificationChannel channel = new NotificationChannel(YOUR_CHANNEL_ID, "Incoming Calls", 3600 * NotificationManager.IMPORTANCE_MAX); 3601 * // other channel setup stuff goes here. 3602 * 3603 * // We'll use the default system ringtone for our incoming call notification channel. You can 3604 * // use your own audio resource here. 3605 * Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); 3606 * channel.setSound(ringtoneUri, new AudioAttributes.Builder() 3607 * // Setting the AudioAttributes is important as it identifies the purpose of your 3608 * // notification sound. 3609 * .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) 3610 * .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 3611 * .build()); 3612 * 3613 * NotificationManager mgr = getSystemService(NotificationManager.class); 3614 * mgr.createNotificationChannel(channel); 3615 * </code></pre> 3616 * When it comes time to post a notification for your incoming call, ensure it uses your 3617 * incoming call {@link android.app.NotificationChannel}. 3618 * <pre><code> 3619 * // Create an intent which triggers your fullscreen incoming call user interface. 3620 * Intent intent = new Intent(Intent.ACTION_MAIN, null); 3621 * intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK); 3622 * intent.setClass(context, YourIncomingCallActivity.class); 3623 * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED); 3624 * 3625 * // Build the notification as an ongoing high priority item; this ensures it will show as 3626 * // a heads up notification which slides down over top of the current content. 3627 * final Notification.Builder builder = new Notification.Builder(context); 3628 * builder.setOngoing(true); 3629 * builder.setPriority(Notification.PRIORITY_HIGH); 3630 * 3631 * // Set notification content intent to take user to fullscreen UI if user taps on the 3632 * // notification body. 3633 * builder.setContentIntent(pendingIntent); 3634 * // Set full screen intent to trigger display of the fullscreen UI when the notification 3635 * // manager deems it appropriate. 3636 * builder.setFullScreenIntent(pendingIntent, true); 3637 * 3638 * // Setup notification content. 3639 * builder.setSmallIcon( yourIconResourceId ); 3640 * builder.setContentTitle("Your notification title"); 3641 * builder.setContentText("Your notification content."); 3642 * 3643 * // Set notification as insistent to cause your ringtone to loop. 3644 * Notification notification = builder.build(); 3645 * notification.flags |= Notification.FLAG_INSISTENT; 3646 * 3647 * // Use builder.addAction(..) to add buttons to answer or reject the call. 3648 * NotificationManager notificationManager = mContext.getSystemService( 3649 * NotificationManager.class); 3650 * notificationManager.notify(YOUR_CHANNEL_ID, YOUR_TAG, YOUR_ID, notification); 3651 * </code></pre> 3652 */ onShowIncomingCallUi()3653 public void onShowIncomingCallUi() {} 3654 3655 /** 3656 * Notifies this {@link Connection} that the user has requested an RTT session. 3657 * The connection service should call {@link #sendRttInitiationSuccess} or 3658 * {@link #sendRttInitiationFailure} to inform Telecom of the success or failure of the 3659 * request, respectively. 3660 * @param rttTextStream The object that should be used to send text to or receive text from 3661 * the in-call app. 3662 */ onStartRtt(@onNull RttTextStream rttTextStream)3663 public void onStartRtt(@NonNull RttTextStream rttTextStream) {} 3664 3665 /** 3666 * Notifies this {@link Connection} that it should terminate any existing RTT communication 3667 * channel. No response to Telecom is needed for this method. 3668 */ onStopRtt()3669 public void onStopRtt() {} 3670 3671 /** 3672 * Notifies this connection of a response to a previous remotely-initiated RTT upgrade 3673 * request sent via {@link #sendRemoteRttRequest}. Acceptance of the request is 3674 * indicated by the supplied {@link RttTextStream} being non-null, and rejection is 3675 * indicated by {@code rttTextStream} being {@code null} 3676 * @param rttTextStream The object that should be used to send text to or receive text from 3677 * the in-call app. 3678 */ handleRttUpgradeResponse(@ullable RttTextStream rttTextStream)3679 public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {} 3680 3681 /** 3682 * Information provided to a {@link Connection} upon completion of call filtering in Telecom. 3683 * 3684 * @hide 3685 */ 3686 @SystemApi 3687 public static final class CallFilteringCompletionInfo implements Parcelable { 3688 private final boolean mIsBlocked; 3689 private final boolean mIsInContacts; 3690 private final CallScreeningService.CallResponse mCallResponse; 3691 private final ComponentName mCallScreeningComponent; 3692 3693 /** 3694 * Constructor for {@link CallFilteringCompletionInfo} 3695 * 3696 * @param isBlocked Whether any part of the call filtering process indicated that this call 3697 * should be blocked. 3698 * @param isInContacts Whether the caller is in the user's contacts. 3699 * @param callResponse The instance of {@link CallScreeningService.CallResponse} provided 3700 * by the {@link CallScreeningService} that processed this call, or 3701 * {@code null} if no call screening service ran. 3702 * @param callScreeningComponent The component of the {@link CallScreeningService} 3703 * that processed this call, or {@link null} if no 3704 * call screening service ran. 3705 */ CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts, @Nullable CallScreeningService.CallResponse callResponse, @Nullable ComponentName callScreeningComponent)3706 public CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts, 3707 @Nullable CallScreeningService.CallResponse callResponse, 3708 @Nullable ComponentName callScreeningComponent) { 3709 mIsBlocked = isBlocked; 3710 mIsInContacts = isInContacts; 3711 mCallResponse = callResponse; 3712 mCallScreeningComponent = callScreeningComponent; 3713 } 3714 3715 /** @hide */ CallFilteringCompletionInfo(Parcel in)3716 protected CallFilteringCompletionInfo(Parcel in) { 3717 mIsBlocked = in.readByte() != 0; 3718 mIsInContacts = in.readByte() != 0; 3719 CallScreeningService.ParcelableCallResponse response 3720 = in.readParcelable(CallScreeningService.class.getClassLoader(), android.telecom.CallScreeningService.ParcelableCallResponse.class); 3721 mCallResponse = response == null ? null : response.toCallResponse(); 3722 mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader(), android.content.ComponentName.class); 3723 } 3724 3725 @NonNull 3726 public static final Creator<CallFilteringCompletionInfo> CREATOR = 3727 new Creator<CallFilteringCompletionInfo>() { 3728 @Override 3729 public CallFilteringCompletionInfo createFromParcel(Parcel in) { 3730 return new CallFilteringCompletionInfo(in); 3731 } 3732 3733 @Override 3734 public CallFilteringCompletionInfo[] newArray(int size) { 3735 return new CallFilteringCompletionInfo[size]; 3736 } 3737 }; 3738 3739 /** 3740 * @return Whether any part of the call filtering process indicated that this call should be 3741 * blocked. 3742 */ isBlocked()3743 public boolean isBlocked() { 3744 return mIsBlocked; 3745 } 3746 3747 /** 3748 * @return Whether the caller is in the user's contacts. 3749 */ isInContacts()3750 public boolean isInContacts() { 3751 return mIsInContacts; 3752 } 3753 3754 /** 3755 * @return The instance of {@link CallScreeningService.CallResponse} provided 3756 * by the {@link CallScreeningService} that processed this 3757 * call, or {@code null} if no call screening service ran. 3758 */ getCallResponse()3759 public @Nullable CallScreeningService.CallResponse getCallResponse() { 3760 return mCallResponse; 3761 } 3762 3763 /** 3764 * @return The component of the {@link CallScreeningService} 3765 * that processed this call, or {@code null} if no call screening service ran. 3766 */ getCallScreeningComponent()3767 public @Nullable ComponentName getCallScreeningComponent() { 3768 return mCallScreeningComponent; 3769 } 3770 3771 @Override describeContents()3772 public int describeContents() { 3773 return 0; 3774 } 3775 3776 @Override toString()3777 public String toString() { 3778 return "CallFilteringCompletionInfo{" + 3779 "mIsBlocked=" + mIsBlocked + 3780 ", mIsInContacts=" + mIsInContacts + 3781 ", mCallResponse=" + mCallResponse + 3782 ", mCallScreeningPackageName='" + mCallScreeningComponent + '\'' + 3783 '}'; 3784 } 3785 3786 /** @hide */ 3787 @Override writeToParcel(Parcel dest, int flags)3788 public void writeToParcel(Parcel dest, int flags) { 3789 dest.writeByte((byte) (mIsBlocked ? 1 : 0)); 3790 dest.writeByte((byte) (mIsInContacts ? 1 : 0)); 3791 dest.writeParcelable(mCallResponse == null ? null : mCallResponse.toParcelable(), 0); 3792 dest.writeParcelable(mCallScreeningComponent, 0); 3793 } 3794 } 3795 3796 /** 3797 * Indicates that call filtering in Telecom is complete 3798 * 3799 * This method is called for a connection created via 3800 * {@link ConnectionService#onCreateIncomingConnection} when call filtering completes in 3801 * Telecom, including checking the blocked number db, per-contact settings, and custom call 3802 * filtering apps. 3803 * 3804 * @param callFilteringCompletionInfo Info provided by Telecom on the results of call filtering. 3805 * @hide 3806 */ 3807 @SystemApi 3808 @RequiresPermission(Manifest.permission.READ_CONTACTS) onCallFilteringCompleted( @onNull CallFilteringCompletionInfo callFilteringCompletionInfo)3809 public void onCallFilteringCompleted( 3810 @NonNull CallFilteringCompletionInfo callFilteringCompletionInfo) { } 3811 toLogSafePhoneNumber(String number)3812 static String toLogSafePhoneNumber(String number) { 3813 // For unknown number, log empty string. 3814 if (number == null) { 3815 return ""; 3816 } 3817 3818 if (PII_DEBUG) { 3819 // When PII_DEBUG is true we emit PII. 3820 return number; 3821 } 3822 3823 // Do exactly same thing as Uri#toSafeString() does, which will enable us to compare 3824 // sanitized phone numbers. 3825 StringBuilder builder = new StringBuilder(); 3826 for (int i = 0; i < number.length(); i++) { 3827 char c = number.charAt(i); 3828 if (c == '-' || c == '@' || c == '.') { 3829 builder.append(c); 3830 } else { 3831 builder.append('x'); 3832 } 3833 } 3834 return builder.toString(); 3835 } 3836 setState(int state)3837 private void setState(int state) { 3838 checkImmutable(); 3839 if (mState == STATE_DISCONNECTED && mState != state) { 3840 Log.d(this, "Connection already DISCONNECTED; cannot transition out of this state."); 3841 return; 3842 } 3843 if (mState != state) { 3844 Log.d(this, "setState: %s", stateToString(state)); 3845 mState = state; 3846 onStateChanged(state); 3847 for (Listener l : mListeners) { 3848 l.onStateChanged(this, state); 3849 } 3850 } 3851 } 3852 3853 private static class FailureSignalingConnection extends Connection { 3854 private boolean mImmutable = false; FailureSignalingConnection(DisconnectCause disconnectCause)3855 public FailureSignalingConnection(DisconnectCause disconnectCause) { 3856 setDisconnected(disconnectCause); 3857 mImmutable = true; 3858 } 3859 checkImmutable()3860 public void checkImmutable() { 3861 if (mImmutable) { 3862 throw new UnsupportedOperationException("Connection is immutable"); 3863 } 3864 } 3865 } 3866 3867 /** 3868 * Return a {@code Connection} which represents a failed connection attempt. The returned 3869 * {@code Connection} will have a {@link android.telecom.DisconnectCause} and as specified, 3870 * and a {@link #getState()} of {@link #STATE_DISCONNECTED}. 3871 * <p> 3872 * The returned {@code Connection} can be assumed to {@link #destroy()} itself when appropriate, 3873 * so users of this method need not maintain a reference to its return value to destroy it. 3874 * 3875 * @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}). 3876 * @return A {@code Connection} which indicates failure. 3877 */ createFailedConnection(DisconnectCause disconnectCause)3878 public static Connection createFailedConnection(DisconnectCause disconnectCause) { 3879 return new FailureSignalingConnection(disconnectCause); 3880 } 3881 3882 /** 3883 * Override to throw an {@link UnsupportedOperationException} if this {@code Connection} is 3884 * not intended to be mutated, e.g., if it is a marker for failure. Only for framework use; 3885 * this should never be un-@hide-den. 3886 * 3887 * @hide 3888 */ checkImmutable()3889 public void checkImmutable() {} 3890 3891 /** 3892 * Return a {@code Connection} which represents a canceled connection attempt. The returned 3893 * {@code Connection} will have state {@link #STATE_DISCONNECTED}, and cannot be moved out of 3894 * that state. This connection should not be used for anything, and no other 3895 * {@code Connection}s should be attempted. 3896 * <p> 3897 * so users of this method need not maintain a reference to its return value to destroy it. 3898 * 3899 * @return A {@code Connection} which indicates that the underlying connection should 3900 * be canceled. 3901 */ createCanceledConnection()3902 public static Connection createCanceledConnection() { 3903 return new FailureSignalingConnection(new DisconnectCause(DisconnectCause.CANCELED)); 3904 } 3905 fireOnConferenceableConnectionsChanged()3906 private final void fireOnConferenceableConnectionsChanged() { 3907 for (Listener l : mListeners) { 3908 l.onConferenceablesChanged(this, getConferenceables()); 3909 } 3910 } 3911 fireConferenceChanged()3912 private final void fireConferenceChanged() { 3913 for (Listener l : mListeners) { 3914 l.onConferenceChanged(this, mConference); 3915 } 3916 } 3917 clearConferenceableList()3918 private final void clearConferenceableList() { 3919 for (Conferenceable c : mConferenceables) { 3920 if (c instanceof Connection) { 3921 Connection connection = (Connection) c; 3922 connection.removeConnectionListener(mConnectionDeathListener); 3923 } else if (c instanceof Conference) { 3924 Conference conference = (Conference) c; 3925 conference.removeListener(mConferenceDeathListener); 3926 } 3927 } 3928 mConferenceables.clear(); 3929 } 3930 3931 /** 3932 * Handles a change to extras received from Telecom. 3933 * 3934 * @param extras The new extras. 3935 * @hide 3936 */ handleExtrasChanged(Bundle extras)3937 final void handleExtrasChanged(Bundle extras) { 3938 Bundle b = null; 3939 synchronized (mExtrasLock) { 3940 mExtras = extras; 3941 if (mExtras != null) { 3942 b = new Bundle(mExtras); 3943 } 3944 } 3945 onExtrasChanged(b); 3946 } 3947 3948 /** 3949 * Called by a {@link ConnectionService} to notify Telecom that a {@link Conference#onMerge()} 3950 * request failed. 3951 */ notifyConferenceMergeFailed()3952 public final void notifyConferenceMergeFailed() { 3953 for (Listener l : mListeners) { 3954 l.onConferenceMergeFailed(this); 3955 } 3956 } 3957 3958 /** 3959 * Notifies listeners when phone account is changed. For example, when the PhoneAccount is 3960 * changed due to an emergency call being redialed. 3961 * @param pHandle The new PhoneAccountHandle for this connection. 3962 * @hide 3963 */ notifyPhoneAccountChanged(PhoneAccountHandle pHandle)3964 public void notifyPhoneAccountChanged(PhoneAccountHandle pHandle) { 3965 for (Listener l : mListeners) { 3966 l.onPhoneAccountChanged(this, pHandle); 3967 } 3968 } 3969 3970 /** 3971 * Sets the {@link PhoneAccountHandle} associated with this connection. 3972 * <p> 3973 * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount} 3974 * which take place after call initiation (important for emergency calling scenarios). 3975 * 3976 * @param phoneAccountHandle the phone account handle to set. 3977 * @hide 3978 */ 3979 @SystemApi setPhoneAccountHandle(@onNull PhoneAccountHandle phoneAccountHandle)3980 public void setPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) { 3981 if (mPhoneAccountHandle != phoneAccountHandle) { 3982 mPhoneAccountHandle = phoneAccountHandle; 3983 notifyPhoneAccountChanged(phoneAccountHandle); 3984 } 3985 } 3986 3987 /** 3988 * Returns the {@link PhoneAccountHandle} associated with this connection. 3989 * <p> 3990 * Used by the Telephony {@link ConnectionService} to handle changes to the {@link PhoneAccount} 3991 * which take place after call initiation (important for emergency calling scenarios). 3992 * 3993 * @return the phone account handle specified via 3994 * {@link #setPhoneAccountHandle(PhoneAccountHandle)}, or {@code null} if none was set. 3995 * @hide 3996 */ 3997 @SystemApi getPhoneAccountHandle()3998 public @Nullable PhoneAccountHandle getPhoneAccountHandle() { 3999 return mPhoneAccountHandle; 4000 } 4001 4002 /** 4003 * Sends an event associated with this {@code Connection} with associated event extras to the 4004 * {@link InCallService}. 4005 * <p> 4006 * Connection events are used to communicate point in time information from a 4007 * {@link ConnectionService} to a {@link InCallService} implementations. An example of a 4008 * custom connection event includes notifying the UI when a WIFI call has been handed over to 4009 * LTE, which the InCall UI might use to inform the user that billing charges may apply. The 4010 * Android Telephony framework will send the {@link #EVENT_CALL_MERGE_FAILED} connection event 4011 * when a call to {@link Call#mergeConference()} has failed to complete successfully. A 4012 * connection event could also be used to trigger UI in the {@link InCallService} which prompts 4013 * the user to make a choice (e.g. whether they want to incur roaming costs for making a call), 4014 * which is communicated back via {@link Call#sendCallEvent(String, Bundle)}. 4015 * <p> 4016 * Events are exposed to {@link InCallService} implementations via 4017 * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}. 4018 * <p> 4019 * No assumptions should be made as to how an In-Call UI or service will handle these events. 4020 * The {@link ConnectionService} must assume that the In-Call UI could even chose to ignore 4021 * some events altogether. 4022 * <p> 4023 * Events should be fully qualified (e.g. {@code com.example.event.MY_EVENT}) to avoid 4024 * conflicts between {@link ConnectionService} implementations. Further, custom 4025 * {@link ConnectionService} implementations shall not re-purpose events in the 4026 * {@code android.*} namespace, nor shall they define new event types in this namespace. When 4027 * defining a custom event type, ensure the contents of the extras {@link Bundle} is clearly 4028 * defined. Extra keys for this bundle should be named similar to the event type (e.g. 4029 * {@code com.example.extra.MY_EXTRA}). 4030 * <p> 4031 * When defining events and the associated extras, it is important to keep their behavior 4032 * consistent when the associated {@link ConnectionService} is updated. Support for deprecated 4033 * events/extras should me maintained to ensure backwards compatibility with older 4034 * {@link InCallService} implementations which were built to support the older behavior. 4035 * 4036 * @param event The connection event. 4037 * @param extras Optional bundle containing extra information associated with the event. 4038 */ sendConnectionEvent(String event, Bundle extras)4039 public void sendConnectionEvent(String event, Bundle extras) { 4040 for (Listener l : mListeners) { 4041 l.onConnectionEvent(this, event, extras); 4042 } 4043 } 4044 4045 /** 4046 * Retrieves the direction of this connection. 4047 * @return The direction of the call. 4048 * @hide 4049 */ 4050 @SystemApi 4051 @FlaggedApi(Flags.FLAG_TELECOM_RESOLVE_HIDDEN_DEPENDENCIES) getCallDirection()4052 public final @Call.Details.CallDirection int getCallDirection() { 4053 return mCallDirection; 4054 } 4055 4056 /** 4057 * Sets the direction of this connection. 4058 * <p> 4059 * Used when calling {@link ConnectionService#addExistingConnection} to specify the existing 4060 * call direction. 4061 * 4062 * @param callDirection The direction of this connection. 4063 * @hide 4064 */ 4065 @SystemApi setCallDirection(@all.Details.CallDirection int callDirection)4066 public void setCallDirection(@Call.Details.CallDirection int callDirection) { 4067 mCallDirection = callDirection; 4068 } 4069 4070 /** 4071 * Gets the verification status for the phone number of an incoming call as identified in 4072 * ATIS-1000082. 4073 * @return the verification status. 4074 */ getCallerNumberVerificationStatus()4075 public final @VerificationStatus int getCallerNumberVerificationStatus() { 4076 return mCallerNumberVerificationStatus; 4077 } 4078 4079 /** 4080 * Sets the verification status for the phone number of an incoming call as identified in 4081 * ATIS-1000082. 4082 * <p> 4083 * This property can only be set at the time of creation of a {@link Connection} being returned 4084 * by 4085 * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}. 4086 */ setCallerNumberVerificationStatus( @erificationStatus int callerNumberVerificationStatus)4087 public final void setCallerNumberVerificationStatus( 4088 @VerificationStatus int callerNumberVerificationStatus) { 4089 mCallerNumberVerificationStatus = callerNumberVerificationStatus; 4090 } 4091 } 4092