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
17package android.telecom;
18
19import android.annotation.IntDef;
20import android.annotation.Nullable;
21import android.annotation.SystemApi;
22import android.net.Uri;
23import android.os.Bundle;
24import android.os.Handler;
25import android.os.ParcelFileDescriptor;
26
27import java.io.IOException;
28import java.io.InputStreamReader;
29import java.io.OutputStreamWriter;
30import java.lang.String;
31import java.lang.annotation.Retention;
32import java.lang.annotation.RetentionPolicy;
33import java.nio.charset.StandardCharsets;
34import java.util.ArrayList;
35import java.util.Arrays;
36import java.util.Collections;
37import java.util.List;
38import java.util.Map;
39import java.util.Objects;
40import java.util.concurrent.CopyOnWriteArrayList;
41
42/**
43 * Represents an ongoing phone call that the in-call app should present to the user.
44 */
45public 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         */
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         */
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         */
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         */
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         */
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         */
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} */
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         */
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         */
623        public int getHandlePresentation() {
624            return mHandlePresentation;
625        }
626
627        /**
628         * @return The display name for the caller.
629         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
698        public GatewayInfo getGatewayInfo() {
699            return mGatewayInfo;
700        }
701
702        /**
703         * @return The video state of the {@code Call}.
704         */
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         */
713        public StatusHints getStatusHints() {
714            return mStatusHints;
715        }
716
717        /**
718         * @return The extras associated with this call.
719         */
720        public Bundle getExtras() {
721            return mExtras;
722        }
723
724        /**
725         * @return The extras used with the original intent to place this call.
726         */
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         */
739        public long getCreationTimeMillis() {
740            return mCreationTimeMillis;
741        }
742
743        @Override
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
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} */
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} */
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
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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         */
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     */
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     */
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     */
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     */
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     */
1331    public void disconnect() {
1332        mInCallAdapter.disconnectCall(mTelecomCallId);
1333    }
1334
1335    /**
1336     * Instructs this {@code Call} to go on hold.
1337     */
1338    public void hold() {
1339        mInCallAdapter.holdCall(mTelecomCallId);
1340    }
1341
1342    /**
1343     * Instructs this {@link #STATE_HOLDING} call to release from hold.
1344     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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
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
1889    public void removeListener(Listener listener) {
1890        unregisterCallback(listener);
1891    }
1892
1893    /** {@hide} */
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} */
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} */
1916    final String internalGetCallId() {
1917        return mTelecomCallId;
1918    }
1919
1920    /** {@hide} */
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} */
2048    final void internalSetPostDialWait(String remaining) {
2049        mRemainingPostDialSequence = remaining;
2050        firePostDialWait(mRemainingPostDialSequence);
2051    }
2052
2053    /** {@hide} */
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} */
2063    final void internalOnConnectionEvent(String event, Bundle extras) {
2064        fireOnConnectionEvent(event, extras);
2065    }
2066
2067    /** {@hide} */
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 */
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} */
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} */
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
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
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
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
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
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
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
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
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
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     */
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     */
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     */
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     */
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