/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telecom;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.String;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Represents an ongoing phone call that the in-call app should present to the user.
 */
public final class Call {
    /**
     * The state of a {@code Call} when newly created.
     */
    public static final int STATE_NEW = 0;

    /**
     * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
     */
    public static final int STATE_DIALING = 1;

    /**
     * The state of an incoming {@code Call} when ringing locally, but not yet connected.
     */
    public static final int STATE_RINGING = 2;

    /**
     * The state of a {@code Call} when in a holding state.
     */
    public static final int STATE_HOLDING = 3;

    /**
     * The state of a {@code Call} when actively supporting conversation.
     */
    public static final int STATE_ACTIVE = 4;

    /**
     * The state of a {@code Call} when no further voice or other communication is being
     * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
     * is no longer active, and the local data transport has or inevitably will release resources
     * associated with this {@code Call}.
     */
    public static final int STATE_DISCONNECTED = 7;

    /**
     * The state of an outgoing {@code Call} when waiting on user to select a
     * {@link PhoneAccount} through which to place the call.
     */
    public static final int STATE_SELECT_PHONE_ACCOUNT = 8;

    /**
     * @hide
     * @deprecated use STATE_SELECT_PHONE_ACCOUNT.
     */
    @Deprecated
    @SystemApi
    public static final int STATE_PRE_DIAL_WAIT = STATE_SELECT_PHONE_ACCOUNT;

    /**
     * The initial state of an outgoing {@code Call}.
     * Common transitions are to {@link #STATE_DIALING} state for a successful call or
     * {@link #STATE_DISCONNECTED} if it failed.
     */
    public static final int STATE_CONNECTING = 9;

    /**
     * The state of a {@code Call} when the user has initiated a disconnection of the call, but the
     * call has not yet been disconnected by the underlying {@code ConnectionService}.  The next
     * state of the call is (potentially) {@link #STATE_DISCONNECTED}.
     */
    public static final int STATE_DISCONNECTING = 10;

    /**
     * The state of an external call which is in the process of being pulled from a remote device to
     * the local device.
     * <p>
     * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property
     * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call.
     * <p>
     * An {@link InCallService} will only see this state if it has the
     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its
     * manifest.
     */
    public static final int STATE_PULLING_CALL = 11;

    /**
     * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call
     * extras. Used to pass the phone accounts to display on the front end to the user in order to
     * select phone accounts to (for example) place a call.
     */
    public static final String AVAILABLE_PHONE_ACCOUNTS = "selectPhoneAccountAccounts";

    /**
     * Extra key used to indicate the time (in milliseconds since midnight, January 1, 1970 UTC)
     * when the last outgoing emergency call was made.  This is used to identify potential emergency
     * callbacks.
     */
    public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS =
            "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";

    /**
     * Call event sent from a {@link Call} via {@link #sendCallEvent(String, Bundle)} to inform
     * Telecom that the user has requested that the current {@link Call} should be handed over
     * to another {@link ConnectionService}.
     * <p>
     * The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
     * Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
     * @hide
     */
    public static final String EVENT_REQUEST_HANDOVER =
            "android.telecom.event.REQUEST_HANDOVER";

    /**
     * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
     * {@link PhoneAccountHandle} to which a call should be handed over to.
     * @hide
     */
    public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
            "android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";

    /**
     * Integer extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Specifies the
     * video state of the call when it is handed over to the new {@link PhoneAccount}.
     * <p>
     * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
     * {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
     * {@link VideoProfile#STATE_TX_ENABLED}.
     * @hide
     */
    public static final String EXTRA_HANDOVER_VIDEO_STATE =
            "android.telecom.extra.HANDOVER_VIDEO_STATE";

    /**
     * Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event.  Used by the
     * {@link InCallService} initiating a handover to provide a {@link Bundle} with extra
     * information to the handover {@link ConnectionService} specified by
     * {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE}.
     * <p>
     * This {@link Bundle} is not interpreted by Telecom, but passed as-is to the
     * {@link ConnectionService} via the request extras when
     * {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
     * is called to initate the handover.
     * @hide
     */
    public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";

    /**
     * Call event sent from Telecom to the handover {@link ConnectionService} via
     * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
     * to the {@link ConnectionService} has completed successfully.
     * <p>
     * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
     * @hide
     */
    public static final String EVENT_HANDOVER_COMPLETE =
            "android.telecom.event.HANDOVER_COMPLETE";

    /**
     * Call event sent from Telecom to the handover destination {@link ConnectionService} via
     * {@link Connection#onCallEvent(String, Bundle)} to inform the handover destination that the
     * source connection has disconnected.  The {@link Bundle} parameter for the call event will be
     * {@code null}.
     * <p>
     * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
     * @hide
     */
    public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
            "android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";

    /**
     * Call event sent from Telecom to the handover {@link ConnectionService} via
     * {@link Connection#onCallEvent(String, Bundle)} to inform a {@link Connection} that a handover
     * to the {@link ConnectionService} has failed.
     * <p>
     * A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
     * @hide
     */
    public static final String EVENT_HANDOVER_FAILED =
            "android.telecom.event.HANDOVER_FAILED";

    public static class Details {

        /** Call can currently be put on hold or unheld. */
        public static final int CAPABILITY_HOLD = 0x00000001;

        /** Call supports the hold feature. */
        public static final int CAPABILITY_SUPPORT_HOLD = 0x00000002;

        /**
         * Calls within a conference can be merged. A {@link ConnectionService} has the option to
         * add a {@link Conference} call before the child {@link Connection}s are merged. This is how
         * CDMA-based {@link Connection}s are implemented. For these unmerged {@link Conference}s, this
         * capability allows a merge button to be shown while the conference call is in the foreground
         * of the in-call UI.
         * <p>
         * This is only intended for use by a {@link Conference}.
         */
        public static final int CAPABILITY_MERGE_CONFERENCE = 0x00000004;

        /**
         * Calls within a conference can be swapped between foreground and background.
         * See {@link #CAPABILITY_MERGE_CONFERENCE} for additional information.
         * <p>
         * This is only intended for use by a {@link Conference}.
         */
        public static final int CAPABILITY_SWAP_CONFERENCE = 0x00000008;

        /**
         * @hide
         */
        public static final int CAPABILITY_UNUSED_1 = 0x00000010;

        /** Call supports responding via text option. */
        public static final int CAPABILITY_RESPOND_VIA_TEXT = 0x00000020;

        /** Call can be muted. */
        public static final int CAPABILITY_MUTE = 0x00000040;

        /**
         * Call supports conference call management. This capability only applies to {@link Conference}
         * calls which can have {@link Connection}s as children.
         */
        public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080;

        /**
         * Local device supports receiving video.
         */
        public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100;

        /**
         * Local device supports transmitting video.
         */
        public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200;

        /**
         * Local device supports bidirectional video calling.
         */
        public static final int CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL =
                CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX;

        /**
         * Remote device supports receiving video.
         */
        public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400;

        /**
         * Remote device supports transmitting video.
         */
        public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800;

        /**
         * Remote device supports bidirectional video calling.
         */
        public static final int CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL =
                CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX;

        /**
         * Call is able to be separated from its parent {@code Conference}, if any.
         */
        public static final int CAPABILITY_SEPARATE_FROM_CONFERENCE = 0x00001000;

        /**
         * Call is able to be individually disconnected when in a {@code Conference}.
         */
        public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 0x00002000;

        /**
         * Speed up audio setup for MT call.
         * @hide
         */
        public static final int CAPABILITY_SPEED_UP_MT_AUDIO = 0x00040000;

        /**
         * Call can be upgraded to a video call.
         * @hide
         */
        @UnsupportedAppUsage
        public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;

