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