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