• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.telecom;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SystemApi;
23 import android.annotation.TestApi;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.content.pm.ServiceInfo;
26 import android.net.Uri;
27 import android.os.Build;
28 import android.os.Bundle;
29 import android.os.Handler;
30 import android.os.ParcelFileDescriptor;
31 
32 import com.android.internal.telecom.IVideoProvider;
33 
34 import java.io.IOException;
35 import java.io.InputStreamReader;
36 import java.io.OutputStreamWriter;
37 import java.lang.annotation.Retention;
38 import java.lang.annotation.RetentionPolicy;
39 import java.nio.charset.StandardCharsets;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collections;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Objects;
46 import java.util.concurrent.CopyOnWriteArrayList;
47 
48 /**
49  * Represents an ongoing phone call that the in-call app should present to the user.
50  */
51 public final class Call {
52     /**
53      * The state of a {@code Call} when newly created.
54      */
55     public static final int STATE_NEW = 0;
56 
57     /**
58      * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
59      */
60     public static final int STATE_DIALING = 1;
61 
62     /**
63      * The state of an incoming {@code Call} when ringing locally, but not yet connected.
64      */
65     public static final int STATE_RINGING = 2;
66 
67     /**
68      * The state of a {@code Call} when in a holding state.
69      */
70     public static final int STATE_HOLDING = 3;
71 
72     /**
73      * The state of a {@code Call} when actively supporting conversation.
74      */
75     public static final int STATE_ACTIVE = 4;
76 
77     /**
78      * The state of a {@code Call} when no further voice or other communication is being
79      * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
80      * is no longer active, and the local data transport has or inevitably will release resources
81      * associated with this {@code Call}.
82      */
83     public static final int STATE_DISCONNECTED = 7;
84 
85     /**
86      * The state of an outgoing {@code Call} when waiting on user to select a
87      * {@link PhoneAccount} through which to place the call.
88      */
89     public static final int STATE_SELECT_PHONE_ACCOUNT = 8;
90 
91     /**
92      * @hide
93      * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
94      */
95     @Deprecated
96     @SystemApi
97     public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;
98 
99     /**
100      * The initial state of an outgoing {@code Call}.
101      * Common transitions are to {@link #STATE_DIALING} state for a successful call or
102      * {@link #STATE_DISCONNECTED} if it failed.
103      */
104     public static final int STATE_CONNECTING = 9;
105 
106     /**
107      * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
108      * call has not yet been disconnected by the underlying {@code ConnectionService}.  The next
109      * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
110      */
111     public static final int STATE_DISCONNECTING = 10;
112 
113     /**
114      * The state of an external call which is in the process of being pulled from a remote device to
115      * the local device.
116      * <p>
117      * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
118      * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
119      * <p>
120      * An {@link InCallService} will only see this state if it has the
121      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
122      * manifest.
123      */
124     public static final int STATE_PULLING_CALL = 11;
125 
126     /**
127      * The state of a call that is active with the network, but the audio from the call is
128      * being intercepted by an app on the local device. Telecom does not hold audio focus in this
129      * state, and the call will be invisible to the user except for a persistent notification.
130      */
131     public static final int STATE_AUDIO_PROCESSING = 12;
132 
133     /**
134      * The state of a call that is being presented to the user after being in
135      * {@link #STATE_AUDIO_PROCESSING}. The call is still active with the network in this case, and
136      * Telecom will hold audio focus and play a ringtone if appropriate.
137      */
138     public static final int STATE_SIMULATED_RINGING = 13;
139 
140     /**
141      * @hide
142      */
143     @IntDef(prefix = { "STATE_" },
144             value = {
145                     STATE_NEW,
146                     STATE_DIALING,
147                     STATE_RINGING,
148                     STATE_HOLDING,
149                     STATE_ACTIVE,
150                     STATE_DISCONNECTED,
151                     STATE_SELECT_PHONE_ACCOUNT,
152                     STATE_CONNECTING,
153                     STATE_DISCONNECTING,
154                     STATE_PULLING_CALL,
155                     STATE_AUDIO_PROCESSING,
156                     STATE_SIMULATED_RINGING
157             })
158     @Retention(RetentionPolicy.SOURCE)
159     public @interface CallState {};
160 
161     /**
162      * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
163      * extras. Used to pass the phone accounts to display on the front end to the user in order to
164      * select phone accounts to (for example) place a call.
165      * @deprecated Use the list from {@link #EXTRA_SUGGESTED_PHONE_ACCOUNTS} instead.
166      */
167     @Deprecated
168     public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";
169 
170     /**
171      * Key for extra used to pass along a list of {@link PhoneAccountSuggestion}s to the in-call
172      * UI when a call enters the {@link #STATE_SELECT_PHONE_ACCOUNT} state. The list included here
173      * will have the same length and be in the same order as the list passed with
174      * {@link #AVAILABLE_PHONE_ACCOUNTS}.
175      */
176     public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS =
177             "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
178 
179     /**
180      * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
181      * when the last outgoing emergency call was made.  This is used to identify potential emergency
182      * callbacks.
183      */
184     public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
185             "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
186 
187 
188     /**
189      * Extra key used to indicate whether a {@link CallScreeningService} has requested to silence
190      * the ringtone for a call.  If the {@link InCallService} declares
191      * {@link TelecomManager#METADATA_IN_CALL_SERVICE_RINGING} in its manifest, it should not
192      * play a ringtone for an incoming call with this extra key set.
193      */
194     public static final String EXTRA_SILENT_RINGING_REQUESTED =
195             "android.telecom.extra.SILENT_RINGING_REQUESTED";
196 
197     /**
198      * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
199      * Telecom that the user has requested that the current {@link Call} should be handed over
200      * to another {@link ConnectionService}.
201      * <p>
202      * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
203      * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
204      * @hide
205      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
206      * APIs instead.
207      */
208     public static final String EVENT_REQUEST_HANDOVER =
209             "android.telecom.event.REQUEST_HANDOVER";
210 
211     /**
212      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
213      * {@link PhoneAccountHandle} to which a call should be handed over to.
214      * @hide
215      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
216      * APIs instead.
217      */
218     public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
219             "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
220 
221     /**
222      * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
223      * video state of the call when it is handed over to the new {@link PhoneAccount}.
224      * <p>
225      * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
226      * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
227      * {@link VideoProfile#STATE_TX_ENABLED}.
228      * @hide
229      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
230      * APIs instead.
231      */
232     public static final String EXTRA_HANDOVER_VIDEO_STATE =
233             "android.telecom.extra.HANDOVER_VIDEO_STATE";
234 
235     /**
236      * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Used by the
237      * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
238      * information to the handover {@link ConnectionService} specified by
239      * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
240      * <p>
241      * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
242      * {@link ConnectionService} via the request extras when
243      * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
244      * is called to initate the handover.
245      * @hide
246      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
247      * APIs instead.
248      */
249     public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
250 
251     /**
252      * Call event sent from Telecom to the handover {@link ConnectionService} via
253      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
254      * to the {@link ConnectionService} has completed successfully.
255      * <p>
256      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
257      * @hide
258      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
259      * APIs instead.
260      */
261     public static final String EVENT_HANDOVER_COMPLETE =
262             "android.telecom.event.HANDOVER_COMPLETE";
263 
264     /**
265      * Call event sent from Telecom to the handover destination {@link ConnectionService} via
266      * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
267      * source connection has disconnected.  The {@link Bundle} parameter for the call event will be
268      * {@code null}.
269      * <p>
270      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
271      * @hide
272      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
273      * APIs instead.
274      */
275     public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
276             "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
277 
278     /**
279      * Call event sent from Telecom to the handover {@link ConnectionService} via
280      * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
281      * to the {@link ConnectionService} has failed.
282      * <p>
283      * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
284      * @hide
285      * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
286      * APIs instead.
287      */
288     public static final String EVENT_HANDOVER_FAILED =
289             "android.telecom.event.HANDOVER_FAILED";
290 
291     /**
292      * Event reported from the Telecom stack to report an in-call diagnostic message which the
293      * dialer app may opt to display to the user.  A diagnostic message is used to communicate
294      * scenarios the device has detected which may impact the quality of the ongoing call.
295      * <p>
296      * For example a problem with a bluetooth headset may generate a recommendation for the user to
297      * try using the speakerphone instead, or if the device detects it has entered a poor service
298      * area, the user might be warned so that they can finish their call prior to it dropping.
299      * <p>
300      * A diagnostic message is considered persistent in nature.  When the user enters a poor service
301      * area, for example, the accompanying diagnostic message persists until they leave the area
302      * of poor service.  Each message is accompanied with a {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID}
303      * which uniquely identifies the diagnostic condition being reported.  The framework raises a
304      * call event of type {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE} when the condition reported has
305      * been cleared.  The dialer app should display the diagnostic message until it is cleared.
306      * If multiple diagnostic messages are sent with different IDs (which have not yet been cleared)
307      * the dialer app should prioritize the most recently received message, but still provide the
308      * user with a means to review past messages.
309      * <p>
310      * The text of the message is found in {@link #EXTRA_DIAGNOSTIC_MESSAGE} in the form of a human
311      * readable {@link CharSequence} which is intended for display in the call UX.
312      * <p>
313      * The telecom framework audibly notifies the user of the presence of a diagnostic message, so
314      * the dialer app needs only to concern itself with visually displaying the message.
315      * <p>
316      * The dialer app receives this event via
317      * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
318      */
319     public static final String EVENT_DISPLAY_DIAGNOSTIC_MESSAGE =
320             "android.telecom.event.DISPLAY_DIAGNOSTIC_MESSAGE";
321 
322     /**
323      * Event reported from the telecom framework when a diagnostic message previously raised with
324      * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE} has cleared and is no longer pertinent.
325      * <p>
326      * The {@link #EXTRA_DIAGNOSTIC_MESSAGE_ID} indicates the diagnostic message which has been
327      * cleared.
328      * <p>
329      * The dialer app receives this event via
330      * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
331      */
332     public static final String EVENT_CLEAR_DIAGNOSTIC_MESSAGE =
333             "android.telecom.event.CLEAR_DIAGNOSTIC_MESSAGE";
334 
335     /**
336      * Integer extra representing a message ID for a message posted via
337      * {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}.  Used to ensure that the dialer app knows when
338      * the message in question has cleared via {@link #EVENT_CLEAR_DIAGNOSTIC_MESSAGE}.
339      */
340     public static final String EXTRA_DIAGNOSTIC_MESSAGE_ID =
341             "android.telecom.extra.DIAGNOSTIC_MESSAGE_ID";
342 
343     /**
344      * {@link CharSequence} extra used with {@link #EVENT_DISPLAY_DIAGNOSTIC_MESSAGE}.  This is the
345      * diagnostic message the dialer app should display.
346      */
347     public static final String EXTRA_DIAGNOSTIC_MESSAGE =
348             "android.telecom.extra.DIAGNOSTIC_MESSAGE";
349 
350     /**
351      * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
352      * call because they have declined to answer it.  This typically means that they are unable
353      * to answer the call at this time and would prefer it be sent to voicemail.
354      */
355     public static final int REJECT_REASON_DECLINED = 1;
356 
357     /**
358      * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
359      * call because it is an unwanted call.  This allows the user to indicate that they are
360      * rejecting a call because it is likely a nuisance call.
361      */
362     public static final int REJECT_REASON_UNWANTED = 2;
363 
364     /**
365      * @hide
366      */
367     @IntDef(prefix = { "REJECT_REASON_" },
368             value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
369     @Retention(RetentionPolicy.SOURCE)
370     public @interface RejectReason {};
371 
372     public static class Details {
373         /** @hide */
374         @Retention(RetentionPolicy.SOURCE)
375         @IntDef(
376                 prefix = { "DIRECTION_" },
377                 value = {DIRECTION_UNKNOWN, DIRECTION_INCOMING, DIRECTION_OUTGOING})
378         public @interface CallDirection {}
379 
380         /**
381          * Indicates that the call is neither and incoming nor an outgoing call.  This can be the
382          * case for calls reported directly by a {@link ConnectionService} in special cases such as
383          * call handovers.
384          */
385         public static final int DIRECTION_UNKNOWN = -1;
386 
387         /**
388          * Indicates that the call is an incoming call.
389          */
390         public static final int DIRECTION_INCOMING = 0;
391 
392         /**
393          * Indicates that the call is an outgoing call.
394          */
395         public static final int DIRECTION_OUTGOING = 1;
396 
397         /** Call can currently be put on hold or unheld. */
398         public static final int CAPABILITY_HOLD = 0x00000001;
399 
400         /** Call supports the hold feature. */
401         public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;
402 
403         /**
404          * Calls within a conference can be merged. A {@link ConnectionService} has the option to
405          * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
406          * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
407          * capability allows a merge button to be shown while the conference call is in the foreground
408          * of the in-call UI.
409          * <p>
410          * This is only intended for use by a {@link Conference}.
411          */
412         public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;
413 
414         /**
415          * Calls within a conference can be swapped between foreground and background.
416          * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
417          * <p>
418          * This is only intended for use by a {@link Conference}.
419          */
420         public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;
421 
422         /**
423          * @hide
424          */
425         public static final int CAPABILITY_UNUSED_1 = 0x00000010;
426 
427         /** Call supports responding via text option. */
428         public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;
429 
430         /** Call can be muted. */
431         public static final int CAPABILITY_MUTE = 0x00000040;
432 
433         /**
434          * Call supports conference call management. This capability only applies to {@link Conference}
435          * calls which can have {@link Connection}s as children.
436          */
437         public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;
438 
439         /**
440          * Local device supports receiving video.
441          */
442         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;
443 
444         /**
445          * Local device supports transmitting video.
446          */
447         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;
448 
449         /**
450          * Local device supports bidirectional video calling.
451          */
452         public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
453                 CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;
454 
455         /**
456          * Remote device supports receiving video.
457          */
458         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;
459 
460         /**
461          * Remote device supports transmitting video.
462          */
463         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;
464 
465         /**
466          * Remote device supports bidirectional video calling.
467          */
468         public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
469                 CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;
470 
471         /**
472          * Call is able to be separated from its parent {@code Conference}, if any.
473          */
474         public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;
475 
476         /**
477          * Call is able to be individually disconnected when in a {@code Conference}.
478          */
479         public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;
480 
481         /**
482          * Speed up audio setup for MT call.
483          * @hide
484          */
485         public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;
486 
487         /**
488          * Call can be upgraded to a video call.
489          * @hide
490          * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
491          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
492          * whether or not video calling is supported.
493          */
494         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
495         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
496 
497         /**
498          * For video calls, indicates whether the outgoing video for the call can be paused using
499          * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
500          */
501         public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;
502 
503         /**
504          * Call sends responses through connection.
505          * @hide
506          */
507         public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;
508 
509         /**
510          * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
511          * <p>
512          * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
513          * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
514          * downgraded from a video call back to a VideoState of
515          * {@link VideoProfile#STATE_AUDIO_ONLY}.
516          * <p>
517          * Intuitively, a call which can be downgraded to audio should also have local and remote
518          * video
519          * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
520          * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
521          */
522         public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;
523 
524         /**
525          * When set for an external call, indicates that this {@code Call} can be pulled from a
526          * remote device to the current device.
527          * <p>
528          * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
529          * <p>
530          * An {@link InCallService} will only see calls with this capability if it has the
531          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
532          * in its manifest.
533          * <p>
534          * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
535          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
536          */
537         public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;
538 
539         /** Call supports the deflect feature. */
540         public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
541 
542         /**
543          * Call supports adding participants to the call via
544          * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
545          * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
546          */
547         public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
548 
549         /**
550          * When set for a call, indicates that this {@code Call} can be transferred to another
551          * number.
552          * Call supports the confirmed and unconfirmed call transfer feature.
553          *
554          * @hide
555          */
556         public static final int CAPABILITY_TRANSFER = 0x04000000;
557 
558         /**
559          * When set for a call, indicates that this {@code Call} can be transferred to another
560          * ongoing call.
561          * Call supports the consultative call transfer feature.
562          *
563          * @hide
564          */
565         public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
566 
567         /**
568          * Indicates whether the remote party supports RTT or not to the UI.
569          */
570 
571         public static final int CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT = 0x10000000;
572 
573         //******************************************************************************************
574         // Next CAPABILITY value: 0x20000000
575         //******************************************************************************************
576 
577         /**
578          * Whether the call is currently a conference.
579          */
580         public static final int PROPERTY_CONFERENCE = 0x00000001;
581 
582         /**
583          * Whether the call is a generic conference, where we do not know the precise state of
584          * participants in the conference (eg. on CDMA).
585          */
586         public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;
587 
588         /**
589          * Whether the call is made while the device is in emergency callback mode.
590          */
591         public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;
592 
593         /**
594          * Connection is using WIFI.
595          */
596         public static final int PROPERTY_WIFI = 0x00000008;
597 
598         /**
599          * When set, the UI should indicate to the user that a call is using high definition
600          * audio.
601          * <p>
602          * The underlying {@link ConnectionService} is responsible for reporting this
603          * property.  It is important to note that this property is not intended to report the
604          * actual audio codec being used for a Call, but whether the call should be indicated
605          * to the user as high definition.
606          * <p>
607          * The Android Telephony stack reports this property for calls based on a number
608          * of factors, including which audio codec is used and whether a call is using an HD
609          * codec end-to-end.  Some mobile operators choose to suppress display of an HD indication,
610          * and in these cases this property will not be set for a call even if the underlying audio
611          * codec is in fact "high definition".
612          */
613         public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;
614 
615         /**
616          * Whether the call is associated with the work profile.
617          */
618         public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;
619 
620         /**
621          * When set, indicates that this {@code Call} does not actually exist locally for the
622          * {@link ConnectionService}.
623          * <p>
624          * Consider, for example, a scenario where a user has two phones with the same phone number.
625          * When a user places a call on one device, the telephony stack can represent that call on
626          * the other device by adding it to the {@link ConnectionService} with the
627          * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
628          * <p>
629          * An {@link InCallService} will only see calls with this property if it has the
630          * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
631          * in its manifest.
632          * <p>
633          * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
634          */
635         public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;
636 
637         /**
638          * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
639          */
640         public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;
641 
642         /**
643          * Indicates that the call is from a self-managed {@link ConnectionService}.
644          * <p>
645          * See also {@link Connection#PROPERTY_SELF_MANAGED}
646          */
647         public static final int PROPERTY_SELF_MANAGED = 0x00000100;
648 
649         /**
650          * Indicates the call used Assisted Dialing.
651          *
652          * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
653          */
654         public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
655 
656         /**
657          * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
658          * {@link RttCall} object that is used to send and receive text.
659          */
660         public static final int PROPERTY_RTT = 0x00000400;
661 
662         /**
663          * Indicates that the call has been identified as the network as an emergency call. This
664          * property may be set for both incoming and outgoing calls which the network identifies as
665          * emergency calls.
666          */
667         public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
668 
669         /**
670          * Indicates that the call is using VoIP audio mode.
671          * <p>
672          * When this property is set, the {@link android.media.AudioManager} audio mode for this
673          * call will be {@link android.media.AudioManager#MODE_IN_COMMUNICATION}.  When this
674          * property is not set, the audio mode for this call will be
675          * {@link android.media.AudioManager#MODE_IN_CALL}.
676          * <p>
677          * This property reflects changes made using {@link Connection#setAudioModeIsVoip(boolean)}.
678          * <p>
679          * You can use this property to determine whether an un-answered incoming call or a held
680          * call will use VoIP audio mode (if the call does not currently have focus, the system
681          * audio mode may not reflect the mode the call will use).
682          */
683         public static final int PROPERTY_VOIP_AUDIO_MODE = 0x00001000;
684 
685         /**
686          * Indicates that the call is an adhoc conference call. This property can be set for both
687          * incoming and outgoing calls. An adhoc conference call is formed using
688          * {@link #addConferenceParticipants(List)},
689          * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
690          * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
691          * call using {@link #conference(Call)}.
692          */
693         public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
694 
695         /**
696          * Connection is using cross sim technology.
697          * <p>
698          * Indicates that the {@link Connection} is using a cross sim technology which would
699          * register IMS over internet APN of default data subscription.
700          * <p>
701          */
702         public static final int PROPERTY_CROSS_SIM = 0x00004000;
703 
704         //******************************************************************************************
705         // Next PROPERTY value: 0x00004000
706         //******************************************************************************************
707 
708         private final @CallState int mState;
709         private final String mTelecomCallId;
710         private final Uri mHandle;
711         private final int mHandlePresentation;
712         private final String mCallerDisplayName;
713         private final int mCallerDisplayNamePresentation;
714         private final PhoneAccountHandle mAccountHandle;
715         private final int mCallCapabilities;
716         private final int mCallProperties;
717         private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
718         private final DisconnectCause mDisconnectCause;
719         private final long mConnectTimeMillis;
720         private final GatewayInfo mGatewayInfo;
721         private final int mVideoState;
722         private final StatusHints mStatusHints;
723         private final Bundle mExtras;
724         private final Bundle mIntentExtras;
725         private final long mCreationTimeMillis;
726         private final String mContactDisplayName;
727         private final @CallDirection int mCallDirection;
728         private final @Connection.VerificationStatus int mCallerNumberVerificationStatus;
729 
730         /**
731          * Whether the supplied capabilities  supports the specified capability.
732          *
733          * @param capabilities A bit field of capabilities.
734          * @param capability The capability to check capabilities for.
735          * @return Whether the specified capability is supported.
736          */
can(int capabilities, int capability)737         public static boolean can(int capabilities, int capability) {
738             return (capabilities & capability) == capability;
739         }
740 
741         /**
742          * Whether the capabilities of this {@code Details} supports the specified capability.
743          *
744          * @param capability The capability to check capabilities for.
745          * @return Whether the specified capability is supported.
746          */
can(int capability)747         public boolean can(int capability) {
748             return can(mCallCapabilities, capability);
749         }
750 
751         /**
752          * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
753          *
754          * @param capabilities A capability bit field.
755          * @return A human readable string representation.
756          */
capabilitiesToString(int capabilities)757         public static String capabilitiesToString(int capabilities) {
758             StringBuilder builder = new StringBuilder();
759             builder.append("[Capabilities:");
760             if (can(capabilities, CAPABILITY_HOLD)) {
761                 builder.append(" CAPABILITY_HOLD");
762             }
763             if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
764                 builder.append(" CAPABILITY_SUPPORT_HOLD");
765             }
766             if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
767                 builder.append(" CAPABILITY_MERGE_CONFERENCE");
768             }
769             if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
770                 builder.append(" CAPABILITY_SWAP_CONFERENCE");
771             }
772             if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
773                 builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
774             }
775             if (can(capabilities, CAPABILITY_MUTE)) {
776                 builder.append(" CAPABILITY_MUTE");
777             }
778             if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
779                 builder.append(" CAPABILITY_MANAGE_CONFERENCE");
780             }
781             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
782                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
783             }
784             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
785                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
786             }
787             if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
788                 builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
789             }
790             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
791                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
792             }
793             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
794                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
795             }
796             if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
797                 builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
798             }
799             if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
800                 builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
801             }
802             if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
803                 builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
804             }
805             if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
806                 builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
807             }
808             if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
809                 builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
810             }
811             if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
812                 builder.append(" CAPABILITY_CAN_PULL_CALL");
813             }
814             if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
815                 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
816             }
817             if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
818                 builder.append(" CAPABILITY_ADD_PARTICIPANT");
819             }
820             if (can(capabilities, CAPABILITY_TRANSFER)) {
821                 builder.append(" CAPABILITY_TRANSFER");
822             }
823             if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
824                 builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
825             }
826             if (can(capabilities, CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT)) {
827                 builder.append(" CAPABILITY_REMOTE_PARTY_SUPPORTS_RTT");
828             }
829             builder.append("]");
830             return builder.toString();
831         }
832 
833         /**
834          * Whether the supplied properties includes the specified property.
835          *
836          * @param properties A bit field of properties.
837          * @param property The property to check properties for.
838          * @return Whether the specified property is supported.
839          */
hasProperty(int properties, int property)840         public static boolean hasProperty(int properties, int property) {
841             return (properties & property) == property;
842         }
843 
844         /**
845          * Whether the properties of this {@code Details} includes the specified property.
846          *
847          * @param property The property to check properties for.
848          * @return Whether the specified property is supported.
849          */
hasProperty(int property)850         public boolean hasProperty(int property) {
851             return hasProperty(mCallProperties, property);
852         }
853 
854         /**
855          * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
856          *
857          * @param properties A property bit field.
858          * @return A human readable string representation.
859          */
propertiesToString(int properties)860         public static String propertiesToString(int properties) {
861             StringBuilder builder = new StringBuilder();
862             builder.append("[Properties:");
863             if (hasProperty(properties, PROPERTY_CONFERENCE)) {
864                 builder.append(" PROPERTY_CONFERENCE");
865             }
866             if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
867                 builder.append(" PROPERTY_GENERIC_CONFERENCE");
868             }
869             if (hasProperty(properties, PROPERTY_WIFI)) {
870                 builder.append(" PROPERTY_WIFI");
871             }
872             if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
873                 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
874             }
875             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
876                 builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
877             }
878             if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
879                 builder.append(" PROPERTY_IS_EXTERNAL_CALL");
880             }
881             if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
882                 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
883             }
884             if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
885                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
886             }
887             if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
888                 builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
889             }
890             if (hasProperty(properties, PROPERTY_RTT)) {
891                 builder.append(" PROPERTY_RTT");
892             }
893             if (hasProperty(properties, PROPERTY_VOIP_AUDIO_MODE)) {
894                 builder.append(" PROPERTY_VOIP_AUDIO_MODE");
895             }
896             if (hasProperty(properties, PROPERTY_IS_ADHOC_CONFERENCE)) {
897                 builder.append(" PROPERTY_IS_ADHOC_CONFERENCE");
898             }
899             if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
900                 builder.append(" PROPERTY_CROSS_SIM");
901             }
902             builder.append("]");
903             return builder.toString();
904         }
905 
906         /**
907          * @return the state of the {@link Call} represented by this {@link Call.Details}.
908          */
getState()909         public final @CallState int getState() {
910             return mState;
911         }
912 
913         /** {@hide} */
914         @TestApi
getTelecomCallId()915         public String getTelecomCallId() {
916             return mTelecomCallId;
917         }
918 
919         /**
920          * @return The handle (e.g., phone number) to which the {@code Call} is currently
921          * connected.
922          */
getHandle()923         public Uri getHandle() {
924             return mHandle;
925         }
926 
927         /**
928          * @return The presentation requirements for the handle. See
929          * {@link TelecomManager} for valid values.
930          */
getHandlePresentation()931         public int getHandlePresentation() {
932             return mHandlePresentation;
933         }
934 
935         /**
936          * The display name for the caller.
937          * <p>
938          * This is the name as reported by the {@link ConnectionService} associated with this call.
939          *
940          * @return The display name for the caller.
941          */
getCallerDisplayName()942         public String getCallerDisplayName() {
943             return mCallerDisplayName;
944         }
945 
946         /**
947          * @return The presentation requirements for the caller display name. See
948          * {@link TelecomManager} for valid values.
949          */
getCallerDisplayNamePresentation()950         public int getCallerDisplayNamePresentation() {
951             return mCallerDisplayNamePresentation;
952         }
953 
954         /**
955          * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
956          * routed.
957          */
getAccountHandle()958         public PhoneAccountHandle getAccountHandle() {
959             return mAccountHandle;
960         }
961 
962         /**
963          * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
964          *         {@code CAPABILITY_*} constants in this class.
965          */
getCallCapabilities()966         public int getCallCapabilities() {
967             return mCallCapabilities;
968         }
969 
970         /**
971          * @return A bitmask of the properties of the {@code Call}, as defined by the various
972          *         {@code PROPERTY_*} constants in this class.
973          */
getCallProperties()974         public int getCallProperties() {
975             return mCallProperties;
976         }
977 
978         /**
979          * @return a bitmask of the audio routes available for the call.
980          *
981          * @hide
982          */
getSupportedAudioRoutes()983         public int getSupportedAudioRoutes() {
984             return mSupportedAudioRoutes;
985         }
986 
987         /**
988          * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
989          * by {@link android.telecom.DisconnectCause}.
990          */
getDisconnectCause()991         public DisconnectCause getDisconnectCause() {
992             return mDisconnectCause;
993         }
994 
995         /**
996          * Returns the time the {@link Call} connected (i.e. became active).  This information is
997          * updated periodically, but user interfaces should not rely on this to display the "call
998          * time clock".  For the time when the call was first added to Telecom, see
999          * {@link #getCreationTimeMillis()}.
1000          *
1001          * @return The time the {@link Call} connected in milliseconds since the epoch.
1002          */
getConnectTimeMillis()1003         public final long getConnectTimeMillis() {
1004             return mConnectTimeMillis;
1005         }
1006 
1007         /**
1008          * @return Information about any calling gateway the {@code Call} may be using.
1009          */
getGatewayInfo()1010         public GatewayInfo getGatewayInfo() {
1011             return mGatewayInfo;
1012         }
1013 
1014         /**
1015          * @return The video state of the {@code Call}.
1016          */
getVideoState()1017         public int getVideoState() {
1018             return mVideoState;
1019         }
1020 
1021         /**
1022          * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
1023          * have been set.
1024          */
getStatusHints()1025         public StatusHints getStatusHints() {
1026             return mStatusHints;
1027         }
1028 
1029         /**
1030          * @return The extras associated with this call.
1031          */
getExtras()1032         public Bundle getExtras() {
1033             return mExtras;
1034         }
1035 
1036         /**
1037          * @return The extras used with the original intent to place this call.
1038          */
getIntentExtras()1039         public Bundle getIntentExtras() {
1040             return mIntentExtras;
1041         }
1042 
1043         /**
1044          * Returns the time when the call was first created and added to Telecom.  This is the same
1045          * time that is logged as the start time in the Call Log (see
1046          * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
1047          * (became active), see {@link #getConnectTimeMillis()}.
1048          *
1049          * @return The creation time of the call, in millis since the epoch.
1050          */
getCreationTimeMillis()1051         public long getCreationTimeMillis() {
1052             return mCreationTimeMillis;
1053         }
1054 
1055         /**
1056          * Returns the name of the caller on the remote end, as derived from a
1057          * {@link android.provider.ContactsContract} lookup of the call's handle.
1058          * @return The name of the caller, or {@code null} if the lookup is not yet complete, if
1059          *         there's no contacts entry for the caller, or if the {@link InCallService} does
1060          *         not hold the {@link android.Manifest.permission#READ_CONTACTS} permission.
1061          */
getContactDisplayName()1062         public @Nullable String getContactDisplayName() {
1063             return mContactDisplayName;
1064         }
1065 
1066         /**
1067          * Indicates whether the call is an incoming or outgoing call.
1068          * @return The call's direction.
1069          */
getCallDirection()1070         public @CallDirection int getCallDirection() {
1071             return mCallDirection;
1072         }
1073 
1074         /**
1075          * Gets the verification status for the phone number of an incoming call as identified in
1076          * ATIS-1000082.
1077          * <p>
1078          * For incoming calls, the number verification status indicates whether the device was
1079          * able to verify the authenticity of the calling number using the STIR process outlined
1080          * in ATIS-1000082.  {@link Connection#VERIFICATION_STATUS_NOT_VERIFIED} indicates that
1081          * the network was not able to use STIR to verify the caller's number (i.e. nothing is
1082          * known regarding the authenticity of the number.
1083          * {@link Connection#VERIFICATION_STATUS_PASSED} indicates that the network was able to
1084          * use STIR to verify the caller's number.  This indicates that the network has a high
1085          * degree of confidence that the incoming call actually originated from the indicated
1086          * number.  {@link Connection#VERIFICATION_STATUS_FAILED} indicates that the network's
1087          * STIR verification did not pass.  This indicates that the incoming call may not
1088          * actually be from the indicated number.  This could occur if, for example, the caller
1089          * is using an impersonated phone number.
1090          * <p>
1091          * A {@link CallScreeningService} can use this information to help determine if an
1092          * incoming call is potentially an unwanted call.  A verification status of
1093          * {@link Connection#VERIFICATION_STATUS_FAILED} indicates that an incoming call may not
1094          * actually be from the number indicated on the call (i.e. impersonated number) and that it
1095          * should potentially be blocked.  Likewise,
1096          * {@link Connection#VERIFICATION_STATUS_PASSED} can be used as a positive signal to
1097          * help clarify that the incoming call is originating from the indicated number and it
1098          * is less likely to be an undesirable call.
1099          * <p>
1100          * An {@link InCallService} can use this information to provide a visual indicator to the
1101          * user regarding the verification status of a call and to help identify calls from
1102          * potentially impersonated numbers.
1103          * @return the verification status.
1104          */
getCallerNumberVerificationStatus()1105         public @Connection.VerificationStatus int getCallerNumberVerificationStatus() {
1106             return mCallerNumberVerificationStatus;
1107         }
1108 
1109         @Override
equals(Object o)1110         public boolean equals(Object o) {
1111             if (o instanceof Details) {
1112                 Details d = (Details) o;
1113                 return
1114                         Objects.equals(mState, d.mState) &&
1115                         Objects.equals(mHandle, d.mHandle) &&
1116                         Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
1117                         Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
1118                         Objects.equals(mCallerDisplayNamePresentation,
1119                                 d.mCallerDisplayNamePresentation) &&
1120                         Objects.equals(mAccountHandle, d.mAccountHandle) &&
1121                         Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
1122                         Objects.equals(mCallProperties, d.mCallProperties) &&
1123                         Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
1124                         Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
1125                         Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
1126                         Objects.equals(mVideoState, d.mVideoState) &&
1127                         Objects.equals(mStatusHints, d.mStatusHints) &&
1128                         areBundlesEqual(mExtras, d.mExtras) &&
1129                         areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
1130                         Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis) &&
1131                         Objects.equals(mContactDisplayName, d.mContactDisplayName) &&
1132                         Objects.equals(mCallDirection, d.mCallDirection) &&
1133                         Objects.equals(mCallerNumberVerificationStatus,
1134                                 d.mCallerNumberVerificationStatus);
1135             }
1136             return false;
1137         }
1138 
1139         @Override
hashCode()1140         public int hashCode() {
1141             return Objects.hash(mState,
1142                             mHandle,
1143                             mHandlePresentation,
1144                             mCallerDisplayName,
1145                             mCallerDisplayNamePresentation,
1146                             mAccountHandle,
1147                             mCallCapabilities,
1148                             mCallProperties,
1149                             mDisconnectCause,
1150                             mConnectTimeMillis,
1151                             mGatewayInfo,
1152                             mVideoState,
1153                             mStatusHints,
1154                             mExtras,
1155                             mIntentExtras,
1156                             mCreationTimeMillis,
1157                             mContactDisplayName,
1158                             mCallDirection,
1159                             mCallerNumberVerificationStatus);
1160         }
1161 
1162         /** {@hide} */
Details( @allState int state, String telecomCallId, Uri handle, int handlePresentation, String callerDisplayName, int callerDisplayNamePresentation, PhoneAccountHandle accountHandle, int capabilities, int properties, DisconnectCause disconnectCause, long connectTimeMillis, GatewayInfo gatewayInfo, int videoState, StatusHints statusHints, Bundle extras, Bundle intentExtras, long creationTimeMillis, String contactDisplayName, int callDirection, int callerNumberVerificationStatus)1163         public Details(
1164                 @CallState int state,
1165                 String telecomCallId,
1166                 Uri handle,
1167                 int handlePresentation,
1168                 String callerDisplayName,
1169                 int callerDisplayNamePresentation,
1170                 PhoneAccountHandle accountHandle,
1171                 int capabilities,
1172                 int properties,
1173                 DisconnectCause disconnectCause,
1174                 long connectTimeMillis,
1175                 GatewayInfo gatewayInfo,
1176                 int videoState,
1177                 StatusHints statusHints,
1178                 Bundle extras,
1179                 Bundle intentExtras,
1180                 long creationTimeMillis,
1181                 String contactDisplayName,
1182                 int callDirection,
1183                 int callerNumberVerificationStatus) {
1184             mState = state;
1185             mTelecomCallId = telecomCallId;
1186             mHandle = handle;
1187             mHandlePresentation = handlePresentation;
1188             mCallerDisplayName = callerDisplayName;
1189             mCallerDisplayNamePresentation = callerDisplayNamePresentation;
1190             mAccountHandle = accountHandle;
1191             mCallCapabilities = capabilities;
1192             mCallProperties = properties;
1193             mDisconnectCause = disconnectCause;
1194             mConnectTimeMillis = connectTimeMillis;
1195             mGatewayInfo = gatewayInfo;
1196             mVideoState = videoState;
1197             mStatusHints = statusHints;
1198             mExtras = extras;
1199             mIntentExtras = intentExtras;
1200             mCreationTimeMillis = creationTimeMillis;
1201             mContactDisplayName = contactDisplayName;
1202             mCallDirection = callDirection;
1203             mCallerNumberVerificationStatus = callerNumberVerificationStatus;
1204         }
1205 
1206         /** {@hide} */
createFromParcelableCall(ParcelableCall parcelableCall)1207         public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
1208             return new Details(
1209                     parcelableCall.getState(),
1210                     parcelableCall.getId(),
1211                     parcelableCall.getHandle(),
1212                     parcelableCall.getHandlePresentation(),
1213                     parcelableCall.getCallerDisplayName(),
1214                     parcelableCall.getCallerDisplayNamePresentation(),
1215                     parcelableCall.getAccountHandle(),
1216                     parcelableCall.getCapabilities(),
1217                     parcelableCall.getProperties(),
1218                     parcelableCall.getDisconnectCause(),
1219                     parcelableCall.getConnectTimeMillis(),
1220                     parcelableCall.getGatewayInfo(),
1221                     parcelableCall.getVideoState(),
1222                     parcelableCall.getStatusHints(),
1223                     parcelableCall.getExtras(),
1224                     parcelableCall.getIntentExtras(),
1225                     parcelableCall.getCreationTimeMillis(),
1226                     parcelableCall.getContactDisplayName(),
1227                     parcelableCall.getCallDirection(),
1228                     parcelableCall.getCallerNumberVerificationStatus());
1229         }
1230 
1231         @Override
toString()1232         public String toString() {
1233             StringBuilder sb = new StringBuilder();
1234             sb.append("[id: ");
1235             sb.append(mTelecomCallId);
1236             sb.append(", state: ");
1237             sb.append(Call.stateToString(mState));
1238             sb.append(", pa: ");
1239             sb.append(mAccountHandle);
1240             sb.append(", hdl: ");
1241             sb.append(Log.piiHandle(mHandle));
1242             sb.append(", hdlPres: ");
1243             sb.append(mHandlePresentation);
1244             sb.append(", videoState: ");
1245             sb.append(VideoProfile.videoStateToString(mVideoState));
1246             sb.append(", caps: ");
1247             sb.append(capabilitiesToString(mCallCapabilities));
1248             sb.append(", props: ");
1249             sb.append(propertiesToString(mCallProperties));
1250             sb.append("]");
1251             return sb.toString();
1252         }
1253     }
1254 
1255     /**
1256      * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
1257      * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
1258      * implementation.
1259      * <p>
1260      * You can handle these callbacks by extending the {@link Callback} class and overriding the
1261      * callbacks that your {@link InCallService} is interested in.  The callback methods include the
1262      * {@link Call} for which the callback applies, allowing reuse of a single instance of your
1263      * {@link Callback} implementation, if desired.
1264      * <p>
1265      * Use {@link Call#registerCallback(Callback)} to register your callback(s).  Ensure
1266      * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
1267      * (typically in {@link InCallService#onCallRemoved(Call)}).
1268      * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
1269      * reach your implementation of {@link Callback}, so it is important to register your callback
1270      * as soon as your {@link InCallService} is notified of a new call via
1271      * {@link InCallService#onCallAdded(Call)}.
1272      */
1273     public static abstract class Callback {
1274         /**
1275          * @hide
1276          */
1277         @IntDef(prefix = { "HANDOVER_" },
1278                 value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
1279                 HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
1280                 HANDOVER_FAILURE_UNKNOWN})
1281         @Retention(RetentionPolicy.SOURCE)
1282         public @interface HandoverFailureErrors {}
1283 
1284         /**
1285          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
1286          * to handover the call to rejects the handover request.
1287          * <p>
1288          * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
1289          * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
1290          * {@code null} {@link Connection} from
1291          * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
1292          * ConnectionRequest)}.
1293          * <p>
1294          * For more information on call handovers, see
1295          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1296          */
1297         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
1298 
1299         /**
1300          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1301          * is initiated but the source or destination app does not support handover.
1302          * <p>
1303          * Will be returned when a handover is requested via
1304          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
1305          * {@link PhoneAccountHandle} does not declare
1306          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
1307          * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
1308          * {@link Details#getAccountHandle()}) does not declare
1309          * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
1310          * <p>
1311          * For more information on call handovers, see
1312          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1313          */
1314         public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
1315 
1316         /**
1317          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
1318          * user rejects the handover request.
1319          * <p>
1320          * For more information on call handovers, see
1321          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1322          */
1323         public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
1324 
1325         /**
1326          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
1327          * is ongoing emergency call.
1328          * <p>
1329          * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
1330          * called on an emergency call, or if any other call is an emergency call.
1331          * <p>
1332          * Handovers are not permitted while there are ongoing emergency calls.
1333          * <p>
1334          * For more information on call handovers, see
1335          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1336          */
1337         public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
1338 
1339         /**
1340          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
1341          * fails for an unknown reason.
1342          * <p>
1343          * For more information on call handovers, see
1344          * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
1345          */
1346         public static final int HANDOVER_FAILURE_UNKNOWN = 5;
1347 
1348         /**
1349          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
1350          *
1351          * @param call The {@code Call} invoking this method.
1352          * @param state The new state of the {@code Call}.
1353          */
onStateChanged(Call call, @CallState int state)1354         public void onStateChanged(Call call, @CallState int state) {}
1355 
1356         /**
1357          * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
1358          *
1359          * @param call The {@code Call} invoking this method.
1360          * @param parent The new parent of the {@code Call}.
1361          */
onParentChanged(Call call, Call parent)1362         public void onParentChanged(Call call, Call parent) {}
1363 
1364         /**
1365          * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
1366          *
1367          * @param call The {@code Call} invoking this method.
1368          * @param children The new children of the {@code Call}.
1369          */
onChildrenChanged(Call call, List<Call> children)1370         public void onChildrenChanged(Call call, List<Call> children) {}
1371 
1372         /**
1373          * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
1374          *
1375          * @param call The {@code Call} invoking this method.
1376          * @param details A {@code Details} object describing the {@code Call}.
1377          */
onDetailsChanged(Call call, Details details)1378         public void onDetailsChanged(Call call, Details details) {}
1379 
1380         /**
1381          * Invoked when the text messages that can be used as responses to the incoming
1382          * {@code Call} are loaded from the relevant database.
1383          * See {@link #getCannedTextResponses()}.
1384          *
1385          * @param call The {@code Call} invoking this method.
1386          * @param cannedTextResponses The text messages useable as responses.
1387          */
onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses)1388         public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
1389 
1390         /**
1391          * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
1392          * character. This causes the post-dial signals to stop pending user confirmation. An
1393          * implementation should present this choice to the user and invoke
1394          * {@link #postDialContinue(boolean)} when the user makes the choice.
1395          *
1396          * @param call The {@code Call} invoking this method.
1397          * @param remainingPostDialSequence The post-dial characters that remain to be sent.
1398          */
onPostDialWait(Call call, String remainingPostDialSequence)1399         public void onPostDialWait(Call call, String remainingPostDialSequence) {}
1400 
1401         /**
1402          * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
1403          *
1404          * @param call The {@code Call} invoking this method.
1405          * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
1406          */
onVideoCallChanged(Call call, InCallService.VideoCall videoCall)1407         public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}
1408 
1409         /**
1410          * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
1411          * up their UI for the {@code Call} in response to state transitions. Specifically,
1412          * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
1413          * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
1414          * clients should wait for this method to be invoked.
1415          *
1416          * @param call The {@code Call} being destroyed.
1417          */
onCallDestroyed(Call call)1418         public void onCallDestroyed(Call call) {}
1419 
1420         /**
1421          * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
1422          * conferenced.
1423          *
1424          * @param call The {@code Call} being updated.
1425          * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
1426          *          conferenced.
1427          */
onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls)1428         public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}
1429 
1430         /**
1431          * Invoked when a {@link Call} receives an event from its associated {@link Connection} or
1432          * {@link Conference}.
1433          * <p>
1434          * Where possible, the Call should make an attempt to handle {@link Connection} events which
1435          * are part of the {@code android.telecom.*} namespace.  The Call should ignore any events
1436          * it does not wish to handle.  Unexpected events should be handled gracefully, as it is
1437          * possible that a {@link ConnectionService} has defined its own Connection events which a
1438          * Call is not aware of.
1439          * <p>
1440          * See {@link Connection#sendConnectionEvent(String, Bundle)},
1441          * {@link Conference#sendConferenceEvent(String, Bundle)}.
1442          *
1443          * @param call The {@code Call} receiving the event.
1444          * @param event The event.
1445          * @param extras Extras associated with the connection event.
1446          */
onConnectionEvent(Call call, String event, Bundle extras)1447         public void onConnectionEvent(Call call, String event, Bundle extras) {}
1448 
1449         /**
1450          * Invoked when the RTT mode changes for this call.
1451          * @param call The call whose RTT mode has changed.
1452          * @param mode the new RTT mode, one of
1453          * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
1454          *             or {@link RttCall#RTT_MODE_VCO}
1455          */
onRttModeChanged(Call call, int mode)1456         public void onRttModeChanged(Call call, int mode) {}
1457 
1458         /**
1459          * Invoked when the call's RTT status changes, either from off to on or from on to off.
1460          * @param call The call whose RTT status has changed.
1461          * @param enabled whether RTT is now enabled or disabled
1462          * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
1463          *                on, null otherwise.
1464          */
onRttStatusChanged(Call call, boolean enabled, RttCall rttCall)1465         public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}
1466 
1467         /**
1468          * Invoked when the remote end of the connection has requested that an RTT communication
1469          * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
1470          * with the same ID that this method is invoked with.
1471          * @param call The call which the RTT request was placed on
1472          * @param id The ID of the request.
1473          */
onRttRequest(Call call, int id)1474         public void onRttRequest(Call call, int id) {}
1475 
1476         /**
1477          * Invoked when the RTT session failed to initiate for some reason, including rejection
1478          * by the remote party.
1479          * <p>
1480          * This callback will ONLY be invoked to report a failure related to a user initiated
1481          * session modification request (i.e. {@link Call#sendRttRequest()}).
1482          * <p>
1483          * If a call is initiated with {@link TelecomManager#EXTRA_START_CALL_WITH_RTT} specified,
1484          * the availability of RTT can be determined by checking {@link Details#PROPERTY_RTT}
1485          * once the call enters state {@link Details#STATE_ACTIVE}.
1486          *
1487          * @param call The call which the RTT initiation failure occurred on.
1488          * @param reason One of the status codes defined in
1489          *      {@link android.telecom.Connection.RttModifyStatus}, with the exception of
1490          *      {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
1491          */
onRttInitiationFailure(Call call, @android.telecom.Connection.RttModifyStatus.RttSessionModifyStatus int reason)1492         public void onRttInitiationFailure(Call call,
1493                 @android.telecom.Connection.RttModifyStatus.RttSessionModifyStatus int reason) {}
1494 
1495         /**
1496          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1497          * has completed successfully.
1498          * <p>
1499          * For a full discussion of the handover process and the APIs involved, see
1500          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1501          *
1502          * @param call The call which had initiated handover.
1503          */
onHandoverComplete(Call call)1504         public void onHandoverComplete(Call call) {}
1505 
1506         /**
1507          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
1508          * has failed.
1509          * <p>
1510          * For a full discussion of the handover process and the APIs involved, see
1511          * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
1512          *
1513          * @param call The call which had initiated handover.
1514          * @param failureReason Error reason for failure.
1515          */
onHandoverFailed(Call call, @HandoverFailureErrors int failureReason)1516         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
1517     }
1518 
1519     /**
1520      * A class that holds the state that describes the state of the RTT channel to the remote
1521      * party, if it is active.
1522      */
1523     public static final class RttCall {
1524         /** @hide */
1525         @Retention(RetentionPolicy.SOURCE)
1526         @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
1527         public @interface RttAudioMode {}
1528 
1529         /**
1530          * For metrics use. Default value in the proto.
1531          * @hide
1532          */
1533         public static final int RTT_MODE_INVALID = 0;
1534 
1535         /**
1536          * Indicates that there should be a bidirectional audio stream between the two parties
1537          * on the call.
1538          */
1539         public static final int RTT_MODE_FULL = 1;
1540 
1541         /**
1542          * Indicates that the local user should be able to hear the audio stream from the remote
1543          * user, but not vice versa. Equivalent to muting the microphone.
1544          */
1545         public static final int RTT_MODE_HCO = 2;
1546 
1547         /**
1548          * Indicates that the remote user should be able to hear the audio stream from the local
1549          * user, but not vice versa. Equivalent to setting the volume to zero.
1550          */
1551         public static final int RTT_MODE_VCO = 3;
1552 
1553         private static final int READ_BUFFER_SIZE = 1000;
1554 
1555         private InputStreamReader mReceiveStream;
1556         private OutputStreamWriter mTransmitStream;
1557         private int mRttMode;
1558         private final InCallAdapter mInCallAdapter;
1559         private final String mTelecomCallId;
1560         private char[] mReadBuffer = new char[READ_BUFFER_SIZE];
1561 
1562         /**
1563          * @hide
1564          */
RttCall(String telecomCallId, InputStreamReader receiveStream, OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter)1565         public RttCall(String telecomCallId, InputStreamReader receiveStream,
1566                 OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
1567             mTelecomCallId = telecomCallId;
1568             mReceiveStream = receiveStream;
1569             mTransmitStream = transmitStream;
1570             mRttMode = mode;
1571             mInCallAdapter = inCallAdapter;
1572         }
1573 
1574         /**
1575          * Returns the current RTT audio mode.
1576          * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
1577          * {@link #RTT_MODE_HCO}.
1578          */
getRttAudioMode()1579         public int getRttAudioMode() {
1580             return mRttMode;
1581         }
1582 
1583         /**
1584          * Sets the RTT audio mode. The requested mode change will be communicated through
1585          * {@link Callback#onRttModeChanged(Call, int)}.
1586          * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
1587          * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
1588          */
setRttMode(@ttAudioMode int mode)1589         public void setRttMode(@RttAudioMode int mode) {
1590             mInCallAdapter.setRttMode(mTelecomCallId, mode);
1591         }
1592 
1593         /**
1594          * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
1595          * RTT transmits text in real-time, this method should be called once for each user action.
1596          * For example, when the user enters text as discrete characters using the keyboard, this
1597          * method should be called once for each character. However, if the user enters text by
1598          * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
1599          * be sent in one call to this method.
1600          *
1601          * This method is not thread-safe -- calling it from multiple threads simultaneously may
1602          * lead to interleaved text.
1603          * @param input The message to send to the remote user.
1604          */
write(String input)1605         public void write(String input) throws IOException {
1606             mTransmitStream.write(input);
1607             mTransmitStream.flush();
1608         }
1609 
1610         /**
1611          * Reads a string from the remote user, blocking if there is no data available. Returns
1612          * {@code null} if the RTT conversation has been terminated and there is no further data
1613          * to read.
1614          *
1615          * This method is not thread-safe -- calling it from multiple threads simultaneously may
1616          * lead to interleaved text.
1617          * @return A string containing text sent by the remote user, or {@code null} if the
1618          * conversation has been terminated or if there was an error while reading.
1619          */
read()1620         public String read() {
1621             try {
1622                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1623                 if (numRead < 0) {
1624                     return null;
1625                 }
1626                 return new String(mReadBuffer, 0, numRead);
1627             } catch (IOException e) {
1628                 Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
1629                 return null;
1630             }
1631         }
1632 
1633         /**
1634          * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
1635          * be read.
1636          * @return A string containing text entered by the user, or {@code null} if the user has
1637          * not entered any new text yet.
1638          */
readImmediately()1639         public String readImmediately() throws IOException {
1640             if (mReceiveStream.ready()) {
1641                 int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
1642                 if (numRead < 0) {
1643                     return null;
1644                 }
1645                 return new String(mReadBuffer, 0, numRead);
1646             } else {
1647                 return null;
1648             }
1649         }
1650 
1651         /**
1652          * Closes the underlying file descriptors
1653          * @hide
1654          */
close()1655         public void close() {
1656             try {
1657                 mReceiveStream.close();
1658             } catch (IOException e) {
1659                 // ignore
1660             }
1661             try {
1662                 mTransmitStream.close();
1663             } catch (IOException e) {
1664                 // ignore
1665             }
1666         }
1667     }
1668 
1669     /**
1670      * @deprecated Use {@code Call.Callback} instead.
1671      * @hide
1672      */
1673     @Deprecated
1674     @SystemApi
1675     public static abstract class Listener extends Callback { }
1676 
1677     private final Phone mPhone;
1678     private final String mTelecomCallId;
1679     private final InCallAdapter mInCallAdapter;
1680     private final List<String> mChildrenIds = new ArrayList<>();
1681     private final List<Call> mChildren = new ArrayList<>();
1682     private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
1683     private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
1684     private final List<Call> mConferenceableCalls = new ArrayList<>();
1685     private final List<Call> mUnmodifiableConferenceableCalls =
1686             Collections.unmodifiableList(mConferenceableCalls);
1687 
1688     private boolean mChildrenCached;
1689     private String mParentId = null;
1690     private String mActiveGenericConferenceChild = null;
1691     private int mState;
1692     private List<String> mCannedTextResponses = null;
1693     private String mCallingPackage;
1694     private int mTargetSdkVersion;
1695     private String mRemainingPostDialSequence;
1696     private VideoCallImpl mVideoCallImpl;
1697     private RttCall mRttCall;
1698     private Details mDetails;
1699     private Bundle mExtras;
1700 
1701     /**
1702      * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
1703      *
1704      * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
1705      * remaining or this {@code Call} is not in a post-dial state.
1706      */
getRemainingPostDialSequence()1707     public String getRemainingPostDialSequence() {
1708         return mRemainingPostDialSequence;
1709     }
1710 
1711     /**
1712      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
1713      * @param videoState The video state in which to answer the call.
1714      */
answer(@ideoProfile.VideoState int videoState)1715     public void answer(@VideoProfile.VideoState int videoState) {
1716         mInCallAdapter.answerCall(mTelecomCallId, videoState);
1717     }
1718 
1719     /**
1720      * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
1721      *
1722      * @param address The address to which the call will be deflected.
1723      */
deflect(Uri address)1724     public void deflect(Uri address) {
1725         mInCallAdapter.deflectCall(mTelecomCallId, address);
1726     }
1727 
1728     /**
1729      * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
1730      *
1731      * @param rejectWithMessage Whether to reject with a text message.
1732      * @param textMessage An optional text message with which to respond.
1733      */
reject(boolean rejectWithMessage, String textMessage)1734     public void reject(boolean rejectWithMessage, String textMessage) {
1735         mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
1736     }
1737 
1738     /**
1739      * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
1740      * user has chosen to reject the call and has indicated a reason why the call is being rejected.
1741      *
1742      * @param rejectReason the reason the call is being rejected.
1743      */
reject(@ejectReason int rejectReason)1744     public void reject(@RejectReason int rejectReason) {
1745         mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
1746     }
1747 
1748     /**
1749      * Instructs this {@code Call} to be transferred to another number.
1750      *
1751      * @param targetNumber The address to which the call will be transferred.
1752      * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
1753      * if {@code false}, it will initiate an unconfirmed transfer.
1754      *
1755      * @hide
1756      */
transfer(@onNull Uri targetNumber, boolean isConfirmationRequired)1757     public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
1758         mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
1759     }
1760 
1761     /**
1762      * Instructs this {@code Call} to be transferred to another ongoing call.
1763      * This will initiate CONSULTATIVE transfer.
1764      * @param toCall The other ongoing {@code Call} to which this call will be transferred.
1765      *
1766      * @hide
1767      */
transfer(@onNull android.telecom.Call toCall)1768     public void transfer(@NonNull android.telecom.Call toCall) {
1769         mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
1770     }
1771 
1772     /**
1773      * Instructs this {@code Call} to disconnect.
1774      */
disconnect()1775     public void disconnect() {
1776         mInCallAdapter.disconnectCall(mTelecomCallId);
1777     }
1778 
1779     /**
1780      * Instructs this {@code Call} to go on hold.
1781      */
hold()1782     public void hold() {
1783         mInCallAdapter.holdCall(mTelecomCallId);
1784     }
1785 
1786     /**
1787      * Instructs this {@link #STATE_HOLDING} call to release from hold.
1788      */
unhold()1789     public void unhold() {
1790         mInCallAdapter.unholdCall(mTelecomCallId);
1791     }
1792 
1793     /**
1794      * Instructs Telecom to put the call into the background audio processing state.
1795      * <p>
1796      * This method can be called either when the call is in {@link #STATE_RINGING} or
1797      * {@link #STATE_ACTIVE}. After Telecom acknowledges the request by setting the call's state to
1798      * {@link #STATE_AUDIO_PROCESSING}, your app may setup the audio paths with the audio stack in
1799      * order to capture and play audio on the call stream.
1800      * <p>
1801      * This method can only be called by the default dialer app.
1802      * <p>
1803      * Apps built with SDK version {@link android.os.Build.VERSION_CODES#R} or later which are using
1804      * the microphone as part of audio processing should specify the foreground service type using
1805      * the attribute {@link android.R.attr#foregroundServiceType} in the {@link InCallService}
1806      * service element of the app's manifest file.
1807      * The {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_MICROPHONE} attribute should be specified.
1808      * @see <a href="https://developer.android.com/preview/privacy/foreground-service-types">
1809      * the Android Developer Site</a> for more information.
1810      * @hide
1811      */
1812     @SystemApi
enterBackgroundAudioProcessing()1813     public void enterBackgroundAudioProcessing() {
1814         if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
1815             throw new IllegalStateException("Call must be active or ringing");
1816         }
1817         mInCallAdapter.enterBackgroundAudioProcessing(mTelecomCallId);
1818     }
1819 
1820     /**
1821      * Instructs Telecom to come out of the background audio processing state requested by
1822      * {@link #enterBackgroundAudioProcessing()} or from the call screening service.
1823      *
1824      * This method can only be called when the call is in {@link #STATE_AUDIO_PROCESSING}.
1825      *
1826      * @param shouldRing If true, Telecom will put the call into the
1827      *                   {@link #STATE_SIMULATED_RINGING} state and notify other apps that there is
1828      *                   a ringing call. Otherwise, the call will go into {@link #STATE_ACTIVE}
1829      *                   immediately.
1830      * @hide
1831      */
1832     @SystemApi
exitBackgroundAudioProcessing(boolean shouldRing)1833     public void exitBackgroundAudioProcessing(boolean shouldRing) {
1834         if (mState != STATE_AUDIO_PROCESSING) {
1835             throw new IllegalStateException("Call must in the audio processing state");
1836         }
1837         mInCallAdapter.exitBackgroundAudioProcessing(mTelecomCallId, shouldRing);
1838     }
1839 
1840     /**
1841      * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
1842      *
1843      * Any other currently playing DTMF tone in the specified call is immediately stopped.
1844      *
1845      * @param digit A character representing the DTMF digit for which to play the tone. This
1846      *         value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
1847      */
playDtmfTone(char digit)1848     public void playDtmfTone(char digit) {
1849         mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
1850     }
1851 
1852     /**
1853      * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
1854      * currently playing.
1855      *
1856      * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
1857      * currently playing, this method will do nothing.
1858      */
stopDtmfTone()1859     public void stopDtmfTone() {
1860         mInCallAdapter.stopDtmfTone(mTelecomCallId);
1861     }
1862 
1863     /**
1864      * Instructs this {@code Call} to continue playing a post-dial DTMF string.
1865      *
1866      * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
1867      * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
1868      *
1869      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
1870      * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
1871      *
1872      * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
1873      * {@code Call} will pause playing the tones and notify callbacks via
1874      * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
1875      * should display to the user an indication of this state and an affordance to continue
1876      * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
1877      * app should invoke the {@link #postDialContinue(boolean)} method.
1878      *
1879      * @param proceed Whether or not to continue with the post-dial sequence.
1880      */
postDialContinue(boolean proceed)1881     public void postDialContinue(boolean proceed) {
1882         mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
1883     }
1884 
1885     /**
1886      * Notifies this {@code Call} that an account has been selected and to proceed with placing
1887      * an outgoing call. Optionally sets this account as the default account.
1888      */
phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault)1889     public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
1890         mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
1891 
1892     }
1893 
1894     /**
1895      * Instructs this {@code Call} to enter a conference.
1896      *
1897      * @param callToConferenceWith The other call with which to conference.
1898      */
conference(Call callToConferenceWith)1899     public void conference(Call callToConferenceWith) {
1900         if (callToConferenceWith != null) {
1901             mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
1902         }
1903     }
1904 
1905     /**
1906      * Instructs this {@code Call} to split from any conference call with which it may be
1907      * connected.
1908      */
splitFromConference()1909     public void splitFromConference() {
1910         mInCallAdapter.splitFromConference(mTelecomCallId);
1911     }
1912 
1913     /**
1914      * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
1915      */
mergeConference()1916     public void mergeConference() {
1917         mInCallAdapter.mergeConference(mTelecomCallId);
1918     }
1919 
1920     /**
1921      * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
1922      */
swapConference()1923     public void swapConference() {
1924         mInCallAdapter.swapConference(mTelecomCallId);
1925     }
1926 
1927     /**
1928      * Pulls participants to existing call by forming a conference call.
1929      * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
1930      *
1931      * @param participants participants to be pulled to existing call.
1932      */
addConferenceParticipants(@onNull List<Uri> participants)1933     public void addConferenceParticipants(@NonNull List<Uri> participants) {
1934         mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
1935     }
1936 
1937     /**
1938      * Initiates a request to the {@link ConnectionService} to pull an external call to the local
1939      * device.
1940      * <p>
1941      * Calls to this method are ignored if the call does not have the
1942      * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
1943      * <p>
1944      * An {@link InCallService} will only see calls which support this method if it has the
1945      * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
1946      * in its manifest.
1947      */
pullExternalCall()1948     public void pullExternalCall() {
1949         // If this isn't an external call, ignore the request.
1950         if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
1951             return;
1952         }
1953 
1954         mInCallAdapter.pullExternalCall(mTelecomCallId);
1955     }
1956 
1957     /**
1958      * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
1959      * the {@link ConnectionService}.
1960      * <p>
1961      * Call events are used to communicate point in time information from an {@link InCallService}
1962      * to a {@link ConnectionService}.  A {@link ConnectionService} implementation could define
1963      * events which enable the {@link InCallService}, for example, toggle a unique feature of the
1964      * {@link ConnectionService}.
1965      * <p>
1966      * A {@link ConnectionService} can communicate to the {@link InCallService} using
1967      * {@link Connection#sendConnectionEvent(String, Bundle)}.
1968      * <p>
1969      * Events are exposed to {@link ConnectionService} implementations via
1970      * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
1971      * <p>
1972      * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
1973      * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
1974      * ignore some events altogether.
1975      * <p>
1976      * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
1977      * conflicts between {@link InCallService} implementations.  Further, {@link InCallService}
1978      * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
1979      * they define their own event types in this namespace.  When defining a custom event type,
1980      * ensure the contents of the extras {@link Bundle} is clearly defined.  Extra keys for this
1981      * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
1982      * <p>
1983      * When defining events and the associated extras, it is important to keep their behavior
1984      * consistent when the associated {@link InCallService} is updated.  Support for deprecated
1985      * events/extras should me maintained to ensure backwards compatibility with older
1986      * {@link ConnectionService} implementations which were built to support the older behavior.
1987      *
1988      * @param event The connection event.
1989      * @param extras Bundle containing extra information associated with the event.
1990      */
sendCallEvent(String event, Bundle extras)1991     public void sendCallEvent(String event, Bundle extras) {
1992         mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
1993     }
1994 
1995     /**
1996      * Sends an RTT upgrade request to the remote end of the connection. Success is not
1997      * guaranteed, and notification of success will be via the
1998      * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
1999      */
sendRttRequest()2000     public void sendRttRequest() {
2001         mInCallAdapter.sendRttRequest(mTelecomCallId);
2002     }
2003 
2004     /**
2005      * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
2006      * callback.
2007      * The ID used here should be the same as the ID that was received via the callback.
2008      * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
2009      * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
2010      */
respondToRttRequest(int id, boolean accept)2011     public void respondToRttRequest(int id, boolean accept) {
2012         mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
2013     }
2014 
2015     /**
2016      * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
2017      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
2018      * handover.
2019      * <p>
2020      * A call handover is the process where an ongoing call is transferred from one app (i.e.
2021      * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
2022      * mobile network call in a video calling app.  The mobile network call via the Telephony stack
2023      * is referred to as the source of the handover, and the video calling app is referred to as the
2024      * destination.
2025      * <p>
2026      * When considering a handover scenario the device this method is called on is considered the
2027      * <em>initiating</em> device (since the user initiates the handover from this device), and the
2028      * other device is considered the <em>receiving</em> device.
2029      * <p>
2030      * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
2031      * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
2032      * and invoke
2033      * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
2034      * ConnectionRequest)} to inform the destination app that a request has been made to handover a
2035      * call to it.  The app returns an instance of {@link Connection} to represent the handover call
2036      * At this point the app should display UI to indicate to the user that a call
2037      * handover is in process.
2038      * <p>
2039      * The destination app is responsible for communicating the handover request from the
2040      * <em>initiating</em> device to the <em>receiving</em> device.
2041      * <p>
2042      * When the app on the <em>receiving</em> device receives the handover request, it calls
2043      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
2044      * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
2045      * the destination app on the <em>receiving</em> device should show UI to allow the user to
2046      * choose whether they want to continue their call in the destination app.
2047      * <p>
2048      * When the destination app on the <em>receiving</em> device calls
2049      * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
2050      * {@link ConnectionService} and call
2051      * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
2052      * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
2053      * {@link Connection} to represent the handover call.
2054      * <p>
2055      * If the user of the <em>receiving</em> device accepts the handover, the app calls
2056      * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
2057      * original call.  If the user rejects the handover, the app calls
2058      * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
2059      * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
2060      * <p>
2061      * Telecom will only allow handovers from {@link PhoneAccount}s which declare
2062      * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
2063      * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
2064      * <p>
2065      * Errors in the handover process are reported to the {@link InCallService} via
2066      * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
2067      * the involved {@link ConnectionService}s via
2068      * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
2069      *
2070      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
2071      *                 this call to.
2072      * @param videoState Indicates the video state desired after the handover (see the
2073      *               {@code STATE_*} constants defined in {@link VideoProfile}).
2074      * @param extras Bundle containing extra information to be passed to the
2075      *               {@link ConnectionService}
2076      */
handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState, Bundle extras)2077     public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
2078             Bundle extras) {
2079         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
2080     }
2081 
2082     /**
2083      * Terminate the RTT session on this call. The resulting state change will be notified via
2084      * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
2085      */
stopRtt()2086     public void stopRtt() {
2087         mInCallAdapter.stopRtt(mTelecomCallId);
2088     }
2089 
2090     /**
2091      * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
2092      * added.
2093      * <p>
2094      * No assumptions should be made as to how an In-Call UI or service will handle these
2095      * extras.  Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
2096      *
2097      * @param extras The extras to add.
2098      */
putExtras(Bundle extras)2099     public final void putExtras(Bundle extras) {
2100         if (extras == null) {
2101             return;
2102         }
2103 
2104         if (mExtras == null) {
2105             mExtras = new Bundle();
2106         }
2107         mExtras.putAll(extras);
2108         mInCallAdapter.putExtras(mTelecomCallId, extras);
2109     }
2110 
2111     /**
2112      * Adds a boolean extra to this {@link Call}.
2113      *
2114      * @param key The extra key.
2115      * @param value The value.
2116      * @hide
2117      */
putExtra(String key, boolean value)2118     public final void putExtra(String key, boolean value) {
2119         if (mExtras == null) {
2120             mExtras = new Bundle();
2121         }
2122         mExtras.putBoolean(key, value);
2123         mInCallAdapter.putExtra(mTelecomCallId, key, value);
2124     }
2125 
2126     /**
2127      * Adds an integer extra to this {@link Call}.
2128      *
2129      * @param key The extra key.
2130      * @param value The value.
2131      * @hide
2132      */
putExtra(String key, int value)2133     public final void putExtra(String key, int value) {
2134         if (mExtras == null) {
2135             mExtras = new Bundle();
2136         }
2137         mExtras.putInt(key, value);
2138         mInCallAdapter.putExtra(mTelecomCallId, key, value);
2139     }
2140 
2141     /**
2142      * Adds a string extra to this {@link Call}.
2143      *
2144      * @param key The extra key.
2145      * @param value The value.
2146      * @hide
2147      */
putExtra(String key, String value)2148     public final void putExtra(String key, String value) {
2149         if (mExtras == null) {
2150             mExtras = new Bundle();
2151         }
2152         mExtras.putString(key, value);
2153         mInCallAdapter.putExtra(mTelecomCallId, key, value);
2154     }
2155 
2156     /**
2157      * Removes extras from this {@link Call}.
2158      *
2159      * @param keys The keys of the extras to remove.
2160      */
removeExtras(List<String> keys)2161     public final void removeExtras(List<String> keys) {
2162         if (mExtras != null) {
2163             for (String key : keys) {
2164                 mExtras.remove(key);
2165             }
2166             if (mExtras.size() == 0) {
2167                 mExtras = null;
2168             }
2169         }
2170         mInCallAdapter.removeExtras(mTelecomCallId, keys);
2171     }
2172 
2173     /**
2174      * Removes extras from this {@link Call}.
2175      *
2176      * @param keys The keys of the extras to remove.
2177      */
removeExtras(String .... keys)2178     public final void removeExtras(String ... keys) {
2179         removeExtras(Arrays.asList(keys));
2180     }
2181 
2182     /**
2183      * Obtains the parent of this {@code Call} in a conference, if any.
2184      *
2185      * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
2186      * child of any conference {@code Call}s.
2187      */
getParent()2188     public Call getParent() {
2189         if (mParentId != null) {
2190             return mPhone.internalGetCallByTelecomId(mParentId);
2191         }
2192         return null;
2193     }
2194 
2195     /**
2196      * Obtains the children of this conference {@code Call}, if any.
2197      *
2198      * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
2199      * {@code List} otherwise.
2200      */
getChildren()2201     public List<Call> getChildren() {
2202         if (!mChildrenCached) {
2203             mChildrenCached = true;
2204             mChildren.clear();
2205 
2206             for(String id : mChildrenIds) {
2207                 Call call = mPhone.internalGetCallByTelecomId(id);
2208                 if (call == null) {
2209                     // At least one child was still not found, so do not save true for "cached"
2210                     mChildrenCached = false;
2211                 } else {
2212                     mChildren.add(call);
2213                 }
2214             }
2215         }
2216 
2217         return mUnmodifiableChildren;
2218     }
2219 
2220     /**
2221      * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
2222      *
2223      * @return The list of conferenceable {@code Call}s.
2224      */
getConferenceableCalls()2225     public List<Call> getConferenceableCalls() {
2226         return mUnmodifiableConferenceableCalls;
2227     }
2228 
2229     /**
2230      * Obtains the state of this {@code Call}.
2231      *
2232      * @return The call state.
2233      * @deprecated The call state is available via {@link Call.Details#getState()}.
2234      */
2235     @Deprecated
getState()2236     public @CallState int getState() {
2237         return mState;
2238     }
2239 
2240     /**
2241      * Returns the child {@link Call} in a generic conference that is currently active.
2242      *
2243      * A "generic conference" is the mechanism used to support two simultaneous calls on a device
2244      * in CDMA networks. It is effectively equivalent to having one call active and one call on hold
2245      * in GSM or IMS calls. This method returns the currently active call.
2246      *
2247      * In a generic conference, the network exposes the conference to us as a single call, and we
2248      * switch between talking to the two participants using a CDMA flash command. Since the network
2249      * exposes no additional information about the call, the only way we know which caller we're
2250      * currently talking to is by keeping track of the flash commands that we've sent to the
2251      * network.
2252      *
2253      * For calls that are not generic conferences, or when the generic conference has more than
2254      * 2 children, returns {@code null}.
2255      * @see Details#PROPERTY_GENERIC_CONFERENCE
2256      * @return The active child call.
2257      */
getGenericConferenceActiveChildCall()2258     public @Nullable Call getGenericConferenceActiveChildCall() {
2259         if (mActiveGenericConferenceChild != null) {
2260             return mPhone.internalGetCallByTelecomId(mActiveGenericConferenceChild);
2261         }
2262         return null;
2263     }
2264 
2265     /**
2266      * Obtains a list of canned, pre-configured message responses to present to the user as
2267      * ways of rejecting an incoming {@code Call} using via a text message.
2268      * <p>
2269      * <em>Note:</em> Since canned responses may be loaded from the file system, they are not
2270      * guaranteed to be present when this {@link Call} is first added to the {@link InCallService}
2271      * via {@link InCallService#onCallAdded(Call)}.  The callback
2272      * {@link Call.Callback#onCannedTextResponsesLoaded(Call, List)} will be called when/if canned
2273      * responses for the call become available.
2274      *
2275      * @see #reject(boolean, String)
2276      *
2277      * @return A list of canned text message responses.
2278      */
getCannedTextResponses()2279     public List<String> getCannedTextResponses() {
2280         return mCannedTextResponses;
2281     }
2282 
2283     /**
2284      * Obtains an object that can be used to display video from this {@code Call}.
2285      *
2286      * @return An {@code Call.VideoCall}.
2287      */
getVideoCall()2288     public InCallService.VideoCall getVideoCall() {
2289         return mVideoCallImpl;
2290     }
2291 
2292     /**
2293      * Obtains an object containing call details.
2294      *
2295      * @return A {@link Details} object. Depending on the state of the {@code Call}, the
2296      * result may be {@code null}.
2297      */
getDetails()2298     public Details getDetails() {
2299         return mDetails;
2300     }
2301 
2302     /**
2303      * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
2304      * receive RTT text data, as well as to change the RTT mode.
2305      * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
2306      */
getRttCall()2307     public @Nullable RttCall getRttCall() {
2308         return mRttCall;
2309     }
2310 
2311     /**
2312      * Returns whether this call has an active RTT connection.
2313      * @return true if there is a connection, false otherwise.
2314      */
isRttActive()2315     public boolean isRttActive() {
2316         return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
2317     }
2318 
2319     /**
2320      * Registers a callback to this {@code Call}.
2321      *
2322      * @param callback A {@code Callback}.
2323      */
registerCallback(Callback callback)2324     public void registerCallback(Callback callback) {
2325         registerCallback(callback, new Handler());
2326     }
2327 
2328     /**
2329      * Registers a callback to this {@code Call}.
2330      *
2331      * @param callback A {@code Callback}.
2332      * @param handler A handler which command and status changes will be delivered to.
2333      */
registerCallback(Callback callback, Handler handler)2334     public void registerCallback(Callback callback, Handler handler) {
2335         unregisterCallback(callback);
2336         // Don't allow new callback registration if the call is already being destroyed.
2337         if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
2338             mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
2339         }
2340     }
2341 
2342     /**
2343      * Unregisters a callback from this {@code Call}.
2344      *
2345      * @param callback A {@code Callback}.
2346      */
unregisterCallback(Callback callback)2347     public void unregisterCallback(Callback callback) {
2348         // Don't allow callback deregistration if the call is already being destroyed.
2349         if (callback != null && mState != STATE_DISCONNECTED) {
2350             for (CallbackRecord<Callback> record : mCallbackRecords) {
2351                 if (record.getCallback() == callback) {
2352                     mCallbackRecords.remove(record);
2353                     break;
2354                 }
2355             }
2356         }
2357     }
2358 
2359     @Override
toString()2360     public String toString() {
2361         return new StringBuilder().
2362                 append("Call [id: ").
2363                 append(mTelecomCallId).
2364                 append(", state: ").
2365                 append(stateToString(mState)).
2366                 append(", details: ").
2367                 append(mDetails).
2368                 append("]").toString();
2369     }
2370 
2371     /**
2372      * @param state An integer value of a {@code STATE_*} constant.
2373      * @return A string representation of the value.
2374      */
stateToString(int state)2375     private static String stateToString(int state) {
2376         switch (state) {
2377             case STATE_NEW:
2378                 return "NEW";
2379             case STATE_RINGING:
2380                 return "RINGING";
2381             case STATE_DIALING:
2382                 return "DIALING";
2383             case STATE_ACTIVE:
2384                 return "ACTIVE";
2385             case STATE_HOLDING:
2386                 return "HOLDING";
2387             case STATE_DISCONNECTED:
2388                 return "DISCONNECTED";
2389             case STATE_CONNECTING:
2390                 return "CONNECTING";
2391             case STATE_DISCONNECTING:
2392                 return "DISCONNECTING";
2393             case STATE_SELECT_PHONE_ACCOUNT:
2394                 return "SELECT_PHONE_ACCOUNT";
2395             case STATE_SIMULATED_RINGING:
2396                 return "SIMULATED_RINGING";
2397             case STATE_AUDIO_PROCESSING:
2398                 return "AUDIO_PROCESSING";
2399             default:
2400                 Log.w(Call.class, "Unknown state %d", state);
2401                 return "UNKNOWN";
2402         }
2403     }
2404 
2405     /**
2406      * Adds a listener to this {@code Call}.
2407      *
2408      * @param listener A {@code Listener}.
2409      * @deprecated Use {@link #registerCallback} instead.
2410      * @hide
2411      */
2412     @Deprecated
2413     @SystemApi
addListener(Listener listener)2414     public void addListener(Listener listener) {
2415         registerCallback(listener);
2416     }
2417 
2418     /**
2419      * Removes a listener from this {@code Call}.
2420      *
2421      * @param listener A {@code Listener}.
2422      * @deprecated Use {@link #unregisterCallback} instead.
2423      * @hide
2424      */
2425     @Deprecated
2426     @SystemApi
removeListener(Listener listener)2427     public void removeListener(Listener listener) {
2428         unregisterCallback(listener);
2429     }
2430 
2431     /** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage, int targetSdkVersion)2432     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
2433          int targetSdkVersion) {
2434         mPhone = phone;
2435         mTelecomCallId = telecomCallId;
2436         mInCallAdapter = inCallAdapter;
2437         mState = STATE_NEW;
2438         mCallingPackage = callingPackage;
2439         mTargetSdkVersion = targetSdkVersion;
2440     }
2441 
2442     /** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state, String callingPackage, int targetSdkVersion)2443     Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
2444             String callingPackage, int targetSdkVersion) {
2445         mPhone = phone;
2446         mTelecomCallId = telecomCallId;
2447         mInCallAdapter = inCallAdapter;
2448         mState = state;
2449         mCallingPackage = callingPackage;
2450         mTargetSdkVersion = targetSdkVersion;
2451     }
2452 
2453     /** {@hide} */
internalGetCallId()2454     final String internalGetCallId() {
2455         return mTelecomCallId;
2456     }
2457 
2458     /** {@hide} */
internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap)2459     final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
2460 
2461         // First, we update the internal state as far as possible before firing any updates.
2462         Details details = Details.createFromParcelableCall(parcelableCall);
2463         boolean detailsChanged = !Objects.equals(mDetails, details);
2464         if (detailsChanged) {
2465             mDetails = details;
2466         }
2467 
2468         boolean cannedTextResponsesChanged = false;
2469         if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
2470                 && !parcelableCall.getCannedSmsResponses().isEmpty()) {
2471             mCannedTextResponses =
2472                     Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
2473             cannedTextResponsesChanged = true;
2474         }
2475 
2476         IVideoProvider previousVideoProvider = mVideoCallImpl == null ? null :
2477                 mVideoCallImpl.getVideoProvider();
2478         IVideoProvider newVideoProvider = parcelableCall.getVideoProvider();
2479 
2480         // parcelableCall.isVideoCallProviderChanged is only true when we have a video provider
2481         // specified; so we should check if the actual IVideoProvider changes as well.
2482         boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged()
2483                 && !Objects.equals(previousVideoProvider, newVideoProvider);
2484         if (videoCallChanged) {
2485             if (mVideoCallImpl != null) {
2486                 mVideoCallImpl.destroy();
2487             }
2488             mVideoCallImpl = parcelableCall.isVideoCallProviderChanged() ?
2489                     parcelableCall.getVideoCallImpl(mCallingPackage, mTargetSdkVersion) : null;
2490         }
2491 
2492         if (mVideoCallImpl != null) {
2493             mVideoCallImpl.setVideoState(getDetails().getVideoState());
2494         }
2495 
2496         int state = parcelableCall.getState();
2497         if (mTargetSdkVersion < Phone.SDK_VERSION_R && state == Call.STATE_SIMULATED_RINGING) {
2498             state = Call.STATE_RINGING;
2499         }
2500         boolean stateChanged = mState != state;
2501         if (stateChanged) {
2502             mState = state;
2503         }
2504 
2505         String parentId = parcelableCall.getParentCallId();
2506         boolean parentChanged = !Objects.equals(mParentId, parentId);
2507         if (parentChanged) {
2508             mParentId = parentId;
2509         }
2510 
2511         List<String> childCallIds = parcelableCall.getChildCallIds();
2512         boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
2513         if (childrenChanged) {
2514             mChildrenIds.clear();
2515             mChildrenIds.addAll(parcelableCall.getChildCallIds());
2516             mChildrenCached = false;
2517         }
2518 
2519         String activeChildCallId = parcelableCall.getActiveChildCallId();
2520         boolean activeChildChanged = !Objects.equals(activeChildCallId,
2521                 mActiveGenericConferenceChild);
2522         if (activeChildChanged) {
2523             mActiveGenericConferenceChild = activeChildCallId;
2524         }
2525 
2526         List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
2527         List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
2528         for (String otherId : conferenceableCallIds) {
2529             if (callIdMap.containsKey(otherId)) {
2530                 conferenceableCalls.add(callIdMap.get(otherId));
2531             }
2532         }
2533 
2534         if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
2535             mConferenceableCalls.clear();
2536             mConferenceableCalls.addAll(conferenceableCalls);
2537             fireConferenceableCallsChanged();
2538         }
2539 
2540         boolean isRttChanged = false;
2541         boolean rttModeChanged = false;
2542         if (parcelableCall.getIsRttCallChanged()
2543                 && mDetails.hasProperty(Details.PROPERTY_RTT)) {
2544             ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
2545             InputStreamReader receiveStream = new InputStreamReader(
2546                     new ParcelFileDescriptor.AutoCloseInputStream(
2547                             parcelableRttCall.getReceiveStream()),
2548                     StandardCharsets.UTF_8);
2549             OutputStreamWriter transmitStream = new OutputStreamWriter(
2550                     new ParcelFileDescriptor.AutoCloseOutputStream(
2551                             parcelableRttCall.getTransmitStream()),
2552                     StandardCharsets.UTF_8);
2553             RttCall newRttCall = new Call.RttCall(mTelecomCallId,
2554                     receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
2555             if (mRttCall == null) {
2556                 isRttChanged = true;
2557             } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
2558                 rttModeChanged = true;
2559             }
2560             mRttCall = newRttCall;
2561         } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
2562                 && parcelableCall.getIsRttCallChanged()) {
2563             isRttChanged = true;
2564             mRttCall.close();
2565             mRttCall = null;
2566         }
2567 
2568         // Now we fire updates, ensuring that any client who listens to any of these notifications
2569         // gets the most up-to-date state.
2570 
2571         if (stateChanged) {
2572             fireStateChanged(mState);
2573         }
2574         if (detailsChanged) {
2575             fireDetailsChanged(mDetails);
2576         }
2577         if (cannedTextResponsesChanged) {
2578             fireCannedTextResponsesLoaded(mCannedTextResponses);
2579         }
2580         if (videoCallChanged) {
2581             fireVideoCallChanged(mVideoCallImpl);
2582         }
2583         if (parentChanged) {
2584             fireParentChanged(getParent());
2585         }
2586         if (childrenChanged || activeChildChanged) {
2587             fireChildrenChanged(getChildren());
2588         }
2589         if (isRttChanged) {
2590             fireOnIsRttChanged(mRttCall != null, mRttCall);
2591         }
2592         if (rttModeChanged) {
2593             fireOnRttModeChanged(mRttCall.getRttAudioMode());
2594         }
2595 
2596         // If we have transitioned to DISCONNECTED, that means we need to notify clients and
2597         // remove ourselves from the Phone. Note that we do this after completing all state updates
2598         // so a client can cleanly transition all their UI to the state appropriate for a
2599         // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
2600         if (mState == STATE_DISCONNECTED) {
2601             fireCallDestroyed();
2602         }
2603     }
2604 
2605     /** {@hide} */
internalSetPostDialWait(String remaining)2606     final void internalSetPostDialWait(String remaining) {
2607         mRemainingPostDialSequence = remaining;
2608         firePostDialWait(mRemainingPostDialSequence);
2609     }
2610 
2611     /** {@hide} */
internalSetDisconnected()2612     final void internalSetDisconnected() {
2613         if (mState != Call.STATE_DISCONNECTED) {
2614             mState = Call.STATE_DISCONNECTED;
2615             if (mDetails != null) {
2616                 mDetails = new Details(mState,
2617                         mDetails.getTelecomCallId(),
2618                         mDetails.getHandle(),
2619                         mDetails.getHandlePresentation(),
2620                         mDetails.getCallerDisplayName(),
2621                         mDetails.getCallerDisplayNamePresentation(),
2622                         mDetails.getAccountHandle(),
2623                         mDetails.getCallCapabilities(),
2624                         mDetails.getCallProperties(),
2625                         mDetails.getDisconnectCause(),
2626                         mDetails.getConnectTimeMillis(),
2627                         mDetails.getGatewayInfo(),
2628                         mDetails.getVideoState(),
2629                         mDetails.getStatusHints(),
2630                         mDetails.getExtras(),
2631                         mDetails.getIntentExtras(),
2632                         mDetails.getCreationTimeMillis(),
2633                         mDetails.getContactDisplayName(),
2634                         mDetails.getCallDirection(),
2635                         mDetails.getCallerNumberVerificationStatus()
2636                         );
2637                 fireDetailsChanged(mDetails);
2638             }
2639             fireStateChanged(mState);
2640             fireCallDestroyed();
2641         }
2642     }
2643 
2644     /** {@hide} */
internalOnConnectionEvent(String event, Bundle extras)2645     final void internalOnConnectionEvent(String event, Bundle extras) {
2646         fireOnConnectionEvent(event, extras);
2647     }
2648 
2649     /** {@hide} */
internalOnRttUpgradeRequest(final int requestId)2650     final void internalOnRttUpgradeRequest(final int requestId) {
2651         for (CallbackRecord<Callback> record : mCallbackRecords) {
2652             final Call call = this;
2653             final Callback callback = record.getCallback();
2654             record.getHandler().post(() -> callback.onRttRequest(call, requestId));
2655         }
2656     }
2657 
2658     /** @hide */
internalOnRttInitiationFailure(int reason)2659     final void internalOnRttInitiationFailure(int reason) {
2660         for (CallbackRecord<Callback> record : mCallbackRecords) {
2661             final Call call = this;
2662             final Callback callback = record.getCallback();
2663             record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
2664         }
2665     }
2666 
2667     /** {@hide} */
internalOnHandoverFailed(int error)2668     final void internalOnHandoverFailed(int error) {
2669         for (CallbackRecord<Callback> record : mCallbackRecords) {
2670             final Call call = this;
2671             final Callback callback = record.getCallback();
2672             record.getHandler().post(() -> callback.onHandoverFailed(call, error));
2673         }
2674     }
2675 
2676     /** {@hide} */
internalOnHandoverComplete()2677     final void internalOnHandoverComplete() {
2678         for (CallbackRecord<Callback> record : mCallbackRecords) {
2679             final Call call = this;
2680             final Callback callback = record.getCallback();
2681             record.getHandler().post(() -> callback.onHandoverComplete(call));
2682         }
2683     }
2684 
fireStateChanged(final int newState)2685     private void fireStateChanged(final int newState) {
2686         for (CallbackRecord<Callback> record : mCallbackRecords) {
2687             final Call call = this;
2688             final Callback callback = record.getCallback();
2689             record.getHandler().post(new Runnable() {
2690                 @Override
2691                 public void run() {
2692                     callback.onStateChanged(call, newState);
2693                 }
2694             });
2695         }
2696     }
2697 
fireParentChanged(final Call newParent)2698     private void fireParentChanged(final Call newParent) {
2699         for (CallbackRecord<Callback> record : mCallbackRecords) {
2700             final Call call = this;
2701             final Callback callback = record.getCallback();
2702             record.getHandler().post(new Runnable() {
2703                 @Override
2704                 public void run() {
2705                     callback.onParentChanged(call, newParent);
2706                 }
2707             });
2708         }
2709     }
2710 
fireChildrenChanged(final List<Call> children)2711     private void fireChildrenChanged(final List<Call> children) {
2712         for (CallbackRecord<Callback> record : mCallbackRecords) {
2713             final Call call = this;
2714             final Callback callback = record.getCallback();
2715             record.getHandler().post(new Runnable() {
2716                 @Override
2717                 public void run() {
2718                     callback.onChildrenChanged(call, children);
2719                 }
2720             });
2721         }
2722     }
2723 
fireDetailsChanged(final Details details)2724     private void fireDetailsChanged(final Details details) {
2725         for (CallbackRecord<Callback> record : mCallbackRecords) {
2726             final Call call = this;
2727             final Callback callback = record.getCallback();
2728             record.getHandler().post(new Runnable() {
2729                 @Override
2730                 public void run() {
2731                     callback.onDetailsChanged(call, details);
2732                 }
2733             });
2734         }
2735     }
2736 
fireCannedTextResponsesLoaded(final List<String> cannedTextResponses)2737     private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
2738         for (CallbackRecord<Callback> record : mCallbackRecords) {
2739             final Call call = this;
2740             final Callback callback = record.getCallback();
2741             record.getHandler().post(new Runnable() {
2742                 @Override
2743                 public void run() {
2744                     callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
2745                 }
2746             });
2747         }
2748     }
2749 
fireVideoCallChanged(final InCallService.VideoCall videoCall)2750     private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
2751         for (CallbackRecord<Callback> record : mCallbackRecords) {
2752             final Call call = this;
2753             final Callback callback = record.getCallback();
2754             record.getHandler().post(new Runnable() {
2755                 @Override
2756                 public void run() {
2757                     callback.onVideoCallChanged(call, videoCall);
2758                 }
2759             });
2760         }
2761     }
2762 
firePostDialWait(final String remainingPostDialSequence)2763     private void firePostDialWait(final String remainingPostDialSequence) {
2764         for (CallbackRecord<Callback> record : mCallbackRecords) {
2765             final Call call = this;
2766             final Callback callback = record.getCallback();
2767             record.getHandler().post(new Runnable() {
2768                 @Override
2769                 public void run() {
2770                     callback.onPostDialWait(call, remainingPostDialSequence);
2771                 }
2772             });
2773         }
2774     }
2775 
fireCallDestroyed()2776     private void fireCallDestroyed() {
2777         /**
2778          * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
2779          * onCallRemoved callback, we remove this call from the Phone's record
2780          * only once all of the registered onCallDestroyed callbacks are executed.
2781          * All the callbacks get removed from our records as a part of this operation
2782          * since onCallDestroyed is the final callback.
2783          */
2784         final Call call = this;
2785         if (mCallbackRecords.isEmpty()) {
2786             // No callbacks registered, remove the call from Phone's record.
2787             mPhone.internalRemoveCall(call);
2788         }
2789         for (final CallbackRecord<Callback> record : mCallbackRecords) {
2790             final Callback callback = record.getCallback();
2791             record.getHandler().post(new Runnable() {
2792                 @Override
2793                 public void run() {
2794                     boolean isFinalRemoval = false;
2795                     RuntimeException toThrow = null;
2796                     try {
2797                         callback.onCallDestroyed(call);
2798                     } catch (RuntimeException e) {
2799                             toThrow = e;
2800                     }
2801                     synchronized(Call.this) {
2802                         mCallbackRecords.remove(record);
2803                         if (mCallbackRecords.isEmpty()) {
2804                             isFinalRemoval = true;
2805                         }
2806                     }
2807                     if (isFinalRemoval) {
2808                         mPhone.internalRemoveCall(call);
2809                     }
2810                     if (toThrow != null) {
2811                         throw toThrow;
2812                     }
2813                 }
2814             });
2815         }
2816     }
2817 
fireConferenceableCallsChanged()2818     private void fireConferenceableCallsChanged() {
2819         for (CallbackRecord<Callback> record : mCallbackRecords) {
2820             final Call call = this;
2821             final Callback callback = record.getCallback();
2822             record.getHandler().post(new Runnable() {
2823                 @Override
2824                 public void run() {
2825                     callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
2826                 }
2827             });
2828         }
2829     }
2830 
2831     /**
2832      * Notifies listeners of an incoming connection event.
2833      * <p>
2834      * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
2835      *
2836      * @param event
2837      * @param extras
2838      */
fireOnConnectionEvent(final String event, final Bundle extras)2839     private void fireOnConnectionEvent(final String event, final Bundle extras) {
2840         for (CallbackRecord<Callback> record : mCallbackRecords) {
2841             final Call call = this;
2842             final Callback callback = record.getCallback();
2843             record.getHandler().post(new Runnable() {
2844                 @Override
2845                 public void run() {
2846                     callback.onConnectionEvent(call, event, extras);
2847                 }
2848             });
2849         }
2850     }
2851 
2852     /**
2853      * Notifies listeners of an RTT on/off change
2854      *
2855      * @param enabled True if RTT is now enabled, false otherwise
2856      */
fireOnIsRttChanged(final boolean enabled, final RttCall rttCall)2857     private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
2858         for (CallbackRecord<Callback> record : mCallbackRecords) {
2859             final Call call = this;
2860             final Callback callback = record.getCallback();
2861             record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
2862         }
2863     }
2864 
2865     /**
2866      * Notifies listeners of a RTT mode change
2867      *
2868      * @param mode The new RTT mode
2869      */
fireOnRttModeChanged(final int mode)2870     private void fireOnRttModeChanged(final int mode) {
2871         for (CallbackRecord<Callback> record : mCallbackRecords) {
2872             final Call call = this;
2873             final Callback callback = record.getCallback();
2874             record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
2875         }
2876     }
2877 
2878     /**
2879      * Determines if two bundles are equal.
2880      *
2881      * @param bundle The original bundle.
2882      * @param newBundle The bundle to compare with.
2883      * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
2884      */
areBundlesEqual(Bundle bundle, Bundle newBundle)2885     private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
2886         if (bundle == null || newBundle == null) {
2887             return bundle == newBundle;
2888         }
2889 
2890         if (bundle.size() != newBundle.size()) {
2891             return false;
2892         }
2893 
2894         for(String key : bundle.keySet()) {
2895             if (key != null) {
2896                 final Object value = bundle.get(key);
2897                 final Object newValue = newBundle.get(key);
2898                 if (!newBundle.containsKey(key)) {
2899                     return false;
2900                 }
2901                 if (value instanceof Bundle && newValue instanceof Bundle) {
2902                     if (!areBundlesEqual((Bundle) value, (Bundle) newValue)) {
2903                         return false;
2904                     }
2905                 }
2906                 if (value instanceof byte[] && newValue instanceof byte[]) {
2907                     if (!Arrays.equals((byte[]) value, (byte[]) newValue)) {
2908                         return false;
2909                     }
2910                 } else if (!Objects.equals(value, newValue)) {
2911                     return false;
2912                 }
2913             }
2914         }
2915         return true;
2916     }
2917 }
2918