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