        /**
         * For video calls, indicates whether the outgoing video for the call can be paused using
         * the {@link android.telecom.VideoProfile#STATE_PAUSED} VideoState.
         */
        public static final int CAPABILITY_CAN_PAUSE_VIDEO = 0x00100000;

        /**
         * Call sends responses through connection.
         * @hide
         */
        public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00200000;

        /**
         * When set, prevents a video {@code Call} from being downgraded to an audio-only call.
         * <p>
         * Should be set when the VideoState has the {@link VideoProfile#STATE_TX_ENABLED} or
         * {@link VideoProfile#STATE_RX_ENABLED} bits set to indicate that the connection cannot be
         * downgraded from a video call back to a VideoState of
         * {@link VideoProfile#STATE_AUDIO_ONLY}.
         * <p>
         * Intuitively, a call which can be downgraded to audio should also have local and remote
         * video
         * capabilities (see {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
         * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL}).
         */
        public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000;

        /**
         * When set for an external call, indicates that this {@code Call} can be pulled from a
         * remote device to the current device.
         * <p>
         * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set.
         * <p>
         * An {@link InCallService} will only see calls with this capability if it has the
         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
         * in its manifest.
         * <p>
         * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and
         * {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
         */
        public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000;

        /**
         * Add participant in an active or conference call option
         * @hide
         */
        public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;

        /** Call supports the deflect feature. */
        public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;

        /**
         * Remote device supports RTT.
         * @hide
         */

        public static final int CAPABILITY_SUPPORTS_RTT_REMOTE = 0x04000000;

        //******************************************************************************************
        // Next CAPABILITY value: 0x08000000
        //******************************************************************************************

        /**
         * Whether the call is currently a conference.
         */
        public static final int PROPERTY_CONFERENCE = 0x00000001;

        /**
         * Whether the call is a generic conference, where we do not know the precise state of
         * participants in the conference (eg. on CDMA).
         */
        public static final int PROPERTY_GENERIC_CONFERENCE = 0x00000002;

        /**
         * Whether the call is made while the device is in emergency callback mode.
         */
        public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 0x00000004;

        /**
         * Connection is using WIFI.
         */
        public static final int PROPERTY_WIFI = 0x00000008;

        /**
         * Call is using high definition audio.
         */
        public static final int PROPERTY_HIGH_DEF_AUDIO = 0x00000010;

        /**
         * Whether the call is associated with the work profile.
         */
        public static final int PROPERTY_ENTERPRISE_CALL = 0x00000020;

        /**
         * When set, indicates that this {@code Call} does not actually exist locally for the
         * {@link ConnectionService}.
         * <p>
         * Consider, for example, a scenario where a user has two phones with the same phone number.
         * When a user places a call on one device, the telephony stack can represent that call on
         * the other device by adding it to the {@link ConnectionService} with the
         * {@link Connection#PROPERTY_IS_EXTERNAL_CALL} property set.
         * <p>
         * An {@link InCallService} will only see calls with this property if it has the
         * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
         * in its manifest.
         * <p>
         * See {@link Connection#PROPERTY_IS_EXTERNAL_CALL}.
         */
        public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040;

        /**
         * Indicates that the call has CDMA Enhanced Voice Privacy enabled.
         */
        public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 0x00000080;

        /**
         * Indicates that the call is from a self-managed {@link ConnectionService}.
         * <p>
         * See also {@link Connection#PROPERTY_SELF_MANAGED}
         */
        public static final int PROPERTY_SELF_MANAGED = 0x00000100;

        /**
         * Indicates the call used Assisted Dialing.
         * See also {@link Connection#PROPERTY_ASSISTED_DIALING_USED}
         * @hide
         */
        public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;

        /**
         * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
         * {@link RttCall} object that is used to send and receive text.
         */
        public static final int PROPERTY_RTT = 0x00000400;

        //******************************************************************************************
        // Next PROPERTY value: 0x00000800
        //******************************************************************************************

        private final String mTelecomCallId;
        private final Uri mHandle;
        private final int mHandlePresentation;
        private final String mCallerDisplayName;
        private final int mCallerDisplayNamePresentation;
        private final PhoneAccountHandle mAccountHandle;
        private final int mCallCapabilities;
        private final int mCallProperties;
        private final int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
        private final DisconnectCause mDisconnectCause;
        private final long mConnectTimeMillis;
        private final GatewayInfo mGatewayInfo;
        private final int mVideoState;
        private final StatusHints mStatusHints;
        private final Bundle mExtras;
        private final Bundle mIntentExtras;
        private final long mCreationTimeMillis;

        /**
         * Whether the supplied capabilities  supports the specified capability.
         *
         * @param capabilities A bit field of capabilities.
         * @param capability The capability to check capabilities for.
         * @return Whether the specified capability is supported.
         */
        public static boolean can(int capabilities, int capability) {
            return (capabilities & capability) == capability;
        }

        /**
         * Whether the capabilities of this {@code Details} supports the specified capability.
         *
         * @param capability The capability to check capabilities for.
         * @return Whether the specified capability is supported.
         */
        public boolean can(int capability) {
            return can(mCallCapabilities, capability);
        }

