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