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 android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.net.Uri;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.ParcelFileDescriptor;
26 
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStreamWriter;
30 import java.lang.String;
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.nio.charset.StandardCharsets;
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.concurrent.CopyOnWriteArrayList;
41 
42 /**
43  * Represents an ongoing phone call that the in-call app should present to the user.
44  */
45 public final class Call {
46     /**
47      * The state of a {@code Call} when newly created.
48      */
49     public static final int STATE_NEW = 0;
50 
51     /**
52      * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
53      */
54     public static final int STATE_DIALING = 1;
55 
56     /**
57      * The state of an incoming {@code Call} when ringing locally, but not yet connected.
58      */
59     public static final int STATE_RINGING = 2;
60 
61     /**
62      * The state of a {@code Call} when in a holding state.
63      */
64     public static final int STATE_HOLDING = 3;
65 
66     /**
67      * The state of a {@code Call} when actively supporting conversation.
68      */
69     public static final int STATE_ACTIVE = 4;
70 
71     /**
72      * The state of a {@code Call} when no further voice or other communication is being
73      * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
74      * is no longer active, and the local data transport has or inevitably will release resources
75      * associated with this {@code Call}.
76      */
77     public static final int STATE_DISCONNECTED = 7;
78 
79     /**
80      * The state of an outgoing {@code Call} when waiting on user to select a
81      * {@link PhoneAccount} through which to place the call.
82      */
83     public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
84 
85     /**
86      * @hide
87      * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
88      */
89     @Deprecated
90     @SystemApi
91     public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
92 
93     /**
94      * The initial state of an outgoing {@code Call}.
95      * Common transitions are to {@link #STATE_DIALING} state for a successful call or
96      * {@link #STATE_DISCONNECTED} if it failed.
97      */
98     public static final int STATE_CONNECTING = 9;
99 
100     /**
101      * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
102      * call has not yet been disconnected by the underlying {@code ConnectionService}.  The next
103      * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
104      */
105     public static final int STATE_DISCONNECTING = 10;
106 
107     /**
108      * The state of an external call which is in the process of being pulled from a remote device to
109      * the local device.
110      * <p>
111      * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
112      * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
113      * <p>
114      * An {@link InCallService} will only see this state if it has the
115      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
116      * manifest.
117      */
118     public static final int STATE_PULLING_CALL = 11;
119 
120     /**
121      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
122      * extras. Used to pass the phone accounts to display on the front end to the user in order to
123      * select phone accounts to (for example) place a call.
124      */
125     public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
126 
127     /**
128      * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
129      * when the last outgoing emergency call was made.  This is used to identify potential emergency
130      * callbacks.
131      */
132     public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
133             "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
134 
135     /**
136      * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
137      * Telecom that the user has requested that the current {@link Call} should be handed over
138      * to another {@link ConnectionService}.
139      * <p>
140      * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
141      * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
142      * @hide
143      */
144     public static final String EVENT_REQUEST_HANDOVER =
145             "android.telecom.event.REQUEST_HANDOVER";
146 
147     /**
148      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
149      * {@link PhoneAccountHandle} to which a call should be handed over to.
150      * @hide
151      */
152     public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
153             "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
154 
155     /**
156      * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
157      * video state of the call when it is handed over to the new {@link PhoneAccount}.
158      * <p>
159      * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
160      * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
161      * {@link VideoProfile#STATE_TX_ENABLED}.
162      * @hide
163      */
164     public static final String EXTRA_HANDOVER_VIDEO_STATE =
165             "android.telecom.extra.HANDOVER_VIDEO_STATE";
166 
167     /**
168      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Used by the
169      * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
170      * information to the handover {@link ConnectionService} specified by
171      * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
172      * <p>
173      * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
174      * {@link ConnectionService} via the request extras when
175      * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
176      * is called to initate the handover.
177      * @hide
178      */
179     public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
180 
181     /**
182      * Call event sent from Telecom to the handover {@link ConnectionService} via
183      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
184      * to the {@link ConnectionService} has completed successfully.
185      * <p>
186      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
187      * @hide
188      */
189     public static final String EVENT_HANDOVER_COMPLETE =
190             "android.telecom.event.HANDOVER_COMPLETE";
191 
192     /**
193      * Call event sent from Telecom to the handover destination {@link ConnectionService} via
194      * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
195      * source connection has disconnected.  The {@link Bundle} parameter for the call event will be
196      * {@code null}.
197      * <p>
198      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
199      * @hide
200      */
201     public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
202             "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
203 
204     /**
205      * Call event sent from Telecom to the handover {@link ConnectionService} via
206      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
207      * to the {@link ConnectionService} has failed.
208      * <p>
209      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
210      * @hide
211      */
212     public static final String EVENT_HANDOVER_FAILED =
213             "android.telecom.event.HANDOVER_FAILED";
214 
215     public static class Details {
216 
217         /** Call can currently be put on hold or unheld. */
218         public static final int CAPABILITY_HOLD = 0x00000001;
219 
220         /** Call supports the hold feature. */
221         public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
222 
223         /**
224          * Calls within a conference can be merged. A {@link ConnectionService} has the option to
225          * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
226          * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
227          * capability allows a merge button to be shown while the conference call is in the foreground
228          * of the in-call UI.
229          * <p>
230          * This is only intended for use by a {@link Conference}.
231          */
232         public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
233 
234         /**
235          * Calls within a conference can be swapped between foreground and background.
236          * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
237          * <p>
238          * This is only intended for use by a {@link Conference}.
239          */
240         public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
241 
242         /**
243          * @hide
244          */
245         public static final int CAPABILITY_UNUSED_1 = 0x00000010;
246 
247         /** Call supports responding via text option. */
248         public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
249 
250         /** Call can be muted. */
251         public static final int CAPABILITY_MUTE = 0x00000040;
252 
253         /**
254          * Call supports conference call management. This capability only applies to {@link Conference}
255          * calls which can have {@link Connection}s as children.
256          */
257         public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
258 
259         /**
260          * Local device supports receiving video.
261          */
262         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
263 
264         /**
265          * Local device supports transmitting video.
266          */
267         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
268 
269         /**
270          * Local device supports bidirectional video calling.
271          */
272         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
273                 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
274 
275         /**
276          * Remote device supports receiving video.
277          */
278         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
279 
280         /**
281          * Remote device supports transmitting video.
282          */
283         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
284 
285         /**
286          * Remote device supports bidirectional video calling.
287          */
288         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
289                 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
290 
291         /**
292          * Call is able to be separated from its parent {@code Conference}, if any.
293          */
294         public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
295 
296         /**
297          * Call is able to be individually disconnected when in a {@code Conference}.
298          */
299         public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
300 
301         /**
302          * Speed up audio setup for MT call.
303          * @hide
304          */
305         public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
306 
307         /**
308          * Call can be upgraded to a video call.
309          * @hide
310          */
311         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
312 
313         /**
314          * For video calls, indicates whether the outgoing video for the call can be paused using
315          * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
316          */
317         public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
318 
319         /**
320          * Call sends responses through connection.
321          * @hide
322          */
323         public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
324 
325         /**
326          * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
327          * <p>
328          * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
329          * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
330          * downgraded from a video call back to a VideoState of
331          * {@link VideoProfile#STATE_AUDIO_ONLY}.
332          * <p>
333          * Intuitively, a call which can be downgraded to audio should also have local and remote
334          * video
335          * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
336          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
337          */
338         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
339 
340         /**
341          * When set for an external call, indicates that this {@code Call} can be pulled from a
342          * remote device to the current device.
343          * <p>
344          * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
345          * <p>
346          * An {@link InCallService} will only see calls with this capability if it has the
347          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
348          * in its manifest.
349          * <p>
350          * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
351          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
352          */
353         public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
354 
355         /** Call supports the deflect feature. */
356         public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
357 
358         //******************************************************************************************
359         // Next CAPABILITY value: 0x02000000
360         //******************************************************************************************
361 
362         /**
363          * Whether the call is currently a conference.
364          */
365         public static final int PROPERTY_CONFERENCE = 0x00000001;
366 
367         /**
368          * Whether the call is a generic conference, where we do not know the precise state of
369          * participants in the conference (eg. on CDMA).
370          */
371         public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
372 
373         /**
374          * Whether the call is made while the device is in emergency callback mode.
375          */
376         public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
377 
378         /**
379          * Connection is using WIFI.
380          */
381         public static final int PROPERTY_WIFI = 0x00000008;
382 
383         /**
384          * Call is using high definition audio.
385          */
386         public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
387 
388         /**
389          * Whether the call is associated with the work profile.
390          */
391         public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
392 
393         /**
394          * When set, indicates that this {@code Call} does not actually exist locally for the
395          * {@link ConnectionService}.
396          * <p>
397          * Consider, for example, a scenario where a user has two phones with the same phone number.
398          * When a user places a call on one device, the telephony stack can represent that call on
399          * the other device by adding it to the {@link ConnectionService} with the
400          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
401          * <p>
402          * An {@link InCallService} will only see calls with this property if it has the
403          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
404          * in its manifest.
405          * <p>
406          * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
407          */
408         public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
409 
410         /**
411          * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
412          */
413         public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
414 
415         /**
416          * Indicates that the call is from a self-managed {@link ConnectionService}.
417          * <p>
418          * See also {@link Connection#PROPERTY_SELF_MANAGED}
419          */
420         public static final int PROPERTY_SELF_MANAGED = 0x00000100;
421 
422         /**
423          * Indicates the call used Assisted Dialing.
424          * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
425          * @hide
426          */
427         public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
428 
429         /**
430          * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
431          * {@link RttCall} object that is used to send and receive text.
432          */
433         public static final int PROPERTY_RTT = 0x00000400;
434 
435         //******************************************************************************************
436         // Next PROPERTY value: 0x00000800
437         //******************************************************************************************
438 
439         private final String mTelecomCallId;
440         private final Uri mHandle;
441         private final int mHandlePresentation;
442         private final String mCallerDisplayName;
443         private final int mCallerDisplayNamePresentation;
444         private final PhoneAccountHandle mAccountHandle;
445         private final int mCallCapabilities;
446         private final int mCallProperties;
447         private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
448         private final DisconnectCause mDisconnectCause;
449         private final long mConnectTimeMillis;
450         private final GatewayInfo mGatewayInfo;
451         private final int mVideoState;
452         private final StatusHints mStatusHints;
453         private final Bundle mExtras;
454         private final Bundle mIntentExtras;
455         private final long mCreationTimeMillis;
456 
457         /**
458          * Whether the supplied capabilities  supports the specified capability.
459          *
460          * @param capabilities A bit field of capabilities.
461          * @param capability The capability to check capabilities for.
462          * @return Whether the specified capability is supported.
463          */
can(int capabilities, int capability)464         public static boolean can(int capabilities, int capability) {
465             return (capabilities & capability) == capability;
466         }
467 
468         /**
469          * Whether the capabilities of this {@code Details} supports the specified capability.
470          *
471          * @param capability The capability to check capabilities for.
472          * @return Whether the specified capability is supported.
473          */
can(int capability)474         public boolean can(int capability) {
475             return can(mCallCapabilities, capability);
476         }
477 
478         /**
479          * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
480          *
481          * @param capabilities A capability bit field.
482          * @return A human readable string representation.
483          */
capabilitiesToString(int capabilities)484         public static String capabilitiesToString(int capabilities) {
485             StringBuilder builder = new StringBuilder();
486             builder.append("[Capabilities:");
487             if (can(capabilities, CAPABILITY_HOLD)) {
488                 builder.append(" CAPABILITY_HOLD");
489             }
490             if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
491                 builder.append(" CAPABILITY_SUPPORT_HOLD");
492             }
493             if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
494                 builder.append(" CAPABILITY_MERGE_CONFERENCE");
495             }
496             if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
497                 builder.append(" CAPABILITY_SWAP_CONFERENCE");
498             }
499             if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
500                 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
501             }
502             if (can(capabilities, CAPABILITY_MUTE)) {
503                 builder.append(" CAPABILITY_MUTE");
504             }
505             if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
506                 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
507             }
508             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
509                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
510             }
511             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
512                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
513             }
514             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
515                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
516             }
517             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
518                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
519             }
520             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
521                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
522             }
523             if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
524                 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
525             }
526             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
527                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
528             }
529             if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
530                 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
531             }
532             if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
533                 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
534             }
535             if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
536                 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
537             }
538             if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
539                 builder.append(" CAPABILITY_CAN_PULL_CALL");
540             }
541             if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
542                 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
543             }
544             builder.append("]");
545             return builder.toString();
546         }
547 
548         /**
549          * Whether the supplied properties includes the specified property.
550          *
551          * @param properties A bit field of properties.
552          * @param property The property to check properties for.
553          * @return Whether the specified property is supported.
554          */
hasProperty(int properties, int property)555         public static boolean hasProperty(int properties, int property) {
556             return (properties & property) == property;
557         }
558 
559         /**
560          * Whether the properties of this {@code Details} includes the specified property.
561          *
562          * @param property The property to check properties for.
563          * @return Whether the specified property is supported.
564          */
hasProperty(int property)565         public boolean hasProperty(int property) {
566             return hasProperty(mCallProperties, property);
567         }
568 
569         /**
570          * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
571          *
572          * @param properties A property bit field.
573          * @return A human readable string representation.
574          */
propertiesToString(int properties)575         public static String propertiesToString(int properties) {
576             StringBuilder builder = new StringBuilder();
577             builder.append("[Properties:");
578             if (hasProperty(properties, PROPERTY_CONFERENCE)) {
579                 builder.append(" PROPERTY_CONFERENCE");
580             }
581             if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
582                 builder.append(" PROPERTY_GENERIC_CONFERENCE");
583             }
584             if (hasProperty(properties, PROPERTY_WIFI)) {
585                 builder.append(" PROPERTY_WIFI");
586             }
587             if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
588                 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
589             }
590             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
591                 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
592             }
593             if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
594                 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
595             }
596             if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
597                 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
598             }
599             if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
600                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
601             }
602             builder.append("]");
603             return builder.toString();
604         }
605 
606         /** {@hide} */
getTelecomCallId()607         public String getTelecomCallId() {
608             return mTelecomCallId;
609         }
610 
611         /**
612          * @return The handle (e.g., phone number) to which the {@code Call} is currently
613          * connected.
614          */
getHandle()615         public Uri getHandle() {
616             return mHandle;
617         }
618 
619         /**
620          * @return The presentation requirements for the handle. See
621          * {@link TelecomManager} for valid values.
622          */
getHandlePresentation()623         public int getHandlePresentation() {
624             return mHandlePresentation;
625         }
626 
627         /**
628          * @return The display name for the caller.
629          */
getCallerDisplayName()630         public String getCallerDisplayName() {
631             return mCallerDisplayName;
632         }
633 
634         /**
635          * @return The presentation requirements for the caller display name. See
636          * {@link TelecomManager} for valid values.
637          */
getCallerDisplayNamePresentation()638         public int getCallerDisplayNamePresentation() {
639             return mCallerDisplayNamePresentation;
640         }
641 
642         /**
643          * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
644          * routed.
645          */
getAccountHandle()646         public PhoneAccountHandle getAccountHandle() {
647             return mAccountHandle;
648         }
649 
650         /**
651          * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
652          *         {@code CAPABILITY_*} constants in this class.
653          */
getCallCapabilities()654         public int getCallCapabilities() {
655             return mCallCapabilities;
656         }
657 
658         /**
659          * @return A bitmask of the properties of the {@code Call}, as defined by the various
660          *         {@code PROPERTY_*} constants in this class.
661          */
getCallProperties()662         public int getCallProperties() {
663             return mCallProperties;
664         }
665 
666         /**
667          * @return a bitmask of the audio routes available for the call.
668          *
669          * @hide
670          */
getSupportedAudioRoutes()671         public int getSupportedAudioRoutes() {
672             return mSupportedAudioRoutes;
673         }
674 
675         /**
676          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
677          * by {@link android.telecom.DisconnectCause}.
678          */
getDisconnectCause()679         public DisconnectCause getDisconnectCause() {
680             return mDisconnectCause;
681         }
682 
683         /**
684          * Returns the time the {@link Call} connected (i.e. became active).  This information is
685          * updated periodically, but user interfaces should not rely on this to display the "call
686          * time clock".  For the time when the call was first added to Telecom, see
687          * {@link #getCreationTimeMillis()}.
688          *
689          * @return The time the {@link Call} connected in milliseconds since the epoch.
690          */
getConnectTimeMillis()691         public final long getConnectTimeMillis() {
692             return mConnectTimeMillis;
693         }
694 
695         /**
696          * @return Information about any calling gateway the {@code Call} may be using.
697          */
getGatewayInfo()698         public GatewayInfo getGatewayInfo() {
699             return mGatewayInfo;
700         }
701 
702         /**
703          * @return The video state of the {@code Call}.
704          */
getVideoState()705         public int getVideoState() {
706             return mVideoState;
707         }
708 
709         /**
710          * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
711          * have been set.
712          */
getStatusHints()713         public StatusHints getStatusHints() {
714             return mStatusHints;
715         }
716 
717         /**
718          * @return The extras associated with this call.
719          */
getExtras()720         public Bundle getExtras() {
721             return mExtras;
722         }
723 
724         /**
725          * @return The extras used with the original intent to place this call.
726          */
getIntentExtras()727         public Bundle getIntentExtras() {
728             return mIntentExtras;
729         }
730 
731         /**
732          * Returns the time when the call was first created and added to Telecom.  This is the same
733          * time that is logged as the start time in the Call Log (see
734          * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
735          * (became active), see {@link #getConnectTimeMillis()}.
736          *
737          * @return The creation time of the call, in millis since the epoch.
738          */
getCreationTimeMillis()739         public long getCreationTimeMillis() {
740             return mCreationTimeMillis;
741         }
742 
743         @Override
equals(Object o)744         public boolean equals(Object o) {
745             if (o instanceof Details) {
746                 Details d = (Details) o;
747                 return
748                         Objects.equals(mHandle, d.mHandle) &&
749                         Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
750                         Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
751                         Objects.equals(mCallerDisplayNamePresentation,
752                                 d.mCallerDisplayNamePresentation) &&
753                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
754                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
755                         Objects.equals(mCallProperties, d.mCallProperties) &&
756                         Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
757                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
758                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
759                         Objects.equals(mVideoState, d.mVideoState) &&
760                         Objects.equals(mStatusHints, d.mStatusHints) &&
761                         areBundlesEqual(mExtras, d.mExtras) &&
762                         areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
763                         Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
764             }
765             return false;
766         }
767 
768         @Override
hashCode()769         public int hashCode() {
770             return Objects.hash(mHandle,
771                             mHandlePresentation,
772                             mCallerDisplayName,
773                             mCallerDisplayNamePresentation,
774                             mAccountHandle,
775                             mCallCapabilities,
776                             mCallProperties,
777                             mDisconnectCause,
778                             mConnectTimeMillis,
779                             mGatewayInfo,
780                             mVideoState,
781                             mStatusHints,
782                             mExtras,
783                             mIntentExtras,
784                             mCreationTimeMillis);
785         }
786 
787         /** {@hide} */
Details( String telecomCallId, Uri handle, int handlePresentation, String callerDisplayName, int callerDisplayNamePresentation, PhoneAccountHandle accountHandle, int capabilities, int properties, DisconnectCause disconnectCause, long connectTimeMillis, GatewayInfo gatewayInfo, int videoState, StatusHints statusHints, Bundle extras, Bundle intentExtras, long creationTimeMillis)788         public Details(
789                 String telecomCallId,
790                 Uri handle,
791                 int handlePresentation,
792                 String callerDisplayName,
793                 int callerDisplayNamePresentation,
794                 PhoneAccountHandle accountHandle,
795                 int capabilities,
796                 int properties,
797                 DisconnectCause disconnectCause,
798                 long connectTimeMillis,
799                 GatewayInfo gatewayInfo,
800                 int videoState,
801                 StatusHints statusHints,
802                 Bundle extras,
803                 Bundle intentExtras,
804                 long creationTimeMillis) {
805             mTelecomCallId = telecomCallId;
806             mHandle = handle;
807             mHandlePresentation = handlePresentation;
808             mCallerDisplayName = callerDisplayName;
809             mCallerDisplayNamePresentation = callerDisplayNamePresentation;
810             mAccountHandle = accountHandle;
811             mCallCapabilities = capabilities;
812             mCallProperties = properties;
813             mDisconnectCause = disconnectCause;
814             mConnectTimeMillis = connectTimeMillis;
815             mGatewayInfo = gatewayInfo;
816             mVideoState = videoState;
817             mStatusHints = statusHints;
818             mExtras = extras;
819             mIntentExtras = intentExtras;
820             mCreationTimeMillis = creationTimeMillis;
821         }
822 
823         /** {@hide} */
createFromParcelableCall(ParcelableCall parcelableCall)824         public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
825             return new Details(
826                     parcelableCall.getId(),
827                     parcelableCall.getHandle(),
828                     parcelableCall.getHandlePresentation(),
829                     parcelableCall.getCallerDisplayName(),
830                     parcelableCall.getCallerDisplayNamePresentation(),
831                     parcelableCall.getAccountHandle(),
832                     parcelableCall.getCapabilities(),
833                     parcelableCall.getProperties(),
834                     parcelableCall.getDisconnectCause(),
835                     parcelableCall.getConnectTimeMillis(),
836                     parcelableCall.getGatewayInfo(),
837                     parcelableCall.getVideoState(),
838                     parcelableCall.getStatusHints(),
839                     parcelableCall.getExtras(),
840                     parcelableCall.getIntentExtras(),
841                     parcelableCall.getCreationTimeMillis());
842         }
843 
844         @Override
toString()845         public String toString() {
846             StringBuilder sb = new StringBuilder();
847             sb.append("[pa: ");
848             sb.append(mAccountHandle);
849             sb.append(", hdl: ");
850             sb.append(Log.pii(mHandle));
851             sb.append(", caps: ");
852             sb.append(capabilitiesToString(mCallCapabilities));
853             sb.append(", props: ");
854             sb.append(propertiesToString(mCallProperties));
855             sb.append("]");
856             return sb.toString();
857         }
858     }
859 
860     /**
861      * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
862      * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
863      * implementation.
864      * <p>
865      * You can handle these callbacks by extending the {@link Callback} class and overriding the
866      * callbacks that your {@link InCallService} is interested in.  The callback methods include the
867      * {@link Call} for which the callback applies, allowing reuse of a single instance of your
868      * {@link Callback} implementation, if desired.
869      * <p>
870      * Use {@link Call#registerCallback(Callback)} to register your callback(s).  Ensure
871      * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
872      * (typically in {@link InCallService#onCallRemoved(Call)}).
873      * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
874      * reach your implementation of {@link Callback}, so it is important to register your callback
875      * as soon as your {@link InCallService} is notified of a new call via
876      * {@link InCallService#onCallAdded(Call)}.
877      */
878     public static abstract class Callback {
879         /**
880          * @hide
881          */
882         @IntDef(prefix = { "HANDOVER_" },
883                 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
884                 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
885                 HANDOVER_FAILURE_UNKNOWN})
886         @Retention(RetentionPolicy.SOURCE)
887         public @interface HandoverFailureErrors {}
888 
889         /**
890          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
891          * to handover the call to rejects the handover request.
892          * <p>
893          * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
894          * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
895          * {@code null} {@link Connection} from
896          * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
897          * ConnectionRequest)}.
898          * <p>
899          * For more information on call handovers, see
900          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
901          */
902         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
903 
904         /**
905          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
906          * is initiated but the source or destination app does not support handover.
907          * <p>
908          * Will be returned when a handover is requested via
909          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
910          * {@link PhoneAccountHandle} does not declare
911          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
912          * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
913          * {@link Details#getAccountHandle()}) does not declare
914          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
915          * <p>
916          * For more information on call handovers, see
917          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
918          */
919         public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
920 
921         /**
922          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
923          * user rejects the handover request.
924          * <p>
925          * For more information on call handovers, see
926          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
927          */
928         public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
929 
930         /**
931          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
932          * is ongoing emergency call.
933          * <p>
934          * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
935          * called on an emergency call, or if any other call is an emergency call.
936          * <p>
937          * Handovers are not permitted while there are ongoing emergency calls.
938          * <p>
939          * For more information on call handovers, see
940          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
941          */
942         public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
943 
944         /**
945          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
946          * fails for an unknown reason.
947          * <p>
948          * For more information on call handovers, see
949          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
950          */
951         public static final int HANDOVER_FAILURE_UNKNOWN = 5;
952 
953         /**
954          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
955          *
956          * @param call The {@code Call} invoking this method.
957          * @param state The new state of the {@code Call}.
958          */
onStateChanged(Call call, int state)959         public void onStateChanged(Call call, int state) {}
960 
961         /**
962          * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
963          *
964          * @param call The {@code Call} invoking this method.
965          * @param parent The new parent of the {@code Call}.
966          */
onParentChanged(Call call, Call parent)967         public void onParentChanged(Call call, Call parent) {}
968 
969         /**
970          * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
971          *
972          * @param call The {@code Call} invoking this method.
973          * @param children The new children of the {@code Call}.
974          */
onChildrenChanged(Call call, List<Call> children)975         public void onChildrenChanged(Call call, List<Call> children) {}
976 
977         /**
978          * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
979          *
980          * @param call The {@code Call} invoking this method.
981          * @param details A {@code Details} object describing the {@code Call}.
982          */
onDetailsChanged(Call call, Details details)983         public void onDetailsChanged(Call call, Details details) {}
984 
985         /**
986          * Invoked when the text messages that can be used as responses to the incoming
987          * {@code Call} are loaded from the relevant database.
988          * See {@link #getCannedTextResponses()}.
989          *
990          * @param call The {@code Call} invoking this method.
991          * @param cannedTextResponses The text messages useable as responses.
992          */
onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses)993         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
994 
995         /**
996          * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
997          * character. This causes the post-dial signals to stop pending user confirmation. An
998          * implementation should present this choice to the user and invoke
999          * {@link #postDialContinue(boolean)} when the user makes the choice.
1000          *
1001          * @param call The {@code Call} invoking this method.
1002          * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1003          */
onPostDialWait(Call call, String remainingPostDialSequence)1004         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1005 
1006         /**
1007          * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
1008          *
1009          * @param call The {@code Call} invoking this method.
1010          * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
1011          */
onVideoCallChanged(Call call, InCallService.VideoCall videoCall)1012         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
1013 
1014         /**
1015          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1016          * up their UI for the {@code Call} in response to state transitions. Specifically,
1017          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1018          * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1019          * clients should wait for this method to be invoked.
1020          *
1021          * @param call The {@code Call} being destroyed.
1022          */
onCallDestroyed(Call call)1023         public void onCallDestroyed(Call call) {}
1024 
1025         /**
1026          * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1027          * conferenced.
1028          *
1029          * @param call The {@code Call} being updated.
1030          * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1031          *          conferenced.
1032          */
onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls)1033         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
1034 
1035         /**
1036          * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
1037          * <p>
1038          * Where possible, the Call should make an attempt to handle {@link Connection} events which
1039          * are part of the {@code android.telecom.*} namespace.  The Call should ignore any events
1040          * it does not wish to handle.  Unexpected events should be handled gracefully, as it is
1041          * possible that a {@link ConnectionService} has defined its own Connection events which a
1042          * Call is not aware of.
1043          * <p>
1044          * See {@link Connection#sendConnectionEvent(String, Bundle)}.
1045          *
1046          * @param call The {@code Call} receiving the event.
1047          * @param event The event.
1048          * @param extras Extras associated with the connection event.
1049          */
onConnectionEvent(Call call, String event, Bundle extras)1050         public void onConnectionEvent(Call call, String event, Bundle extras) {}
1051 
1052         /**
1053          * Invoked when the RTT mode changes for this call.
1054          * @param call The call whose RTT mode has changed.
1055          * @param mode the new RTT mode, one of
1056          * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1057          *             or {@link RttCall#RTT_MODE_VCO}
1058          */
onRttModeChanged(Call call, int mode)1059         public void onRttModeChanged(Call call, int mode) {}
1060 
1061         /**
1062          * Invoked when the call's RTT status changes, either from off to on or from on to off.
1063          * @param call The call whose RTT status has changed.
1064          * @param enabled whether RTT is now enabled or disabled
1065          * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1066          *                on, null otherwise.
1067          */
onRttStatusChanged(Call call, boolean enabled, RttCall rttCall)1068         public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1069 
1070         /**
1071          * Invoked when the remote end of the connection has requested that an RTT communication
1072          * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1073          * with the same ID that this method is invoked with.
1074          * @param call The call which the RTT request was placed on
1075          * @param id The ID of the request.
1076          */
onRttRequest(Call call, int id)1077         public void onRttRequest(Call call, int id) {}
1078 
1079         /**
1080          * Invoked when the RTT session failed to initiate for some reason, including rejection
1081          * by the remote party.
1082          * @param call The call which the RTT initiation failure occurred on.
1083          * @param reason One of the status codes defined in
1084          *               {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1085          *               {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1086          */
onRttInitiationFailure(Call call, int reason)1087         public void onRttInitiationFailure(Call call, int reason) {}
1088 
1089         /**
1090          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1091          * has completed successfully.
1092          * <p>
1093          * For a full discussion of the handover process and the APIs involved, see
1094          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1095          *
1096          * @param call The call which had initiated handover.
1097          */
onHandoverComplete(Call call)1098         public void onHandoverComplete(Call call) {}
1099 
1100         /**
1101          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1102          * has failed.
1103          * <p>
1104          * For a full discussion of the handover process and the APIs involved, see
1105          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1106          *
1107          * @param call The call which had initiated handover.
1108          * @param failureReason Error reason for failure.
1109          */
onHandoverFailed(Call call, @HandoverFailureErrors int failureReason)1110         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
1111     }
1112 
1113     /**
1114      * A class that holds the state that describes the state of the RTT channel to the remote
1115      * party, if it is active.
1116      */
1117     public static final class RttCall {
1118         /** @hide */
1119         @Retention(RetentionPolicy.SOURCE)
1120         @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1121         public @interface RttAudioMode {}
1122 
1123         /**
1124          * For metrics use. Default value in the proto.
1125          * @hide
1126          */
1127         public static final int RTT_MODE_INVALID = 0;
1128 
1129         /**
1130          * Indicates that there should be a bidirectional audio stream between the two parties
1131          * on the call.
1132          */
1133         public static final int RTT_MODE_FULL = 1;
1134 
1135         /**
1136          * Indicates that the local user should be able to hear the audio stream from the remote
1137          * user, but not vice versa. Equivalent to muting the microphone.
1138          */
1139         public static final int RTT_MODE_HCO = 2;
1140 
1141         /**
1142          * Indicates that the remote user should be able to hear the audio stream from the local
1143          * user, but not vice versa. Equivalent to setting the volume to zero.
1144          */
1145         public static final int RTT_MODE_VCO = 3;
1146 
1147         private static final int READ_BUFFER_SIZE = 1000;
1148 
1149         private InputStreamReader mReceiveStream;
1150         private OutputStreamWriter mTransmitStream;
1151         private int mRttMode;
1152         private final InCallAdapter mInCallAdapter;
1153         private final String mTelecomCallId;
1154         private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1155 
1156         /**
1157          * @hide
1158          */
RttCall(String telecomCallId, InputStreamReader receiveStream, OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter)1159         public RttCall(String telecomCallId, InputStreamReader receiveStream,
1160                 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1161             mTelecomCallId = telecomCallId;
1162             mReceiveStream = receiveStream;
1163             mTransmitStream = transmitStream;
1164             mRttMode = mode;
1165             mInCallAdapter = inCallAdapter;
1166         }
1167 
1168         /**
1169          * Returns the current RTT audio mode.
1170          * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1171          * {@link #RTT_MODE_HCO}.
1172          */
getRttAudioMode()1173         public int getRttAudioMode() {
1174             return mRttMode;
1175         }
1176 
1177         /**
1178          * Sets the RTT audio mode. The requested mode change will be communicated through
1179          * {@link Callback#onRttModeChanged(Call, int)}.
1180          * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1181          * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1182          */
setRttMode(@ttAudioMode int mode)1183         public void setRttMode(@RttAudioMode int mode) {
1184             mInCallAdapter.setRttMode(mTelecomCallId, mode);
1185         }
1186 
1187         /**
1188          * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1189          * RTT transmits text in real-time, this method should be called once for each character
1190          * the user enters into the device.
1191          *
1192          * This method is not thread-safe -- calling it from multiple threads simultaneously may
1193          * lead to interleaved text.
1194          * @param input The message to send to the remote user.
1195          */
write(String input)1196         public void write(String input) throws IOException {
1197             mTransmitStream.write(input);
1198             mTransmitStream.flush();
1199         }
1200 
1201         /**
1202          * Reads a string from the remote user, blocking if there is no data available. Returns
1203          * {@code null} if the RTT conversation has been terminated and there is no further data
1204          * to read.
1205          *
1206          * This method is not thread-safe -- calling it from multiple threads simultaneously may
1207          * lead to interleaved text.
1208          * @return A string containing text sent by the remote user, or {@code null} if the
1209          * conversation has been terminated or if there was an error while reading.
1210          */
read()1211         public String read() {
1212             try {
1213                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1214                 if (numRead < 0) {
1215                     return null;
1216                 }
1217                 return new String(mReadBuffer, 0, numRead);
1218             } catch (IOException e) {
1219                 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
1220                 return null;
1221             }
1222         }
1223 
1224         /**
1225          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1226          * be read.
1227          * @return A string containing text entered by the user, or {@code null} if the user has
1228          * not entered any new text yet.
1229          */
readImmediately()1230         public String readImmediately() throws IOException {
1231             if (mReceiveStream.ready()) {
1232                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1233                 if (numRead < 0) {
1234                     return null;
1235                 }
1236                 return new String(mReadBuffer, 0, numRead);
1237             } else {
1238                 return null;
1239             }
1240         }
1241 
1242         /**
1243          * Closes the underlying file descriptors
1244          * @hide
1245          */
close()1246         public void close() {
1247             try {
1248                 mReceiveStream.close();
1249             } catch (IOException e) {
1250                 // ignore
1251             }
1252             try {
1253                 mTransmitStream.close();
1254             } catch (IOException e) {
1255                 // ignore
1256             }
1257         }
1258     }
1259 
1260     /**
1261      * @deprecated Use {@code Call.Callback} instead.
1262      * @hide
1263      */
1264     @Deprecated
1265     @SystemApi
1266     public static abstract class Listener extends Callback { }
1267 
1268     private final Phone mPhone;
1269     private final String mTelecomCallId;
1270     private final InCallAdapter mInCallAdapter;
1271     private final List<String> mChildrenIds = new ArrayList<>();
1272     private final List<Call> mChildren = new ArrayList<>();
1273     private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
1274     private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
1275     private final List<Call> mConferenceableCalls = new ArrayList<>();
1276     private final List<Call> mUnmodifiableConferenceableCalls =
1277             Collections.unmodifiableList(mConferenceableCalls);
1278 
1279     private boolean mChildrenCached;
1280     private String mParentId = null;
1281     private int mState;
1282     private List<String> mCannedTextResponses = null;
1283     private String mCallingPackage;
1284     private int mTargetSdkVersion;
1285     private String mRemainingPostDialSequence;
1286     private VideoCallImpl mVideoCallImpl;
1287     private RttCall mRttCall;
1288     private Details mDetails;
1289     private Bundle mExtras;
1290 
1291     /**
1292      * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1293      *
1294      * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1295      * remaining or this {@code Call} is not in a post-dial state.
1296      */
getRemainingPostDialSequence()1297     public String getRemainingPostDialSequence() {
1298         return mRemainingPostDialSequence;
1299     }
1300 
1301     /**
1302      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
1303      * @param videoState The video state in which to answer the call.
1304      */
answer(@ideoProfile.VideoState int videoState)1305     public void answer(@VideoProfile.VideoState int videoState) {
1306         mInCallAdapter.answerCall(mTelecomCallId, videoState);
1307     }
1308 
1309     /**
1310      * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1311      *
1312      * @param address The address to which the call will be deflected.
1313      */
deflect(Uri address)1314     public void deflect(Uri address) {
1315         mInCallAdapter.deflectCall(mTelecomCallId, address);
1316     }
1317 
1318     /**
1319      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1320      *
1321      * @param rejectWithMessage Whether to reject with a text message.
1322      * @param textMessage An optional text message with which to respond.
1323      */
reject(boolean rejectWithMessage, String textMessage)1324     public void reject(boolean rejectWithMessage, String textMessage) {
1325         mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
1326     }
1327 
1328     /**
1329      * Instructs this {@code Call} to disconnect.
1330      */
disconnect()1331     public void disconnect() {
1332         mInCallAdapter.disconnectCall(mTelecomCallId);
1333     }
1334 
1335     /**
1336      * Instructs this {@code Call} to go on hold.
1337      */
hold()1338     public void hold() {
1339         mInCallAdapter.holdCall(mTelecomCallId);
1340     }
1341 
1342     /**
1343      * Instructs this {@link #STATE_HOLDING} call to release from hold.
1344      */
unhold()1345     public void unhold() {
1346         mInCallAdapter.unholdCall(mTelecomCallId);
1347     }
1348 
1349     /**
1350      * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1351      *
1352      * Any other currently playing DTMF tone in the specified call is immediately stopped.
1353      *
1354      * @param digit A character representing the DTMF digit for which to play the tone. This
1355      *         value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1356      */
playDtmfTone(char digit)1357     public void playDtmfTone(char digit) {
1358         mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
1359     }
1360 
1361     /**
1362      * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1363      * currently playing.
1364      *
1365      * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1366      * currently playing, this method will do nothing.
1367      */
stopDtmfTone()1368     public void stopDtmfTone() {
1369         mInCallAdapter.stopDtmfTone(mTelecomCallId);
1370     }
1371 
1372     /**
1373      * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1374      *
1375      * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1376      * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
1377      *
1378      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
1379      * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1380      *
1381      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
1382      * {@code Call} will pause playing the tones and notify callbacks via
1383      * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
1384      * should display to the user an indication of this state and an affordance to continue
1385      * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1386      * app should invoke the {@link #postDialContinue(boolean)} method.
1387      *
1388      * @param proceed Whether or not to continue with the post-dial sequence.
1389      */
postDialContinue(boolean proceed)1390     public void postDialContinue(boolean proceed) {
1391         mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
1392     }
1393 
1394     /**
1395      * Notifies this {@code Call} that an account has been selected and to proceed with placing
1396      * an outgoing call. Optionally sets this account as the default account.
1397      */
phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault)1398     public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1399         mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
1400 
1401     }
1402 
1403     /**
1404      * Instructs this {@code Call} to enter a conference.
1405      *
1406      * @param callToConferenceWith The other call with which to conference.
1407      */
conference(Call callToConferenceWith)1408     public void conference(Call callToConferenceWith) {
1409         if (callToConferenceWith != null) {
1410             mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
1411         }
1412     }
1413 
1414     /**
1415      * Instructs this {@code Call} to split from any conference call with which it may be
1416      * connected.
1417      */
splitFromConference()1418     public void splitFromConference() {
1419         mInCallAdapter.splitFromConference(mTelecomCallId);
1420     }
1421 
1422     /**
1423      * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
1424      */
mergeConference()1425     public void mergeConference() {
1426         mInCallAdapter.mergeConference(mTelecomCallId);
1427     }
1428 
1429     /**
1430      * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
1431      */
swapConference()1432     public void swapConference() {
1433         mInCallAdapter.swapConference(mTelecomCallId);
1434     }
1435 
1436     /**
1437      * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1438      * device.
1439      * <p>
1440      * Calls to this method are ignored if the call does not have the
1441      * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1442      * <p>
1443      * An {@link InCallService} will only see calls which support this method if it has the
1444      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1445      * in its manifest.
1446      */
pullExternalCall()1447     public void pullExternalCall() {
1448         // If this isn't an external call, ignore the request.
1449         if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1450             return;
1451         }
1452 
1453         mInCallAdapter.pullExternalCall(mTelecomCallId);
1454     }
1455 
1456     /**
1457      * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1458      * the {@link ConnectionService}.
1459      * <p>
1460      * Call events are used to communicate point in time information from an {@link InCallService}
1461      * to a {@link ConnectionService}.  A {@link ConnectionService} implementation could define
1462      * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1463      * {@link ConnectionService}.
1464      * <p>
1465      * A {@link ConnectionService} can communicate to the {@link InCallService} using
1466      * {@link Connection#sendConnectionEvent(String, Bundle)}.
1467      * <p>
1468      * Events are exposed to {@link ConnectionService} implementations via
1469      * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1470      * <p>
1471      * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
1472      * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1473      * ignore some events altogether.
1474      * <p>
1475      * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1476      * conflicts between {@link InCallService} implementations.  Further, {@link InCallService}
1477      * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1478      * they define their own event types in this namespace.  When defining a custom event type,
1479      * ensure the contents of the extras {@link Bundle} is clearly defined.  Extra keys for this
1480      * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1481      * <p>
1482      * When defining events and the associated extras, it is important to keep their behavior
1483      * consistent when the associated {@link InCallService} is updated.  Support for deprecated
1484      * events/extras should me maintained to ensure backwards compatibility with older
1485      * {@link ConnectionService} implementations which were built to support the older behavior.
1486      *
1487      * @param event The connection event.
1488      * @param extras Bundle containing extra information associated with the event.
1489      */
sendCallEvent(String event, Bundle extras)1490     public void sendCallEvent(String event, Bundle extras) {
1491         mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
1492     }
1493 
1494     /**
1495      * Sends an RTT upgrade request to the remote end of the connection. Success is not
1496      * guaranteed, and notification of success will be via the
1497      * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1498      */
sendRttRequest()1499     public void sendRttRequest() {
1500         mInCallAdapter.sendRttRequest(mTelecomCallId);
1501     }
1502 
1503     /**
1504      * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
1505      * callback.
1506      * The ID used here should be the same as the ID that was received via the callback.
1507      * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
1508      * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
1509      */
respondToRttRequest(int id, boolean accept)1510     public void respondToRttRequest(int id, boolean accept) {
1511         mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
1512     }
1513 
1514     /**
1515      * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
1516      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
1517      * handover.
1518      * <p>
1519      * A call handover is the process where an ongoing call is transferred from one app (i.e.
1520      * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
1521      * mobile network call in a video calling app.  The mobile network call via the Telephony stack
1522      * is referred to as the source of the handover, and the video calling app is referred to as the
1523      * destination.
1524      * <p>
1525      * When considering a handover scenario the device this method is called on is considered the
1526      * <em>initiating</em> device (since the user initiates the handover from this device), and the
1527      * other device is considered the <em>receiving</em> device.
1528      * <p>
1529      * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
1530      * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
1531      * and invoke
1532      * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1533      * ConnectionRequest)} to inform the destination app that a request has been made to handover a
1534      * call to it.  The app returns an instance of {@link Connection} to represent the handover call
1535      * At this point the app should display UI to indicate to the user that a call
1536      * handover is in process.
1537      * <p>
1538      * The destination app is responsible for communicating the handover request from the
1539      * <em>initiating</em> device to the <em>receiving</em> device.
1540      * <p>
1541      * When the app on the <em>receiving</em> device receives the handover request, it calls
1542      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
1543      * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
1544      * the destination app on the <em>receiving</em> device should show UI to allow the user to
1545      * choose whether they want to continue their call in the destination app.
1546      * <p>
1547      * When the destination app on the <em>receiving</em> device calls
1548      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
1549      * {@link ConnectionService} and call
1550      * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
1551      * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
1552      * {@link Connection} to represent the handover call.
1553      * <p>
1554      * If the user of the <em>receiving</em> device accepts the handover, the app calls
1555      * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
1556      * original call.  If the user rejects the handover, the app calls
1557      * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
1558      * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
1559      * <p>
1560      * Telecom will only allow handovers from {@link PhoneAccount}s which declare
1561      * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
1562      * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
1563      * <p>
1564      * Errors in the handover process are reported to the {@link InCallService} via
1565      * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
1566      * the involved {@link ConnectionService}s via
1567      * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
1568      *
1569      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
1570      *                 this call to.
1571      * @param videoState Indicates the video state desired after the handover (see the
1572      *               {@code STATE_*} constants defined in {@link VideoProfile}).
1573      * @param extras Bundle containing extra information to be passed to the
1574      *               {@link ConnectionService}
1575      */
handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState, Bundle extras)1576     public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
1577             Bundle extras) {
1578         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
1579     }
1580 
1581     /**
1582      * Terminate the RTT session on this call. The resulting state change will be notified via
1583      * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1584      */
stopRtt()1585     public void stopRtt() {
1586         mInCallAdapter.stopRtt(mTelecomCallId);
1587     }
1588 
1589     /**
1590      * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
1591      * added.
1592      * <p>
1593      * No assumptions should be made as to how an In-Call UI or service will handle these
1594      * extras.  Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
1595      *
1596      * @param extras The extras to add.
1597      */
putExtras(Bundle extras)1598     public final void putExtras(Bundle extras) {
1599         if (extras == null) {
1600             return;
1601         }
1602 
1603         if (mExtras == null) {
1604             mExtras = new Bundle();
1605         }
1606         mExtras.putAll(extras);
1607         mInCallAdapter.putExtras(mTelecomCallId, extras);
1608     }
1609 
1610     /**
1611      * Adds a boolean extra to this {@link Call}.
1612      *
1613      * @param key The extra key.
1614      * @param value The value.
1615      * @hide
1616      */
putExtra(String key, boolean value)1617     public final void putExtra(String key, boolean value) {
1618         if (mExtras == null) {
1619             mExtras = new Bundle();
1620         }
1621         mExtras.putBoolean(key, value);
1622         mInCallAdapter.putExtra(mTelecomCallId, key, value);
1623     }
1624 
1625     /**
1626      * Adds an integer extra to this {@link Call}.
1627      *
1628      * @param key The extra key.
1629      * @param value The value.
1630      * @hide
1631      */
putExtra(String key, int value)1632     public final void putExtra(String key, int value) {
1633         if (mExtras == null) {
1634             mExtras = new Bundle();
1635         }
1636         mExtras.putInt(key, value);
1637         mInCallAdapter.putExtra(mTelecomCallId, key, value);
1638     }
1639 
1640     /**
1641      * Adds a string extra to this {@link Call}.
1642      *
1643      * @param key The extra key.
1644      * @param value The value.
1645      * @hide
1646      */
putExtra(String key, String value)1647     public final void putExtra(String key, String value) {
1648         if (mExtras == null) {
1649             mExtras = new Bundle();
1650         }
1651         mExtras.putString(key, value);
1652         mInCallAdapter.putExtra(mTelecomCallId, key, value);
1653     }
1654 
1655     /**
1656      * Removes extras from this {@link Call}.
1657      *
1658      * @param keys The keys of the extras to remove.
1659      */
removeExtras(List<String> keys)1660     public final void removeExtras(List<String> keys) {
1661         if (mExtras != null) {
1662             for (String key : keys) {
1663                 mExtras.remove(key);
1664             }
1665             if (mExtras.size() == 0) {
1666                 mExtras = null;
1667             }
1668         }
1669         mInCallAdapter.removeExtras(mTelecomCallId, keys);
1670     }
1671 
1672     /**
1673      * Removes extras from this {@link Call}.
1674      *
1675      * @param keys The keys of the extras to remove.
1676      */
removeExtras(String .... keys)1677     public final void removeExtras(String ... keys) {
1678         removeExtras(Arrays.asList(keys));
1679     }
1680 
1681     /**
1682      * Obtains the parent of this {@code Call} in a conference, if any.
1683      *
1684      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
1685      * child of any conference {@code Call}s.
1686      */
getParent()1687     public Call getParent() {
1688         if (mParentId != null) {
1689             return mPhone.internalGetCallByTelecomId(mParentId);
1690         }
1691         return null;
1692     }
1693 
1694     /**
1695      * Obtains the children of this conference {@code Call}, if any.
1696      *
1697      * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
1698      * {@code List} otherwise.
1699      */
getChildren()1700     public List<Call> getChildren() {
1701         if (!mChildrenCached) {
1702             mChildrenCached = true;
1703             mChildren.clear();
1704 
1705             for(String id : mChildrenIds) {
1706                 Call call = mPhone.internalGetCallByTelecomId(id);
1707                 if (call == null) {
1708                     // At least one child was still not found, so do not save true for "cached"
1709                     mChildrenCached = false;
1710                 } else {
1711                     mChildren.add(call);
1712                 }
1713             }
1714         }
1715 
1716         return mUnmodifiableChildren;
1717     }
1718 
1719     /**
1720      * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
1721      *
1722      * @return The list of conferenceable {@code Call}s.
1723      */
getConferenceableCalls()1724     public List<Call> getConferenceableCalls() {
1725         return mUnmodifiableConferenceableCalls;
1726     }
1727 
1728     /**
1729      * Obtains the state of this {@code Call}.
1730      *
1731      * @return A state value, chosen from the {@code STATE_*} constants.
1732      */
getState()1733     public int getState() {
1734         return mState;
1735     }
1736 
1737     /**
1738      * Obtains a list of canned, pre-configured message responses to present to the user as
1739      * ways of rejecting this {@code Call} using via a text message.
1740      *
1741      * @see #reject(boolean, String)
1742      *
1743      * @return A list of canned text message responses.
1744      */
getCannedTextResponses()1745     public List<String> getCannedTextResponses() {
1746         return mCannedTextResponses;
1747     }
1748 
1749     /**
1750      * Obtains an object that can be used to display video from this {@code Call}.
1751      *
1752      * @return An {@code Call.VideoCall}.
1753      */
getVideoCall()1754     public InCallService.VideoCall getVideoCall() {
1755         return mVideoCallImpl;
1756     }
1757 
1758     /**
1759      * Obtains an object containing call details.
1760      *
1761      * @return A {@link Details} object. Depending on the state of the {@code Call}, the
1762      * result may be {@code null}.
1763      */
getDetails()1764     public Details getDetails() {
1765         return mDetails;
1766     }
1767 
1768     /**
1769      * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
1770      * receive RTT text data, as well as to change the RTT mode.
1771      * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
1772      */
getRttCall()1773     public @Nullable RttCall getRttCall() {
1774         return mRttCall;
1775     }
1776 
1777     /**
1778      * Returns whether this call has an active RTT connection.
1779      * @return true if there is a connection, false otherwise.
1780      */
isRttActive()1781     public boolean isRttActive() {
1782         return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
1783     }
1784 
1785     /**
1786      * Registers a callback to this {@code Call}.
1787      *
1788      * @param callback A {@code Callback}.
1789      */
registerCallback(Callback callback)1790     public void registerCallback(Callback callback) {
1791         registerCallback(callback, new Handler());
1792     }
1793 
1794     /**
1795      * Registers a callback to this {@code Call}.
1796      *
1797      * @param callback A {@code Callback}.
1798      * @param handler A handler which command and status changes will be delivered to.
1799      */
registerCallback(Callback callback, Handler handler)1800     public void registerCallback(Callback callback, Handler handler) {
1801         unregisterCallback(callback);
1802         // Don't allow new callback registration if the call is already being destroyed.
1803         if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
1804             mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
1805         }
1806     }
1807 
1808     /**
1809      * Unregisters a callback from this {@code Call}.
1810      *
1811      * @param callback A {@code Callback}.
1812      */
unregisterCallback(Callback callback)1813     public void unregisterCallback(Callback callback) {
1814         // Don't allow callback deregistration if the call is already being destroyed.
1815         if (callback != null && mState != STATE_DISCONNECTED) {
1816             for (CallbackRecord<Callback> record : mCallbackRecords) {
1817                 if (record.getCallback() == callback) {
1818                     mCallbackRecords.remove(record);
1819                     break;
1820                 }
1821             }
1822         }
1823     }
1824 
1825     @Override
toString()1826     public String toString() {
1827         return new StringBuilder().
1828                 append("Call [id: ").
1829                 append(mTelecomCallId).
1830                 append(", state: ").
1831                 append(stateToString(mState)).
1832                 append(", details: ").
1833                 append(mDetails).
1834                 append("]").toString();
1835     }
1836 
1837     /**
1838      * @param state An integer value of a {@code STATE_*} constant.
1839      * @return A string representation of the value.
1840      */
stateToString(int state)1841     private static String stateToString(int state) {
1842         switch (state) {
1843             case STATE_NEW:
1844                 return "NEW";
1845             case STATE_RINGING:
1846                 return "RINGING";
1847             case STATE_DIALING:
1848                 return "DIALING";
1849             case STATE_ACTIVE:
1850                 return "ACTIVE";
1851             case STATE_HOLDING:
1852                 return "HOLDING";
1853             case STATE_DISCONNECTED:
1854                 return "DISCONNECTED";
1855             case STATE_CONNECTING:
1856                 return "CONNECTING";
1857             case STATE_DISCONNECTING:
1858                 return "DISCONNECTING";
1859             case STATE_SELECT_PHONE_ACCOUNT:
1860                 return "SELECT_PHONE_ACCOUNT";
1861             default:
1862                 Log.w(Call.class, "Unknown state %d", state);
1863                 return "UNKNOWN";
1864         }
1865     }
1866 
1867     /**
1868      * Adds a listener to this {@code Call}.
1869      *
1870      * @param listener A {@code Listener}.
1871      * @deprecated Use {@link #registerCallback} instead.
1872      * @hide
1873      */
1874     @Deprecated
1875     @SystemApi
addListener(Listener listener)1876     public void addListener(Listener listener) {
1877         registerCallback(listener);
1878     }
1879 
1880     /**
1881      * Removes a listener from this {@code Call}.
1882      *
1883      * @param listener A {@code Listener}.
1884      * @deprecated Use {@link #unregisterCallback} instead.
1885      * @hide
1886      */
1887     @Deprecated
1888     @SystemApi
removeListener(Listener listener)1889     public void removeListener(Listener listener) {
1890         unregisterCallback(listener);
1891     }
1892 
1893     /** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage, int targetSdkVersion)1894     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
1895          int targetSdkVersion) {
1896         mPhone = phone;
1897         mTelecomCallId = telecomCallId;
1898         mInCallAdapter = inCallAdapter;
1899         mState = STATE_NEW;
1900         mCallingPackage = callingPackage;
1901         mTargetSdkVersion = targetSdkVersion;
1902     }
1903 
1904     /** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state, String callingPackage, int targetSdkVersion)1905     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
1906             String callingPackage, int targetSdkVersion) {
1907         mPhone = phone;
1908         mTelecomCallId = telecomCallId;
1909         mInCallAdapter = inCallAdapter;
1910         mState = state;
1911         mCallingPackage = callingPackage;
1912         mTargetSdkVersion = targetSdkVersion;
1913     }
1914 
1915     /** {@hide} */
internalGetCallId()1916     final String internalGetCallId() {
1917         return mTelecomCallId;
1918     }
1919 
1920     /** {@hide} */
internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap)1921     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
1922 
1923         // First, we update the internal state as far as possible before firing any updates.
1924         Details details = Details.createFromParcelableCall(parcelableCall);
1925         boolean detailsChanged = !Objects.equals(mDetails, details);
1926         if (detailsChanged) {
1927             mDetails = details;
1928         }
1929 
1930         boolean cannedTextResponsesChanged = false;
1931         if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
1932                 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
1933             mCannedTextResponses =
1934                     Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
1935             cannedTextResponsesChanged = true;
1936         }
1937 
1938         VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
1939                 mTargetSdkVersion);
1940         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
1941                 !Objects.equals(mVideoCallImpl, newVideoCallImpl);
1942         if (videoCallChanged) {
1943             mVideoCallImpl = newVideoCallImpl;
1944         }
1945         if (mVideoCallImpl != null) {
1946             mVideoCallImpl.setVideoState(getDetails().getVideoState());
1947         }
1948 
1949         int state = parcelableCall.getState();
1950         boolean stateChanged = mState != state;
1951         if (stateChanged) {
1952             mState = state;
1953         }
1954 
1955         String parentId = parcelableCall.getParentCallId();
1956         boolean parentChanged = !Objects.equals(mParentId, parentId);
1957         if (parentChanged) {
1958             mParentId = parentId;
1959         }
1960 
1961         List<String> childCallIds = parcelableCall.getChildCallIds();
1962         boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
1963         if (childrenChanged) {
1964             mChildrenIds.clear();
1965             mChildrenIds.addAll(parcelableCall.getChildCallIds());
1966             mChildrenCached = false;
1967         }
1968 
1969         List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
1970         List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
1971         for (String otherId : conferenceableCallIds) {
1972             if (callIdMap.containsKey(otherId)) {
1973                 conferenceableCalls.add(callIdMap.get(otherId));
1974             }
1975         }
1976 
1977         if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
1978             mConferenceableCalls.clear();
1979             mConferenceableCalls.addAll(conferenceableCalls);
1980             fireConferenceableCallsChanged();
1981         }
1982 
1983         boolean isRttChanged = false;
1984         boolean rttModeChanged = false;
1985         if (parcelableCall.getIsRttCallChanged()
1986                 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
1987             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
1988             InputStreamReader receiveStream = new InputStreamReader(
1989                     new ParcelFileDescriptor.AutoCloseInputStream(
1990                             parcelableRttCall.getReceiveStream()),
1991                     StandardCharsets.UTF_8);
1992             OutputStreamWriter transmitStream = new OutputStreamWriter(
1993                     new ParcelFileDescriptor.AutoCloseOutputStream(
1994                             parcelableRttCall.getTransmitStream()),
1995                     StandardCharsets.UTF_8);
1996             RttCall newRttCall = new Call.RttCall(mTelecomCallId,
1997                     receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
1998             if (mRttCall == null) {
1999                 isRttChanged = true;
2000             } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2001                 rttModeChanged = true;
2002             }
2003             mRttCall = newRttCall;
2004         } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2005                 && parcelableCall.getIsRttCallChanged()) {
2006             isRttChanged = true;
2007             mRttCall = null;
2008         }
2009 
2010         // Now we fire updates, ensuring that any client who listens to any of these notifications
2011         // gets the most up-to-date state.
2012 
2013         if (stateChanged) {
2014             fireStateChanged(mState);
2015         }
2016         if (detailsChanged) {
2017             fireDetailsChanged(mDetails);
2018         }
2019         if (cannedTextResponsesChanged) {
2020             fireCannedTextResponsesLoaded(mCannedTextResponses);
2021         }
2022         if (videoCallChanged) {
2023             fireVideoCallChanged(mVideoCallImpl);
2024         }
2025         if (parentChanged) {
2026             fireParentChanged(getParent());
2027         }
2028         if (childrenChanged) {
2029             fireChildrenChanged(getChildren());
2030         }
2031         if (isRttChanged) {
2032             fireOnIsRttChanged(mRttCall != null, mRttCall);
2033         }
2034         if (rttModeChanged) {
2035             fireOnRttModeChanged(mRttCall.getRttAudioMode());
2036         }
2037 
2038         // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2039         // remove ourselves from the Phone. Note that we do this after completing all state updates
2040         // so a client can cleanly transition all their UI to the state appropriate for a
2041         // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2042         if (mState == STATE_DISCONNECTED) {
2043             fireCallDestroyed();
2044         }
2045     }
2046 
2047     /** {@hide} */
internalSetPostDialWait(String remaining)2048     final void internalSetPostDialWait(String remaining) {
2049         mRemainingPostDialSequence = remaining;
2050         firePostDialWait(mRemainingPostDialSequence);
2051     }
2052 
2053     /** {@hide} */
internalSetDisconnected()2054     final void internalSetDisconnected() {
2055         if (mState != Call.STATE_DISCONNECTED) {
2056             mState = Call.STATE_DISCONNECTED;
2057             fireStateChanged(mState);
2058             fireCallDestroyed();
2059         }
2060     }
2061 
2062     /** {@hide} */
internalOnConnectionEvent(String event, Bundle extras)2063     final void internalOnConnectionEvent(String event, Bundle extras) {
2064         fireOnConnectionEvent(event, extras);
2065     }
2066 
2067     /** {@hide} */
internalOnRttUpgradeRequest(final int requestId)2068     final void internalOnRttUpgradeRequest(final int requestId) {
2069         for (CallbackRecord<Callback> record : mCallbackRecords) {
2070             final Call call = this;
2071             final Callback callback = record.getCallback();
2072             record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2073         }
2074     }
2075 
2076     /** @hide */
internalOnRttInitiationFailure(int reason)2077     final void internalOnRttInitiationFailure(int reason) {
2078         for (CallbackRecord<Callback> record : mCallbackRecords) {
2079             final Call call = this;
2080             final Callback callback = record.getCallback();
2081             record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2082         }
2083     }
2084 
2085     /** {@hide} */
internalOnHandoverFailed(int error)2086     final void internalOnHandoverFailed(int error) {
2087         for (CallbackRecord<Callback> record : mCallbackRecords) {
2088             final Call call = this;
2089             final Callback callback = record.getCallback();
2090             record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2091         }
2092     }
2093 
2094     /** {@hide} */
internalOnHandoverComplete()2095     final void internalOnHandoverComplete() {
2096         for (CallbackRecord<Callback> record : mCallbackRecords) {
2097             final Call call = this;
2098             final Callback callback = record.getCallback();
2099             record.getHandler().post(() -> callback.onHandoverComplete(call));
2100         }
2101     }
2102 
fireStateChanged(final int newState)2103     private void fireStateChanged(final int newState) {
2104         for (CallbackRecord<Callback> record : mCallbackRecords) {
2105             final Call call = this;
2106             final Callback callback = record.getCallback();
2107             record.getHandler().post(new Runnable() {
2108                 @Override
2109                 public void run() {
2110                     callback.onStateChanged(call, newState);
2111                 }
2112             });
2113         }
2114     }
2115 
fireParentChanged(final Call newParent)2116     private void fireParentChanged(final Call newParent) {
2117         for (CallbackRecord<Callback> record : mCallbackRecords) {
2118             final Call call = this;
2119             final Callback callback = record.getCallback();
2120             record.getHandler().post(new Runnable() {
2121                 @Override
2122                 public void run() {
2123                     callback.onParentChanged(call, newParent);
2124                 }
2125             });
2126         }
2127     }
2128 
fireChildrenChanged(final List<Call> children)2129     private void fireChildrenChanged(final List<Call> children) {
2130         for (CallbackRecord<Callback> record : mCallbackRecords) {
2131             final Call call = this;
2132             final Callback callback = record.getCallback();
2133             record.getHandler().post(new Runnable() {
2134                 @Override
2135                 public void run() {
2136                     callback.onChildrenChanged(call, children);
2137                 }
2138             });
2139         }
2140     }
2141 
fireDetailsChanged(final Details details)2142     private void fireDetailsChanged(final Details details) {
2143         for (CallbackRecord<Callback> record : mCallbackRecords) {
2144             final Call call = this;
2145             final Callback callback = record.getCallback();
2146             record.getHandler().post(new Runnable() {
2147                 @Override
2148                 public void run() {
2149                     callback.onDetailsChanged(call, details);
2150                 }
2151             });
2152         }
2153     }
2154 
fireCannedTextResponsesLoaded(final List<String> cannedTextResponses)2155     private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2156         for (CallbackRecord<Callback> record : mCallbackRecords) {
2157             final Call call = this;
2158             final Callback callback = record.getCallback();
2159             record.getHandler().post(new Runnable() {
2160                 @Override
2161                 public void run() {
2162                     callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2163                 }
2164             });
2165         }
2166     }
2167 
fireVideoCallChanged(final InCallService.VideoCall videoCall)2168     private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2169         for (CallbackRecord<Callback> record : mCallbackRecords) {
2170             final Call call = this;
2171             final Callback callback = record.getCallback();
2172             record.getHandler().post(new Runnable() {
2173                 @Override
2174                 public void run() {
2175                     callback.onVideoCallChanged(call, videoCall);
2176                 }
2177             });
2178         }
2179     }
2180 
firePostDialWait(final String remainingPostDialSequence)2181     private void firePostDialWait(final String remainingPostDialSequence) {
2182         for (CallbackRecord<Callback> record : mCallbackRecords) {
2183             final Call call = this;
2184             final Callback callback = record.getCallback();
2185             record.getHandler().post(new Runnable() {
2186                 @Override
2187                 public void run() {
2188                     callback.onPostDialWait(call, remainingPostDialSequence);
2189                 }
2190             });
2191         }
2192     }
2193 
fireCallDestroyed()2194     private void fireCallDestroyed() {
2195         /**
2196          * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2197          * onCallRemoved callback, we remove this call from the Phone's record
2198          * only once all of the registered onCallDestroyed callbacks are executed.
2199          * All the callbacks get removed from our records as a part of this operation
2200          * since onCallDestroyed is the final callback.
2201          */
2202         final Call call = this;
2203         if (mCallbackRecords.isEmpty()) {
2204             // No callbacks registered, remove the call from Phone's record.
2205             mPhone.internalRemoveCall(call);
2206         }
2207         for (final CallbackRecord<Callback> record : mCallbackRecords) {
2208             final Callback callback = record.getCallback();
2209             record.getHandler().post(new Runnable() {
2210                 @Override
2211                 public void run() {
2212                     boolean isFinalRemoval = false;
2213                     RuntimeException toThrow = null;
2214                     try {
2215                         callback.onCallDestroyed(call);
2216                     } catch (RuntimeException e) {
2217                             toThrow = e;
2218                     }
2219                     synchronized(Call.this) {
2220                         mCallbackRecords.remove(record);
2221                         if (mCallbackRecords.isEmpty()) {
2222                             isFinalRemoval = true;
2223                         }
2224                     }
2225                     if (isFinalRemoval) {
2226                         mPhone.internalRemoveCall(call);
2227                     }
2228                     if (toThrow != null) {
2229                         throw toThrow;
2230                     }
2231                 }
2232             });
2233         }
2234     }
2235 
fireConferenceableCallsChanged()2236     private void fireConferenceableCallsChanged() {
2237         for (CallbackRecord<Callback> record : mCallbackRecords) {
2238             final Call call = this;
2239             final Callback callback = record.getCallback();
2240             record.getHandler().post(new Runnable() {
2241                 @Override
2242                 public void run() {
2243                     callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2244                 }
2245             });
2246         }
2247     }
2248 
2249     /**
2250      * Notifies listeners of an incoming connection event.
2251      * <p>
2252      * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2253      *
2254      * @param event
2255      * @param extras
2256      */
fireOnConnectionEvent(final String event, final Bundle extras)2257     private void fireOnConnectionEvent(final String event, final Bundle extras) {
2258         for (CallbackRecord<Callback> record : mCallbackRecords) {
2259             final Call call = this;
2260             final Callback callback = record.getCallback();
2261             record.getHandler().post(new Runnable() {
2262                 @Override
2263                 public void run() {
2264                     callback.onConnectionEvent(call, event, extras);
2265                 }
2266             });
2267         }
2268     }
2269 
2270     /**
2271      * Notifies listeners of an RTT on/off change
2272      *
2273      * @param enabled True if RTT is now enabled, false otherwise
2274      */
fireOnIsRttChanged(final boolean enabled, final RttCall rttCall)2275     private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2276         for (CallbackRecord<Callback> record : mCallbackRecords) {
2277             final Call call = this;
2278             final Callback callback = record.getCallback();
2279             record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2280         }
2281     }
2282 
2283     /**
2284      * Notifies listeners of a RTT mode change
2285      *
2286      * @param mode The new RTT mode
2287      */
fireOnRttModeChanged(final int mode)2288     private void fireOnRttModeChanged(final int mode) {
2289         for (CallbackRecord<Callback> record : mCallbackRecords) {
2290             final Call call = this;
2291             final Callback callback = record.getCallback();
2292             record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2293         }
2294     }
2295 
2296     /**
2297      * Determines if two bundles are equal.
2298      *
2299      * @param bundle The original bundle.
2300      * @param newBundle The bundle to compare with.
2301      * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2302      */
areBundlesEqual(Bundle bundle, Bundle newBundle)2303     private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2304         if (bundle == null || newBundle == null) {
2305             return bundle == newBundle;
2306         }
2307 
2308         if (bundle.size() != newBundle.size()) {
2309             return false;
2310         }
2311 
2312         for(String key : bundle.keySet()) {
2313             if (key != null) {
2314                 final Object value = bundle.get(key);
2315                 final Object newValue = newBundle.get(key);
2316                 if (!Objects.equals(value, newValue)) {
2317                     return false;
2318                 }
2319             }
2320         }
2321         return true;
2322     }
2323 }
2324