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