        /**
         * Render a set of capability bits ({@code CAPABILITY_*}) as a human readable string.
         *
         * @param capabilities A capability bit field.
         * @return A human readable string representation.
         */
        public static String capabilitiesToString(int capabilities) {
            StringBuilder builder = new StringBuilder();
            builder.append("[Capabilities:");
            if (can(capabilities, CAPABILITY_HOLD)) {
                builder.append(" CAPABILITY_HOLD");
            }
            if (can(capabilities, CAPABILITY_SUPPORT_HOLD)) {
                builder.append(" CAPABILITY_SUPPORT_HOLD");
            }
            if (can(capabilities, CAPABILITY_MERGE_CONFERENCE)) {
                builder.append(" CAPABILITY_MERGE_CONFERENCE");
            }
            if (can(capabilities, CAPABILITY_SWAP_CONFERENCE)) {
                builder.append(" CAPABILITY_SWAP_CONFERENCE");
            }
            if (can(capabilities, CAPABILITY_RESPOND_VIA_TEXT)) {
                builder.append(" CAPABILITY_RESPOND_VIA_TEXT");
            }
            if (can(capabilities, CAPABILITY_MUTE)) {
                builder.append(" CAPABILITY_MUTE");
            }
            if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) {
                builder.append(" CAPABILITY_MANAGE_CONFERENCE");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX");
            }
            if (can(capabilities, CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO)) {
                builder.append(" CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL)) {
                builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL");
            }
            if (can(capabilities, CAPABILITY_SPEED_UP_MT_AUDIO)) {
                builder.append(" CAPABILITY_SPEED_UP_MT_AUDIO");
            }
            if (can(capabilities, CAPABILITY_CAN_UPGRADE_TO_VIDEO)) {
                builder.append(" CAPABILITY_CAN_UPGRADE_TO_VIDEO");
            }
            if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) {
                builder.append(" CAPABILITY_CAN_PAUSE_VIDEO");
            }
            if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) {
                builder.append(" CAPABILITY_CAN_PULL_CALL");
            }
            if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
                builder.append(" CAPABILITY_ADD_PARTICIPANT");
            }
            if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
                builder.append(" CAPABILITY_SUPPORT_DEFLECT");
            }
            if (can(capabilities, CAPABILITY_SUPPORTS_RTT_REMOTE)) {
                builder.append(" CAPABILITY_SUPPORTS_RTT_REMOTE");
            }
            builder.append("]");
            return builder.toString();
        }

        /**
         * Whether the supplied properties includes the specified property.
         *
         * @param properties A bit field of properties.
         * @param property The property to check properties for.
         * @return Whether the specified property is supported.
         */
        public static boolean hasProperty(int properties, int property) {
            return (properties & property) == property;
        }

        /**
         * Whether the properties of this {@code Details} includes the specified property.
         *
         * @param property The property to check properties for.
         * @return Whether the specified property is supported.
         */
        public boolean hasProperty(int property) {
            return hasProperty(mCallProperties, property);
        }

        /**
         * Render a set of property bits ({@code PROPERTY_*}) as a human readable string.
         *
         * @param properties A property bit field.
         * @return A human readable string representation.
         */
        public static String propertiesToString(int properties) {
            StringBuilder builder = new StringBuilder();
            builder.append("[Properties:");
            if (hasProperty(properties, PROPERTY_CONFERENCE)) {
                builder.append(" PROPERTY_CONFERENCE");
            }
            if (hasProperty(properties, PROPERTY_GENERIC_CONFERENCE)) {
                builder.append(" PROPERTY_GENERIC_CONFERENCE");
            }
            if (hasProperty(properties, PROPERTY_WIFI)) {
                builder.append(" PROPERTY_WIFI");
            }
            if (hasProperty(properties, PROPERTY_HIGH_DEF_AUDIO)) {
                builder.append(" PROPERTY_HIGH_DEF_AUDIO");
            }
            if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
                builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
            }
            if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) {
                builder.append(" PROPERTY_IS_EXTERNAL_CALL");
            }
            if(hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
                builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
            }
            if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
                builder.append(" PROPERTY_ASSISTED_DIALING_USED");
            }
            builder.append("]");
            return builder.toString();
        }

        /** {@hide} */
        public String getTelecomCallId() {
            return mTelecomCallId;
        }

        /**
         * @return The handle (e.g., phone number) to which the {@code Call} is currently
         * connected.
         */
        public Uri getHandle() {
            return mHandle;
        }

        /**
         * @return The presentation requirements for the handle. See
         * {@link TelecomManager} for valid values.
         */
        public int getHandlePresentation() {
            return mHandlePresentation;
        }

        /**
         * @return The display name for the caller.
         */
        public String getCallerDisplayName() {
            return mCallerDisplayName;
        }

        /**
         * @return The presentation requirements for the caller display name. See
         * {@link TelecomManager} for valid values.
         */
        public int getCallerDisplayNamePresentation() {
            return mCallerDisplayNamePresentation;
        }

        /**
         * @return The {@code PhoneAccountHandle} whereby the {@code Call} is currently being
         * routed.
         */
        public PhoneAccountHandle getAccountHandle() {
            return mAccountHandle;
        }

        /**
         * @return A bitmask of the capabilities of the {@code Call}, as defined by the various
         *         {@code CAPABILITY_*} constants in this class.
         */
        public int getCallCapabilities() {
            return mCallCapabilities;
        }

        /**
         * @return A bitmask of the properties of the {@code Call}, as defined by the various
         *         {@code PROPERTY_*} constants in this class.
         */
        public int getCallProperties() {
            return mCallProperties;
        }

        /**
         * @return a bitmask of the audio routes available for the call.
         *
         * @hide
         */
        public int getSupportedAudioRoutes() {
            return mSupportedAudioRoutes;
        }

        /**
         * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
         * by {@link android.telecom.DisconnectCause}.
         */
        public DisconnectCause getDisconnectCause() {
            return mDisconnectCause;
        }

        /**
         * Returns the time the {@link Call} connected (i.e. became active).  This information is
         * updated periodically, but user interfaces should not rely on this to display the "call
         * time clock".  For the time when the call was first added to Telecom, see
         * {@link #getCreationTimeMillis()}.
         *
         * @return The time the {@link Call} connected in milliseconds since the epoch.
         */
        public final long getConnectTimeMillis() {
            return mConnectTimeMillis;
        }

        /**
         * @return Information about any calling gateway the {@code Call} may be using.
         */
        public GatewayInfo getGatewayInfo() {
            return mGatewayInfo;
        }

        /**
         * @return The video state of the {@code Call}.
         */
        public int getVideoState() {
            return mVideoState;
        }

        /**
         * @return The current {@link android.telecom.StatusHints}, or {@code null} if none
         * have been set.
         */
        public StatusHints getStatusHints() {
            return mStatusHints;
        }

        /**
         * @return The extras associated with this call.
         */
        public Bundle getExtras() {
            return mExtras;
        }

        /**
         * @return The extras used with the original intent to place this call.
         */
        public Bundle getIntentExtras() {
            return mIntentExtras;
        }

        /**
         * Returns the time when the call was first created and added to Telecom.  This is the same
         * time that is logged as the start time in the Call Log (see
         * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
         * (became active), see {@link #getConnectTimeMillis()}.
         *
         * @return The creation time of the call, in millis since the epoch.
         */
        public long getCreationTimeMillis() {
            return mCreationTimeMillis;
        }

        @Override
        public boolean equals(Object o) {
            if (o instanceof Details) {
                Details d = (Details) o;
                return
                        Objects.equals(mHandle, d.mHandle) &&
                        Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
                        Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
                        Objects.equals(mCallerDisplayNamePresentation,
                                d.mCallerDisplayNamePresentation) &&
                        Objects.equals(mAccountHandle, d.mAccountHandle) &&
                        Objects.equals(mCallCapabilities, d.mCallCapabilities) &&
                        Objects.equals(mCallProperties, d.mCallProperties) &&
                        Objects.equals(mDisconnectCause, d.mDisconnectCause) &&
                        Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
                        Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
                        Objects.equals(mVideoState, d.mVideoState) &&
                        Objects.equals(mStatusHints, d.mStatusHints) &&
                        areBundlesEqual(mExtras, d.mExtras) &&
                        areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
                        Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mHandle,
                            mHandlePresentation,
                            mCallerDisplayName,
                            mCallerDisplayNamePresentation,
                            mAccountHandle,
                            mCallCapabilities,
                            mCallProperties,
                            mDisconnectCause,
                            mConnectTimeMillis,
                            mGatewayInfo,
                            mVideoState,
                            mStatusHints,
                            mExtras,
                            mIntentExtras,
                            mCreationTimeMillis);
        }

        /** {@hide} */
        public Details(
                String telecomCallId,
                Uri handle,
                int handlePresentation,
                String callerDisplayName,
                int callerDisplayNamePresentation,
                PhoneAccountHandle accountHandle,
                int capabilities,
                int properties,
                DisconnectCause disconnectCause,
                long connectTimeMillis,
                GatewayInfo gatewayInfo,
                int videoState,
                StatusHints statusHints,
                Bundle extras,
                Bundle intentExtras,
                long creationTimeMillis) {
            mTelecomCallId = telecomCallId;
            mHandle = handle;
            mHandlePresentation = handlePresentation;
            mCallerDisplayName = callerDisplayName;
            mCallerDisplayNamePresentation = callerDisplayNamePresentation;
            mAccountHandle = accountHandle;
            mCallCapabilities = capabilities;
            mCallProperties = properties;
            mDisconnectCause = disconnectCause;
            mConnectTimeMillis = connectTimeMillis;
            mGatewayInfo = gatewayInfo;
            mVideoState = videoState;
            mStatusHints = statusHints;
            mExtras = extras;
            mIntentExtras = intentExtras;
            mCreationTimeMillis = creationTimeMillis;
        }

        /** {@hide} */
        public static Details createFromParcelableCall(ParcelableCall parcelableCall) {
            return new Details(
                    parcelableCall.getId(),
                    parcelableCall.getHandle(),
                    parcelableCall.getHandlePresentation(),
                    parcelableCall.getCallerDisplayName(),
                    parcelableCall.getCallerDisplayNamePresentation(),
                    parcelableCall.getAccountHandle(),
                    parcelableCall.getCapabilities(),
                    parcelableCall.getProperties(),
                    parcelableCall.getDisconnectCause(),
                    parcelableCall.getConnectTimeMillis(),
                    parcelableCall.getGatewayInfo(),
                    parcelableCall.getVideoState(),
                    parcelableCall.getStatusHints(),
                    parcelableCall.getExtras(),
                    parcelableCall.getIntentExtras(),
                    parcelableCall.getCreationTimeMillis());
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("[pa: ");
            sb.append(mAccountHandle);
            sb.append(", hdl: ");
            sb.append(Log.pii(mHandle));
            sb.append(", caps: ");
            sb.append(capabilitiesToString(mCallCapabilities));
            sb.append(", props: ");
            sb.append(propertiesToString(mCallProperties));
            sb.append("]");
            return sb.toString();
        }
    }

    /**
     * Defines callbacks which inform the {@link InCallService} of changes to a {@link Call}.
     * These callbacks can originate from the Telecom framework, or a {@link ConnectionService}
     * implementation.
     * <p>
     * You can handle these callbacks by extending the {@link Callback} class and overriding the
     * callbacks that your {@link InCallService} is interested in.  The callback methods include the
     * {@link Call} for which the callback applies, allowing reuse of a single instance of your
     * {@link Callback} implementation, if desired.
     * <p>
     * Use {@link Call#registerCallback(Callback)} to register your callback(s).  Ensure
     * {@link Call#unregisterCallback(Callback)} is called when you no longer require callbacks
     * (typically in {@link InCallService#onCallRemoved(Call)}).
     * Note: Callbacks which occur before you call {@link Call#registerCallback(Callback)} will not
     * reach your implementation of {@link Callback}, so it is important to register your callback
     * as soon as your {@link InCallService} is notified of a new call via
     * {@link InCallService#onCallAdded(Call)}.
     */
    public static abstract class Callback {
        /**
         * @hide
         */
        @IntDef(prefix = { "HANDOVER_" },
                value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
                HANDOVER_FAILURE_UNKNOWN})
        @Retention(RetentionPolicy.SOURCE)
        public @interface HandoverFailureErrors {}

        /**
         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
         * to handover the call to rejects the handover request.
         * <p>
         * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
         * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
         * {@code null} {@link Connection} from
         * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
         * ConnectionRequest)}.
         * <p>
         * For more information on call handovers, see
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
         */
        public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;

        /**
         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
         * is initiated but the source or destination app does not support handover.
         * <p>
         * Will be returned when a handover is requested via
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
         * {@link PhoneAccountHandle} does not declare
         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
         * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
         * {@link Details#getAccountHandle()}) does not declare
         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
         * <p>
         * For more information on call handovers, see
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
         */
        public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;

        /**
         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
         * user rejects the handover request.
         * <p>
         * For more information on call handovers, see
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
         */
        public static final int HANDOVER_FAILURE_USER_REJECTED = 3;

        /**
         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
         * is ongoing emergency call.
         * <p>
         * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
         * called on an emergency call, or if any other call is an emergency call.
         * <p>
         * Handovers are not permitted while there are ongoing emergency calls.
         * <p>
         * For more information on call handovers, see
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
         */
        public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;

        /**
         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
         * fails for an unknown reason.
         * <p>
         * For more information on call handovers, see
         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
         */
        public static final int HANDOVER_FAILURE_UNKNOWN = 5;

        /**
         * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
         *
         * @param call The {@code Call} invoking this method.
         * @param state The new state of the {@code Call}.
         */
        public void onStateChanged(Call call, int state) {}

        /**
         * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
         *
         * @param call The {@code Call} invoking this method.
         * @param parent The new parent of the {@code Call}.
         */
        public void onParentChanged(Call call, Call parent) {}

        /**
         * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
         *
         * @param call The {@code Call} invoking this method.
         * @param children The new children of the {@code Call}.
         */
        public void onChildrenChanged(Call call, List<Call> children) {}

        /**
         * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
         *
         * @param call The {@code Call} invoking this method.
         * @param details A {@code Details} object describing the {@code Call}.
         */
        public void onDetailsChanged(Call call, Details details) {}

        /**
         * Invoked when the text messages that can be used as responses to the incoming
         * {@code Call} are loaded from the relevant database.
         * See {@link #getCannedTextResponses()}.
         *
         * @param call The {@code Call} invoking this method.
         * @param cannedTextResponses The text messages useable as responses.
         */
        public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}

        /**
         * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
         * character. This causes the post-dial signals to stop pending user confirmation. An
         * implementation should present this choice to the user and invoke
         * {@link #postDialContinue(boolean)} when the user makes the choice.
         *
         * @param call The {@code Call} invoking this method.
         * @param remainingPostDialSequence The post-dial characters that remain to be sent.
         */
        public void onPostDialWait(Call call, String remainingPostDialSequence) {}

        /**
         * Invoked when the {@code Call.VideoCall} of the {@code Call} has changed.
         *
         * @param call The {@code Call} invoking this method.
         * @param videoCall The {@code Call.VideoCall} associated with the {@code Call}.
         */
        public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {}

        /**
         * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
         * up their UI for the {@code Call} in response to state transitions. Specifically,
         * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
         * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
         * clients should wait for this method to be invoked.
         *
         * @param call The {@code Call} being destroyed.
         */
        public void onCallDestroyed(Call call) {}

        /**
         * Invoked upon changes to the set of {@code Call}s with which this {@code Call} can be
         * conferenced.
         *
         * @param call The {@code Call} being updated.
         * @param conferenceableCalls The {@code Call}s with which this {@code Call} can be
         *          conferenced.
         */
        public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {}

        /**
         * Invoked when a {@link Call} receives an event from its associated {@link Connection}.
         * <p>
         * Where possible, the Call should make an attempt to handle {@link Connection} events which
         * are part of the {@code android.telecom.*} namespace.  The Call should ignore any events
         * it does not wish to handle.  Unexpected events should be handled gracefully, as it is
         * possible that a {@link ConnectionService} has defined its own Connection events which a
         * Call is not aware of.
         * <p>
         * See {@link Connection#sendConnectionEvent(String, Bundle)}.
         *
         * @param call The {@code Call} receiving the event.
         * @param event The event.
         * @param extras Extras associated with the connection event.
         */
        public void onConnectionEvent(Call call, String event, Bundle extras) {}

        /**
         * Invoked when the RTT mode changes for this call.
         * @param call The call whose RTT mode has changed.
         * @param mode the new RTT mode, one of
         * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
         *             or {@link RttCall#RTT_MODE_VCO}
         */
        public void onRttModeChanged(Call call, int mode) {}

        /**
         * Invoked when the call's RTT status changes, either from off to on or from on to off.
         * @param call The call whose RTT status has changed.
         * @param enabled whether RTT is now enabled or disabled
         * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
         *                on, null otherwise.
         */
        public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}

        /**
         * Invoked when the remote end of the connection has requested that an RTT communication
         * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
         * with the same ID that this method is invoked with.
         * @param call The call which the RTT request was placed on
         * @param id The ID of the request.
         */
        public void onRttRequest(Call call, int id) {}

        /**
         * Invoked when the RTT session failed to initiate for some reason, including rejection
         * by the remote party.
         * @param call The call which the RTT initiation failure occurred on.
         * @param reason One of the status codes defined in
         *               {@link android.telecom.Connection.RttModifyStatus}, with the exception of
         *               {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}.
         */
        public void onRttInitiationFailure(Call call, int reason) {}

        /**
         * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
         * has completed successfully.
         * <p>
         * For a full discussion of the handover process and the APIs involved, see
         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
         *
         * @param call The call which had initiated handover.
         */
        public void onHandoverComplete(Call call) {}

        /**
         * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
         * has failed.
         * <p>
         * For a full discussion of the handover process and the APIs involved, see
         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
         *
         * @param call The call which had initiated handover.
         * @param failureReason Error reason for failure.
         */
        public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
    }

    /**
     * A class that holds the state that describes the state of the RTT channel to the remote
     * party, if it is active.
     */
    public static final class RttCall {
        /** @hide */
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
        public @interface RttAudioMode {}

        /**
         * For metrics use. Default value in the proto.
         * @hide
         */
        public static final int RTT_MODE_INVALID = 0;

        /**
         * Indicates that there should be a bidirectional audio stream between the two parties
         * on the call.
         */
        public static final int RTT_MODE_FULL = 1;

        /**
         * Indicates that the local user should be able to hear the audio stream from the remote
         * user, but not vice versa. Equivalent to muting the microphone.
         */
        public static final int RTT_MODE_HCO = 2;

        /**
         * Indicates that the remote user should be able to hear the audio stream from the local
         * user, but not vice versa. Equivalent to setting the volume to zero.
         */
        public static final int RTT_MODE_VCO = 3;

        private static final int READ_BUFFER_SIZE = 1000;

        private InputStreamReader mReceiveStream;
        private OutputStreamWriter mTransmitStream;
        private int mRttMode;
        private final InCallAdapter mInCallAdapter;
        private final String mTelecomCallId;
        private char[] mReadBuffer = new char[READ_BUFFER_SIZE];

        /**
         * @hide
         */
        public RttCall(String telecomCallId, InputStreamReader receiveStream,
                OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) {
            mTelecomCallId = telecomCallId;
            mReceiveStream = receiveStream;
            mTransmitStream = transmitStream;
            mRttMode = mode;
            mInCallAdapter = inCallAdapter;
        }

        /**
         * Returns the current RTT audio mode.
         * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
         * {@link #RTT_MODE_HCO}.
         */
        public int getRttAudioMode() {
            return mRttMode;
        }

        /**
         * Sets the RTT audio mode. The requested mode change will be communicated through
         * {@link Callback#onRttModeChanged(Call, int)}.
         * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
         * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
         */
        public void setRttMode(@RttAudioMode int mode) {
            mInCallAdapter.setRttMode(mTelecomCallId, mode);
        }

        /**
         * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
         * RTT transmits text in real-time, this method should be called once for each character
         * the user enters into the device.
         *
         * This method is not thread-safe -- calling it from multiple threads simultaneously may
         * lead to interleaved text.
         * @param input The message to send to the remote user.
         */
        public void write(String input) throws IOException {
            mTransmitStream.write(input);
            mTransmitStream.flush();
        }

        /**
         * Reads a string from the remote user, blocking if there is no data available. Returns
         * {@code null} if the RTT conversation has been terminated and there is no further data
         * to read.
         *
         * This method is not thread-safe -- calling it from multiple threads simultaneously may
         * lead to interleaved text.
         * @return A string containing text sent by the remote user, or {@code null} if the
         * conversation has been terminated or if there was an error while reading.
         */
        public String read() {
            try {
                int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
                if (numRead < 0) {
                    return null;
                }
                return new String(mReadBuffer, 0, numRead);
            } catch (IOException e) {
                Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
                return null;
            }
        }

        /**
         * Non-blocking version of {@link #read()}. Returns {@code null} if there is nothing to
         * be read.
         * @return A string containing text entered by the user, or {@code null} if the user has
         * not entered any new text yet.
         */
        public String readImmediately() throws IOException {
            if (mReceiveStream.ready()) {
                int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
                if (numRead < 0) {
                    return null;
                }
                return new String(mReadBuffer, 0, numRead);
            } else {
                return null;
            }
        }

        /**
         * Closes the underlying file descriptors
         * @hide
         */
        public void close() {
            try {
                mReceiveStream.close();
            } catch (IOException e) {
                // ignore
            }
            try {
                mTransmitStream.close();
            } catch (IOException e) {
                // ignore
            }
        }
    }

    /**
     * @deprecated Use {@code Call.Callback} instead.
     * @hide
     */
    @Deprecated
    @SystemApi
    public static abstract class Listener extends Callback { }

    private final Phone mPhone;
    private final String mTelecomCallId;
    private final InCallAdapter mInCallAdapter;
    private final List<String> mChildrenIds = new ArrayList<>();
    private final List<Call> mChildren = new ArrayList<>();
    private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
    private final List<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArrayList<>();
    private final List<Call> mConferenceableCalls = new ArrayList<>();
    private final List<Call> mUnmodifiableConferenceableCalls =
            Collections.unmodifiableList(mConferenceableCalls);

    private boolean mChildrenCached;
    private String mParentId = null;
    private int mState;
    private List<String> mCannedTextResponses = null;
    private String mCallingPackage;
    private int mTargetSdkVersion;
    private String mRemainingPostDialSequence;
    private VideoCallImpl mVideoCallImpl;
    private RttCall mRttCall;
    private Details mDetails;
    private Bundle mExtras;

    /**
     * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
     *
     * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
     * remaining or this {@code Call} is not in a post-dial state.
     */
    public String getRemainingPostDialSequence() {
        return mRemainingPostDialSequence;
    }

    /**
     * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
     * @param videoState The video state in which to answer the call.
     */
    public void answer(@VideoProfile.VideoState int videoState) {
        mInCallAdapter.answerCall(mTelecomCallId, videoState);
    }

    /**
     * Instructs this {@link #STATE_RINGING} {@code Call} to deflect.
     *
     * @param address The address to which the call will be deflected.
     */
    public void deflect(Uri address) {
        mInCallAdapter.deflectCall(mTelecomCallId, address);
    }

    /**
     * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
     *
     * @param rejectWithMessage Whether to reject with a text message.
     * @param textMessage An optional text message with which to respond.
     */
    public void reject(boolean rejectWithMessage, String textMessage) {
        mInCallAdapter.rejectCall(mTelecomCallId, rejectWithMessage, textMessage);
    }

    /**
     * Instructs this {@code Call} to disconnect.
     */
    public void disconnect() {
        mInCallAdapter.disconnectCall(mTelecomCallId);
    }

    /**
     * Instructs this {@code Call} to go on hold.
     */
    public void hold() {
        mInCallAdapter.holdCall(mTelecomCallId);
    }

    /**
     * Instructs this {@link #STATE_HOLDING} call to release from hold.
     */
    public void unhold() {
        mInCallAdapter.unholdCall(mTelecomCallId);
    }

    /**
     * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
     *
     * Any other currently playing DTMF tone in the specified call is immediately stopped.
     *
     * @param digit A character representing the DTMF digit for which to play the tone. This
     *         value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
     */
    public void playDtmfTone(char digit) {
        mInCallAdapter.playDtmfTone(mTelecomCallId, digit);
    }

    /**
     * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
     * currently playing.
     *
     * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
     * currently playing, this method will do nothing.
     */
    public void stopDtmfTone() {
        mInCallAdapter.stopDtmfTone(mTelecomCallId);
    }

    /**
     * Instructs this {@code Call} to continue playing a post-dial DTMF string.
     *
     * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
     * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
     *
     * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_PAUSE} symbol, this
     * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
     *
     * If the DTMF string contains a {@link TelecomManager#DTMF_CHARACTER_WAIT} symbol, this
     * {@code Call} will pause playing the tones and notify callbacks via
     * {@link Callback#onPostDialWait(Call, String)}. At this point, the in-call app
     * should display to the user an indication of this state and an affordance to continue
     * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
     * app should invoke the {@link #postDialContinue(boolean)} method.
     *
     * @param proceed Whether or not to continue with the post-dial sequence.
     */
    public void postDialContinue(boolean proceed) {
        mInCallAdapter.postDialContinue(mTelecomCallId, proceed);
    }

    /**
     * Notifies this {@code Call} that an account has been selected and to proceed with placing
     * an outgoing call. Optionally sets this account as the default account.
     */
    public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
        mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);

    }

    /**
     * Instructs this {@code Call} to enter a conference.
     *
     * @param callToConferenceWith The other call with which to conference.
     */
    public void conference(Call callToConferenceWith) {
        if (callToConferenceWith != null) {
            mInCallAdapter.conference(mTelecomCallId, callToConferenceWith.mTelecomCallId);
        }
    }

    /**
     * Instructs this {@code Call} to split from any conference call with which it may be
     * connected.
     */
    public void splitFromConference() {
        mInCallAdapter.splitFromConference(mTelecomCallId);
    }

    /**
     * Merges the calls within this conference. See {@link Details#CAPABILITY_MERGE_CONFERENCE}.
     */
    public void mergeConference() {
        mInCallAdapter.mergeConference(mTelecomCallId);
    }

    /**
     * Swaps the calls within this conference. See {@link Details#CAPABILITY_SWAP_CONFERENCE}.
     */
    public void swapConference() {
        mInCallAdapter.swapConference(mTelecomCallId);
    }

    /**
     * Initiates a request to the {@link ConnectionService} to pull an external call to the local
     * device.
     * <p>
     * Calls to this method are ignored if the call does not have the
     * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set.
     * <p>
     * An {@link InCallService} will only see calls which support this method if it has the
     * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true}
     * in its manifest.
     */
    public void pullExternalCall() {
        // If this isn't an external call, ignore the request.
        if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) {
            return;
        }

        mInCallAdapter.pullExternalCall(mTelecomCallId);
    }

    /**
     * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in
     * the {@link ConnectionService}.
     * <p>
     * Call events are used to communicate point in time information from an {@link InCallService}
     * to a {@link ConnectionService}.  A {@link ConnectionService} implementation could define
     * events which enable the {@link InCallService}, for example, toggle a unique feature of the
     * {@link ConnectionService}.
     * <p>
     * A {@link ConnectionService} can communicate to the {@link InCallService} using
     * {@link Connection#sendConnectionEvent(String, Bundle)}.
     * <p>
     * Events are exposed to {@link ConnectionService} implementations via
     * {@link android.telecom.Connection#onCallEvent(String, Bundle)}.
     * <p>
     * No assumptions should be made as to how a {@link ConnectionService} will handle these events.
     * The {@link InCallService} must assume that the {@link ConnectionService} could chose to
     * ignore some events altogether.
     * <p>
     * Events should be fully qualified (e.g., {@code com.example.event.MY_EVENT}) to avoid
     * conflicts between {@link InCallService} implementations.  Further, {@link InCallService}
     * implementations shall not re-purpose events in the {@code android.*} namespace, nor shall
     * they define their own event types in this namespace.  When defining a custom event type,
     * ensure the contents of the extras {@link Bundle} is clearly defined.  Extra keys for this
     * bundle should be named similar to the event type (e.g. {@code com.example.extra.MY_EXTRA}).
     * <p>
     * When defining events and the associated extras, it is important to keep their behavior
     * consistent when the associated {@link InCallService} is updated.  Support for deprecated
     * events/extras should me maintained to ensure backwards compatibility with older
     * {@link ConnectionService} implementations which were built to support the older behavior.
     *
     * @param event The connection event.
     * @param extras Bundle containing extra information associated with the event.
     */
    public void sendCallEvent(String event, Bundle extras) {
        mInCallAdapter.sendCallEvent(mTelecomCallId, event, mTargetSdkVersion, extras);
    }

    /**
     * Sends an RTT upgrade request to the remote end of the connection. Success is not
     * guaranteed, and notification of success will be via the
     * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
     */
    public void sendRttRequest() {
        mInCallAdapter.sendRttRequest(mTelecomCallId);
    }

    /**
     * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
     * callback.
     * The ID used here should be the same as the ID that was received via the callback.
     * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
     * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
     */
    public void respondToRttRequest(int id, boolean accept) {
        mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept);
    }

    /**
     * Initiates a handover of this {@link Call} to the {@link ConnectionService} identified
     * by {@code toHandle}.  The videoState specified indicates the desired video state after the
     * handover.
     * <p>
     * A call handover is the process where an ongoing call is transferred from one app (i.e.
     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
     * is referred to as the source of the handover, and the video calling app is referred to as the
     * destination.
     * <p>
     * When considering a handover scenario the device this method is called on is considered the
     * <em>initiating</em> device (since the user initiates the handover from this device), and the
     * other device is considered the <em>receiving</em> device.
     * <p>
     * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
     * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
     * and invoke
     * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
     * ConnectionRequest)} to inform the destination app that a request has been made to handover a
     * call to it.  The app returns an instance of {@link Connection} to represent the handover call
     * At this point the app should display UI to indicate to the user that a call
     * handover is in process.
     * <p>
     * The destination app is responsible for communicating the handover request from the
     * <em>initiating</em> device to the <em>receiving</em> device.
     * <p>
     * When the app on the <em>receiving</em> device receives the handover request, it calls
     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
     * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
     * the destination app on the <em>receiving</em> device should show UI to allow the user to
     * choose whether they want to continue their call in the destination app.
     * <p>
     * When the destination app on the <em>receiving</em> device calls
     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
     * {@link ConnectionService} and call
     * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
     * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
     * {@link Connection} to represent the handover call.
     * <p>
     * If the user of the <em>receiving</em> device accepts the handover, the app calls
     * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
     * original call.  If the user rejects the handover, the app calls
     * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
     * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
     * <p>
     * Telecom will only allow handovers from {@link PhoneAccount}s which declare
     * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
     * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
     * <p>
     * Errors in the handover process are reported to the {@link InCallService} via
     * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
     * the involved {@link ConnectionService}s via
     * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
     *
     * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
     *                 this call to.
     * @param videoState Indicates the video state desired after the handover (see the
     *               {@code STATE_*} constants defined in {@link VideoProfile}).
     * @param extras Bundle containing extra information to be passed to the
     *               {@link ConnectionService}
     */
    public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
            Bundle extras) {
        mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
    }

    /**
     * Terminate the RTT session on this call. The resulting state change will be notified via
     * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
     */
    public void stopRtt() {
        mInCallAdapter.stopRtt(mTelecomCallId);
    }

    /**
     * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
     * added.
     * <p>
     * No assumptions should be made as to how an In-Call UI or service will handle these
     * extras.  Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
     *
     * @param extras The extras to add.
     */
    public final void putExtras(Bundle extras) {
        if (extras == null) {
            return;
        }

        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putAll(extras);
        mInCallAdapter.putExtras(mTelecomCallId, extras);
    }

    /**
     * Adds a boolean extra to this {@link Call}.
     *
     * @param key The extra key.
     * @param value The value.
     * @hide
     */
    public final void putExtra(String key, boolean value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putBoolean(key, value);
        mInCallAdapter.putExtra(mTelecomCallId, key, value);
    }

    /**
     * Adds an integer extra to this {@link Call}.
     *
     * @param key The extra key.
     * @param value The value.
     * @hide
     */
    public final void putExtra(String key, int value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putInt(key, value);
        mInCallAdapter.putExtra(mTelecomCallId, key, value);
    }

    /**
     * Adds a string extra to this {@link Call}.
     *
     * @param key The extra key.
     * @param value The value.
     * @hide
     */
    public final void putExtra(String key, String value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putString(key, value);
        mInCallAdapter.putExtra(mTelecomCallId, key, value);
    }

    /**
     * Removes extras from this {@link Call}.
     *
     * @param keys The keys of the extras to remove.
     */
    public final void removeExtras(List<String> keys) {
        if (mExtras != null) {
            for (String key : keys) {
                mExtras.remove(key);
            }
            if (mExtras.size() == 0) {
                mExtras = null;
            }
        }
        mInCallAdapter.removeExtras(mTelecomCallId, keys);
    }

    /**
     * Removes extras from this {@link Call}.
     *
     * @param keys The keys of the extras to remove.
     */
    public final void removeExtras(String ... keys) {
        removeExtras(Arrays.asList(keys));
    }

    /**
     * Obtains the parent of this {@code Call} in a conference, if any.
     *
     * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
     * child of any conference {@code Call}s.
     */
    public Call getParent() {
        if (mParentId != null) {
            return mPhone.internalGetCallByTelecomId(mParentId);
        }
        return null;
    }

    /**
     * Obtains the children of this conference {@code Call}, if any.
     *
     * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
     * {@code List} otherwise.
     */
    public List<Call> getChildren() {
        if (!mChildrenCached) {
            mChildrenCached = true;
            mChildren.clear();

            for(String id : mChildrenIds) {
                Call call = mPhone.internalGetCallByTelecomId(id);
                if (call == null) {
                    // At least one child was still not found, so do not save true for "cached"
                    mChildrenCached = false;
                } else {
                    mChildren.add(call);
                }
            }
        }

        return mUnmodifiableChildren;
    }

    /**
     * Returns the list of {@code Call}s with which this {@code Call} is allowed to conference.
     *
     * @return The list of conferenceable {@code Call}s.
     */
    public List<Call> getConferenceableCalls() {
        return mUnmodifiableConferenceableCalls;
    }

    /**
     * Obtains the state of this {@code Call}.
     *
     * @return A state value, chosen from the {@code STATE_*} constants.
     */
    public int getState() {
        return mState;
    }

    /**
     * Obtains a list of canned, pre-configured message responses to present to the user as
     * ways of rejecting this {@code Call} using via a text message.
     *
     * @see #reject(boolean, String)
     *
     * @return A list of canned text message responses.
     */
    public List<String> getCannedTextResponses() {
        return mCannedTextResponses;
    }

    /**
     * Obtains an object that can be used to display video from this {@code Call}.
     *
     * @return An {@code Call.VideoCall}.
     */
    public InCallService.VideoCall getVideoCall() {
        return mVideoCallImpl;
    }

    /**
     * Obtains an object containing call details.
     *
     * @return A {@link Details} object. Depending on the state of the {@code Call}, the
     * result may be {@code null}.
     */
    public Details getDetails() {
        return mDetails;
    }

    /**
     * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
     * receive RTT text data, as well as to change the RTT mode.
     * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
     */
    public @Nullable RttCall getRttCall() {
        return mRttCall;
    }

    /**
     * Returns whether this call has an active RTT connection.
     * @return true if there is a connection, false otherwise.
     */
    public boolean isRttActive() {
        return mRttCall != null && mDetails.hasProperty(Details.PROPERTY_RTT);
    }

    /**
     * Registers a callback to this {@code Call}.
     *
     * @param callback A {@code Callback}.
     */
    public void registerCallback(Callback callback) {
        registerCallback(callback, new Handler());
    }

    /**
     * Registers a callback to this {@code Call}.
     *
     * @param callback A {@code Callback}.
     * @param handler A handler which command and status changes will be delivered to.
     */
    public void registerCallback(Callback callback, Handler handler) {
        unregisterCallback(callback);
        // Don't allow new callback registration if the call is already being destroyed.
        if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
            mCallbackRecords.add(new CallbackRecord<Callback>(callback, handler));
        }
    }

    /**
     * Unregisters a callback from this {@code Call}.
     *
     * @param callback A {@code Callback}.
     */
    public void unregisterCallback(Callback callback) {
        // Don't allow callback deregistration if the call is already being destroyed.
        if (callback != null && mState != STATE_DISCONNECTED) {
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                if (record.getCallback() == callback) {
                    mCallbackRecords.remove(record);
                    break;
                }
            }
        }
    }

    @Override
    public String toString() {
        return new StringBuilder().
                append("Call [id: ").
                append(mTelecomCallId).
                append(", state: ").
                append(stateToString(mState)).
                append(", details: ").
                append(mDetails).
                append("]").toString();
    }

    /**
     * @param state An integer value of a {@code STATE_*} constant.
     * @return A string representation of the value.
     */
    private static String stateToString(int state) {
        switch (state) {
            case STATE_NEW:
                return "NEW";
            case STATE_RINGING:
                return "RINGING";
            case STATE_DIALING:
                return "DIALING";
            case STATE_ACTIVE:
                return "ACTIVE";
            case STATE_HOLDING:
                return "HOLDING";
            case STATE_DISCONNECTED:
                return "DISCONNECTED";
            case STATE_CONNECTING:
                return "CONNECTING";
            case STATE_DISCONNECTING:
                return "DISCONNECTING";
            case STATE_SELECT_PHONE_ACCOUNT:
                return "SELECT_PHONE_ACCOUNT";
            default:
                Log.w(Call.class, "Unknown state %d", state);
                return "UNKNOWN";
        }
    }

    /**
     * Adds a listener to this {@code Call}.
     *
     * @param listener A {@code Listener}.
     * @deprecated Use {@link #registerCallback} instead.
     * @hide
     */
    @Deprecated
    @SystemApi
    public void addListener(Listener listener) {
        registerCallback(listener);
    }

    /**
     * Removes a listener from this {@code Call}.
     *
     * @param listener A {@code Listener}.
     * @deprecated Use {@link #unregisterCallback} instead.
     * @hide
     */
    @Deprecated
    @SystemApi
    public void removeListener(Listener listener) {
        unregisterCallback(listener);
    }

    /** {@hide} */
    Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage,
         int targetSdkVersion) {
        mPhone = phone;
        mTelecomCallId = telecomCallId;
        mInCallAdapter = inCallAdapter;
        mState = STATE_NEW;
        mCallingPackage = callingPackage;
        mTargetSdkVersion = targetSdkVersion;
    }

    /** {@hide} */
    Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
            String callingPackage, int targetSdkVersion) {
        mPhone = phone;
        mTelecomCallId = telecomCallId;
        mInCallAdapter = inCallAdapter;
        mState = state;
        mCallingPackage = callingPackage;
        mTargetSdkVersion = targetSdkVersion;
    }

    /** {@hide} */
    final String internalGetCallId() {
        return mTelecomCallId;
    }

    /** {@hide} */
    final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {

        // First, we update the internal state as far as possible before firing any updates.
        Details details = Details.createFromParcelableCall(parcelableCall);
        boolean detailsChanged = !Objects.equals(mDetails, details);
        if (detailsChanged) {
            mDetails = details;
        }

        boolean cannedTextResponsesChanged = false;
        if (mCannedTextResponses == null && parcelableCall.getCannedSmsResponses() != null
                && !parcelableCall.getCannedSmsResponses().isEmpty()) {
            mCannedTextResponses =
                    Collections.unmodifiableList(parcelableCall.getCannedSmsResponses());
            cannedTextResponsesChanged = true;
        }

        VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage,
                mTargetSdkVersion);
        boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
                !Objects.equals(mVideoCallImpl, newVideoCallImpl);
        if (videoCallChanged) {
            mVideoCallImpl = newVideoCallImpl;
        }
        if (mVideoCallImpl != null) {
            mVideoCallImpl.setVideoState(getDetails().getVideoState());
        }

        int state = parcelableCall.getState();
        boolean stateChanged = mState != state;
        if (stateChanged) {
            mState = state;
        }

        String parentId = parcelableCall.getParentCallId();
        boolean parentChanged = !Objects.equals(mParentId, parentId);
        if (parentChanged) {
            mParentId = parentId;
        }

        List<String> childCallIds = parcelableCall.getChildCallIds();
        boolean childrenChanged = !Objects.equals(childCallIds, mChildrenIds);
        if (childrenChanged) {
            mChildrenIds.clear();
            mChildrenIds.addAll(parcelableCall.getChildCallIds());
            mChildrenCached = false;
        }

        List<String> conferenceableCallIds = parcelableCall.getConferenceableCallIds();
        List<Call> conferenceableCalls = new ArrayList<Call>(conferenceableCallIds.size());
        for (String otherId : conferenceableCallIds) {
            if (callIdMap.containsKey(otherId)) {
                conferenceableCalls.add(callIdMap.get(otherId));
            }
        }

        if (!Objects.equals(mConferenceableCalls, conferenceableCalls)) {
            mConferenceableCalls.clear();
            mConferenceableCalls.addAll(conferenceableCalls);
            fireConferenceableCallsChanged();
        }

        boolean isRttChanged = false;
        boolean rttModeChanged = false;
        if (parcelableCall.getIsRttCallChanged()
                && mDetails.hasProperty(Details.PROPERTY_RTT)) {
            ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
            InputStreamReader receiveStream = new InputStreamReader(
                    new ParcelFileDescriptor.AutoCloseInputStream(
                            parcelableRttCall.getReceiveStream()),
                    StandardCharsets.UTF_8);
            OutputStreamWriter transmitStream = new OutputStreamWriter(
                    new ParcelFileDescriptor.AutoCloseOutputStream(
                            parcelableRttCall.getTransmitStream()),
                    StandardCharsets.UTF_8);
            RttCall newRttCall = new Call.RttCall(mTelecomCallId,
                    receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
            if (mRttCall == null) {
                isRttChanged = true;
            } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
                rttModeChanged = true;
            }
            mRttCall = newRttCall;
        } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
                && parcelableCall.getIsRttCallChanged()) {
            isRttChanged = true;
            mRttCall = null;
        }

        // Now we fire updates, ensuring that any client who listens to any of these notifications
        // gets the most up-to-date state.

        if (stateChanged) {
            fireStateChanged(mState);
        }
        if (detailsChanged) {
            fireDetailsChanged(mDetails);
        }
        if (cannedTextResponsesChanged) {
            fireCannedTextResponsesLoaded(mCannedTextResponses);
        }
        if (videoCallChanged) {
            fireVideoCallChanged(mVideoCallImpl);
        }
        if (parentChanged) {
            fireParentChanged(getParent());
        }
        if (childrenChanged) {
            fireChildrenChanged(getChildren());
        }
        if (isRttChanged) {
            fireOnIsRttChanged(mRttCall != null, mRttCall);
        }
        if (rttModeChanged) {
            fireOnRttModeChanged(mRttCall.getRttAudioMode());
        }

        // If we have transitioned to DISCONNECTED, that means we need to notify clients and
        // remove ourselves from the Phone. Note that we do this after completing all state updates
        // so a client can cleanly transition all their UI to the state appropriate for a
        // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
        if (mState == STATE_DISCONNECTED) {
            fireCallDestroyed();
        }
    }

    /** {@hide} */
    final void internalSetPostDialWait(String remaining) {
        mRemainingPostDialSequence = remaining;
        firePostDialWait(mRemainingPostDialSequence);
    }

    /** {@hide} */
    final void internalSetDisconnected() {
        if (mState != Call.STATE_DISCONNECTED) {
            mState = Call.STATE_DISCONNECTED;
            fireStateChanged(mState);
            fireCallDestroyed();
        }
    }

    /** {@hide} */
    final void internalOnConnectionEvent(String event, Bundle extras) {
        fireOnConnectionEvent(event, extras);
    }

    /** {@hide} */
    final void internalOnRttUpgradeRequest(final int requestId) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttRequest(call, requestId));
        }
    }

    /** @hide */
    final void internalOnRttInitiationFailure(int reason) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason));
        }
    }

    /** {@hide} */
    final void internalOnHandoverFailed(int error) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onHandoverFailed(call, error));
        }
    }

    /** {@hide} */
    final void internalOnHandoverComplete() {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onHandoverComplete(call));
        }
    }

    private void fireStateChanged(final int newState) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onStateChanged(call, newState);
                }
            });
        }
    }

    private void fireParentChanged(final Call newParent) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onParentChanged(call, newParent);
                }
            });
        }
    }

    private void fireChildrenChanged(final List<Call> children) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onChildrenChanged(call, children);
                }
            });
        }
    }

    private void fireDetailsChanged(final Details details) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onDetailsChanged(call, details);
                }
            });
        }
    }

    private void fireCannedTextResponsesLoaded(final List<String> cannedTextResponses) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onCannedTextResponsesLoaded(call, cannedTextResponses);
                }
            });
        }
    }

    private void fireVideoCallChanged(final InCallService.VideoCall videoCall) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onVideoCallChanged(call, videoCall);
                }
            });
        }
    }

    private void firePostDialWait(final String remainingPostDialSequence) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onPostDialWait(call, remainingPostDialSequence);
                }
            });
        }
    }

    private void fireCallDestroyed() {
        /**
         * To preserve the ordering of the Call's onCallDestroyed callback and Phone's
         * onCallRemoved callback, we remove this call from the Phone's record
         * only once all of the registered onCallDestroyed callbacks are executed.
         * All the callbacks get removed from our records as a part of this operation
         * since onCallDestroyed is the final callback.
         */
        final Call call = this;
        if (mCallbackRecords.isEmpty()) {
            // No callbacks registered, remove the call from Phone's record.
            mPhone.internalRemoveCall(call);
        }
        for (final CallbackRecord<Callback> record : mCallbackRecords) {
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    boolean isFinalRemoval = false;
                    RuntimeException toThrow = null;
                    try {
                        callback.onCallDestroyed(call);
                    } catch (RuntimeException e) {
                            toThrow = e;
                    }
                    synchronized(Call.this) {
                        mCallbackRecords.remove(record);
                        if (mCallbackRecords.isEmpty()) {
                            isFinalRemoval = true;
                        }
                    }
                    if (isFinalRemoval) {
                        mPhone.internalRemoveCall(call);
                    }
                    if (toThrow != null) {
                        throw toThrow;
                    }
                }
            });
        }
    }

    private void fireConferenceableCallsChanged() {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onConferenceableCallsChanged(call, mUnmodifiableConferenceableCalls);
                }
            });
        }
    }

    /**
     * Notifies listeners of an incoming connection event.
     * <p>
     * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}.
     *
     * @param event
     * @param extras
     */
    private void fireOnConnectionEvent(final String event, final Bundle extras) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onConnectionEvent(call, event, extras);
                }
            });
        }
    }

    /**
     * Notifies listeners of an RTT on/off change
     *
     * @param enabled True if RTT is now enabled, false otherwise
     */
    private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
        }
    }

    /**
     * Notifies listeners of a RTT mode change
     *
     * @param mode The new RTT mode
     */
    private void fireOnRttModeChanged(final int mode) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
        }
    }

    /**
     * Determines if two bundles are equal.
     *
     * @param bundle The original bundle.
     * @param newBundle The bundle to compare with.
     * @retrun {@code true} if the bundles are equal, {@code false} otherwise.
     */
    private static boolean areBundlesEqual(Bundle bundle, Bundle newBundle) {
        if (bundle == null || newBundle == null) {
            return bundle == newBundle;
        }

        if (bundle.size() != newBundle.size()) {
            return false;
        }

        for(String key : bundle.keySet()) {
            if (key != null) {
                final Object value = bundle.get(key);
                final Object newValue = newBundle.get(key);
                if (!Objects.equals(value, newValue)) {
                    return false;
                }
            }
        }
        return true;
    }
}
