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