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