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