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