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