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