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