/*
 * Copyright (c) 2013 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 com.android.ims;

import com.android.internal.R;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.os.Parcel;
import android.telecom.ConferenceParticipant;
import android.telecom.Connection;
import android.telephony.Rlog;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

import android.telephony.ServiceState;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsConferenceState;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.ImsSuppServiceNotification;
import android.util.Log;

import com.android.ims.internal.ICall;
import android.telephony.ims.ImsCallSession;
import com.android.ims.internal.ImsStreamMediaSession;
import com.android.internal.annotations.VisibleForTesting;

/**
 * Handles an IMS voice / video call over LTE. You can instantiate this class with
 * {@link ImsManager}.
 *
 * @hide
 */
public class ImsCall implements ICall {
    // Mode of USSD message
    public static final int USSD_MODE_NOTIFY = 0;
    public static final int USSD_MODE_REQUEST = 1;

    private static final String TAG = "ImsCall";

    // This flag is meant to be used as a debugging tool to quickly see all logs
    // regardless of the actual log level set on this component.
    private static final boolean FORCE_DEBUG = false; /* STOPSHIP if true */

    // We will log messages guarded by these flags at the info level. If logging is required
    // to occur at (and only at) a particular log level, please use the logd, logv and loge
    // functions as those will not be affected by the value of FORCE_DEBUG at all.
    // Otherwise, anything guarded by these flags will be logged at the info level since that
    // level allows those statements ot be logged by default which supports the workflow of
    // setting FORCE_DEBUG and knowing these logs will show up regardless of the actual log
    // level of this component.
    private static final boolean DBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.DEBUG);
    private static final boolean VDBG = FORCE_DEBUG || Log.isLoggable(TAG, Log.VERBOSE);
    // This is a special flag that is used only to highlight specific log around bringing
    // up and tearing down conference calls. At times, these errors are transient and hard to
    // reproduce so we need to capture this information the first time.
    // TODO: Set this flag to FORCE_DEBUG once the new conference call logic gets more mileage
    // across different IMS implementations.
    private static final boolean CONF_DBG = true;

    private List<ConferenceParticipant> mConferenceParticipants;
    /**
     * Listener for events relating to an IMS call, such as when a call is being
     * received ("on ringing") or a call is outgoing ("on calling").
     * <p>Many of these events are also received by {@link ImsCallSession.Listener}.</p>
     */
    public static class Listener {
        /**
         * Called when a request is sent out to initiate a new call
         * and 1xx response is received from the network.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallProgressing(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call is established.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallStarted(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call setup is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call setup failure
         */
        public void onCallStartFailed(ImsCall call, ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the call is terminated.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call termination
         */
        public void onCallTerminated(ImsCall call, ImsReasonInfo reasonInfo) {
            // Store the call termination reason

            onCallStateChanged(call);
        }

        /**
         * Called when the call is in hold.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallHeld(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call hold is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call hold failure
         */
        public void onCallHoldFailed(ImsCall call, ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the call hold is received from the remote user.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallHoldReceived(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call is in call.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallResumed(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call resume is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call resume failure
         */
        public void onCallResumeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the call resume is received from the remote user.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallResumeReceived(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call is in call.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the active IMS call
         * @param peerCall the call object that carries out the held IMS call
         * @param swapCalls {@code true} if the foreground and background calls should be swapped
         *                              now that the merge has completed.
         */
        public void onCallMerged(ImsCall call, ImsCall peerCall, boolean swapCalls) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call merge is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call merge failure
         */
        public void onCallMergeFailed(ImsCall call, ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the call is updated (except for hold/unhold).
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallUpdated(ImsCall call) {
            onCallStateChanged(call);
        }

        /**
         * Called when the call update is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the call update failure
         */
        public void onCallUpdateFailed(ImsCall call, ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the call update is received from the remote user.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallUpdateReceived(ImsCall call) {
            // no-op
        }

        /**
         * Called when the call is extended to the conference call.
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         * @param newCall the call object that is extended to the conference from the active call
         */
        public void onCallConferenceExtended(ImsCall call, ImsCall newCall) {
            onCallStateChanged(call);
        }

        /**
         * Called when the conference extension is failed.
         * The default implementation calls {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the conference extension failure
         */
        public void onCallConferenceExtendFailed(ImsCall call,
                ImsReasonInfo reasonInfo) {
            onCallError(call, reasonInfo);
        }

        /**
         * Called when the conference extension is received from the remote user.
         *
         * @param call the call object that carries out the IMS call
         * @param newCall the call object that is extended to the conference from the active call
         */
        public void onCallConferenceExtendReceived(ImsCall call, ImsCall newCall) {
            onCallStateChanged(call);
        }

        /**
         * Called when the invitation request of the participants is delivered to
         * the conference server.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallInviteParticipantsRequestDelivered(ImsCall call) {
            // no-op
        }

        /**
         * Called when the invitation request of the participants is failed.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the conference invitation failure
         */
        public void onCallInviteParticipantsRequestFailed(ImsCall call,
                ImsReasonInfo reasonInfo) {
            // no-op
        }

        /**
         * Called when the removal request of the participants is delivered to
         * the conference server.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallRemoveParticipantsRequestDelivered(ImsCall call) {
            // no-op
        }

        /**
         * Called when the removal request of the participants is failed.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of the conference removal failure
         */
        public void onCallRemoveParticipantsRequestFailed(ImsCall call,
                ImsReasonInfo reasonInfo) {
            // no-op
        }

        /**
         * Called when the conference state is updated.
         *
         * @param call the call object that carries out the IMS call
         * @param state state of the participant who is participated in the conference call
         */
        public void onCallConferenceStateUpdated(ImsCall call, ImsConferenceState state) {
            // no-op
        }

        /**
         * Called when the state of IMS conference participant(s) has changed.
         *
         * @param call the call object that carries out the IMS call.
         * @param participants the participant(s) and their new state information.
         */
        public void onConferenceParticipantsStateChanged(ImsCall call,
                List<ConferenceParticipant> participants) {
            // no-op
        }

        /**
         * Called when the USSD message is received from the network.
         *
         * @param mode mode of the USSD message (REQUEST / NOTIFY)
         * @param ussdMessage USSD message
         */
        public void onCallUssdMessageReceived(ImsCall call,
                int mode, String ussdMessage) {
            // no-op
        }

        /**
         * Called when an error occurs. The default implementation is no op.
         * overridden. The default implementation is no op. Error events are
         * not re-directed to this callback and are handled in {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         * @param reasonInfo detailed reason of this error
         * @see ImsReasonInfo
         */
        public void onCallError(ImsCall call, ImsReasonInfo reasonInfo) {
            // no-op
        }

        /**
         * Called when an event occurs and the corresponding callback is not
         * overridden. The default implementation is no op. Error events are
         * not re-directed to this callback and are handled in {@link #onCallError}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallStateChanged(ImsCall call) {
            // no-op
        }

        /**
         * Called when the call moves the hold state to the conversation state.
         * For example, when merging the active & hold call, the state of all the hold call
         * will be changed from hold state to conversation state.
         * This callback method can be invoked even though the application does not trigger
         * any operations.
         *
         * @param call the call object that carries out the IMS call
         * @param state the detailed state of call state changes;
         *      Refer to CALL_STATE_* in {@link ImsCall}
         */
        public void onCallStateChanged(ImsCall call, int state) {
            // no-op
        }

        /**
         * Called when the call supp service is received
         * The default implementation calls {@link #onCallStateChanged}.
         *
         * @param call the call object that carries out the IMS call
         */
        public void onCallSuppServiceReceived(ImsCall call,
            ImsSuppServiceNotification suppServiceInfo) {
        }

        /**
         * Called when TTY mode of remote party changed
         *
         * @param call the call object that carries out the IMS call
         * @param mode TTY mode of remote party
         */
        public void onCallSessionTtyModeReceived(ImsCall call, int mode) {
            // no-op
        }

        /**
         * Called when handover occurs from one access technology to another.
         *
         * @param imsCall ImsCall object
         * @param srcAccessTech original access technology
         * @param targetAccessTech new access technology
         * @param reasonInfo
         */
        public void onCallHandover(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
            ImsReasonInfo reasonInfo) {
        }

        /**
         * Called when the remote party issues an RTT modify request
         *
         * @param imsCall ImsCall object
         */
        public void onRttModifyRequestReceived(ImsCall imsCall) {
        }

        /**
         * Called when the remote party responds to a locally-issued RTT request.
         *
         * @param imsCall ImsCall object
         * @param status The status of the request. See
         *               {@link Connection.RttModifyStatus} for possible values.
         */
        public void onRttModifyResponseReceived(ImsCall imsCall, int status) {
        }

        /**
         * Called when the remote party has sent some characters via RTT
         *
         * @param imsCall ImsCall object
         * @param message A string containing the transmitted characters.
         */
        public void onRttMessageReceived(ImsCall imsCall, String message) {
        }

        /**
         * Called when handover from one access technology to another fails.
         *
         * @param imsCall call that failed the handover.
         * @param srcAccessTech original access technology
         * @param targetAccessTech new access technology
         * @param reasonInfo
         */
        public void onCallHandoverFailed(ImsCall imsCall, int srcAccessTech, int targetAccessTech,
            ImsReasonInfo reasonInfo) {
        }

        /**
         * Notifies of a change to the multiparty state for this {@code ImsCall}.
         *
         * @param imsCall The IMS call.
         * @param isMultiParty {@code true} if the call became multiparty, {@code false}
         *      otherwise.
         */
        public void onMultipartyStateChanged(ImsCall imsCall, boolean isMultiParty) {
        }

        /**
         * Called when rtt call audio indicator has changed.
         *
         * @param imsCall ImsCall object
         * @param profile updated ImsStreamMediaProfile profile.
         */
        public void onRttAudioIndicatorChanged(ImsCall imsCall, ImsStreamMediaProfile profile) {
        }
    }

    // List of update operation for IMS call control
    private static final int UPDATE_NONE = 0;
    private static final int UPDATE_HOLD = 1;
    private static final int UPDATE_HOLD_MERGE = 2;
    private static final int UPDATE_RESUME = 3;
    private static final int UPDATE_MERGE = 4;
    private static final int UPDATE_EXTEND_TO_CONFERENCE = 5;
    private static final int UPDATE_UNSPECIFIED = 6;

    // For synchronization of private variables
    private Object mLockObj = new Object();
    private Context mContext;

    // true if the call is established & in the conversation state
    private boolean mInCall = false;
    // true if the call is on hold
    // If it is triggered by the local, mute the call. Otherwise, play local hold tone
    // or network generated media.
    private boolean mHold = false;
    // true if the call is on mute
    private boolean mMute = false;
    // It contains the exclusive call update request. Refer to UPDATE_*.
    private int mUpdateRequest = UPDATE_NONE;

    private ImsCall.Listener mListener = null;

    // When merging two calls together, the "peer" call that will merge into this call.
    private ImsCall mMergePeer = null;
    // When merging two calls together, the "host" call we are merging into.
    private ImsCall mMergeHost = null;

    // True if Conference request was initiated by
    // Foreground Conference call else it will be false
    private boolean mMergeRequestedByConference = false;
    // Wrapper call session to interworking the IMS service (server).
    private ImsCallSession mSession = null;
    // Call profile of the current session.
    // It can be changed at anytime when the call is updated.
    private ImsCallProfile mCallProfile = null;
    // Call profile to be updated after the application's action (accept/reject)
    // to the call update. After the application's action (accept/reject) is done,
    // it will be set to null.
    private ImsCallProfile mProposedCallProfile = null;
    private ImsReasonInfo mLastReasonInfo = null;

    // Media session to control media (audio/video) operations for an IMS call
    private ImsStreamMediaSession mMediaSession = null;

    // The temporary ImsCallSession that could represent the merged call once
    // we receive notification that the merge was successful.
    private ImsCallSession mTransientConferenceSession = null;
    // While a merge is progressing, we bury any session termination requests
    // made on the original ImsCallSession until we have closure on the merge request
    // If the request ultimately fails, we need to act on the termination request
    // that we buried temporarily. We do this because we feel that timing issues could
    // cause the termination request to occur just because the merge is succeeding.
    private boolean mSessionEndDuringMerge = false;
    // Just like mSessionEndDuringMerge, we need to keep track of the reason why the
    // termination request was made on the original session in case we need to act
    // on it in the case of a merge failure.
    private ImsReasonInfo mSessionEndDuringMergeReasonInfo = null;
    // This flag is used to indicate if this ImsCall was merged into a conference
    // or not.  It is used primarily to determine if a disconnect sound should
    // be heard when the call is terminated.
    private boolean mIsMerged = false;
    // If true, this flag means that this ImsCall is in the process of merging
    // into a conference but it does not yet have closure on if it was
    // actually added to the conference or not. false implies that it either
    // is not part of a merging conference or already knows if it was
    // successfully added.
    private boolean mCallSessionMergePending = false;

    /**
     * If {@code true}, this flag indicates that a request to terminate the call was made by
     * Telephony (could be from the user or some internal telephony logic)
     * and that when we receive a {@link #processCallTerminated(ImsReasonInfo)} callback from the
     * radio indicating that the call was terminated, we should override any burying of the
     * termination due to an ongoing conference merge.
     */
    private boolean mTerminationRequestPending = false;

    /**
     * For multi-party IMS calls (e.g. conferences), determines if this {@link ImsCall} is the one
     * hosting the call.  This is used to distinguish between a situation where an {@link ImsCall}
     * is {@link #isMultiparty()} because calls were merged on the device, and a situation where
     * an {@link ImsCall} is {@link #isMultiparty()} because it is a member of a conference started
     * on another device.
     * <p>
     * When {@code true}, this {@link ImsCall} is is the origin of the conference call.
     * When {@code false}, this {@link ImsCall} is a member of a conference started on another
     * device.
     */
    private boolean mIsConferenceHost = false;

    /**
     * Tracks whether this {@link ImsCall} has been a video call at any point in its lifetime.
     * Some examples of calls which are/were video calls:
     * 1. A call which has been a video call for its duration.
     * 2. An audio call upgraded to video (and potentially downgraded to audio later).
     * 3. A call answered as video which was downgraded to audio.
     */
    private boolean mWasVideoCall = false;

    /**
     * Unique id generator used to generate call id.
     */
    private static final AtomicInteger sUniqueIdGenerator = new AtomicInteger();

    /**
     * Unique identifier.
     */
    public final int uniqueId;

    /**
     * The current ImsCallSessionListenerProxy.
     */
    private ImsCallSessionListenerProxy mImsCallSessionListenerProxy;

    /**
     * When calling {@link #terminate(int, int)}, an override for the termination reason which the
     * modem returns.
     *
     * Necessary because passing in an unexpected {@link ImsReasonInfo} reason code to
     * {@link #terminate(int)} will cause the modem to ignore the terminate request.
     */
    private int mOverrideReason = ImsReasonInfo.CODE_UNSPECIFIED;

    /**
     * When true, if this call is incoming, it will be answered with an
     * {@link ImsStreamMediaProfile} that has RTT enabled.
     */
    private boolean mAnswerWithRtt = false;

    /**
     * Create an IMS call object.
     *
     * @param context the context for accessing system services
     * @param profile the call profile to make/take a call
     */
    public ImsCall(Context context, ImsCallProfile profile) {
        mContext = context;
        setCallProfile(profile);
        uniqueId = sUniqueIdGenerator.getAndIncrement();
    }

    /**
     * Closes this object. This object is not usable after being closed.
     */
    @Override
    public void close() {
        synchronized(mLockObj) {
            if (mSession != null) {
                mSession.close();
                mSession = null;
            } else {
                logi("close :: Cannot close Null call session!");
            }

            mCallProfile = null;
            mProposedCallProfile = null;
            mLastReasonInfo = null;
            mMediaSession = null;
        }
    }

    /**
     * Checks if the call has a same remote user identity or not.
     *
     * @param userId the remote user identity
     * @return true if the remote user identity is equal; otherwise, false
     */
    @Override
    public boolean checkIfRemoteUserIsSame(String userId) {
        if (userId == null) {
            return false;
        }

        return userId.equals(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_REMOTE_URI, ""));
    }

    /**
     * Checks if the call is equal or not.
     *
     * @param call the call to be compared
     * @return true if the call is equal; otherwise, false
     */
    @Override
    public boolean equalsTo(ICall call) {
        if (call == null) {
            return false;
        }

        if (call instanceof ImsCall) {
            return this.equals(call);
        }

        return false;
    }

    public static boolean isSessionAlive(ImsCallSession session) {
        return session != null && session.isAlive();
    }

    /**
     * Gets the negotiated (local & remote) call profile.
     *
     * @return a {@link ImsCallProfile} object that has the negotiated call profile
     */
    public ImsCallProfile getCallProfile() {
        synchronized(mLockObj) {
            return mCallProfile;
        }
    }

    /**
     * Replaces the current call profile with a new one, tracking whethere this was previously a
     * video call or not.
     *
     * @param profile The new call profile.
     */
    @VisibleForTesting
    public void setCallProfile(ImsCallProfile profile) {
        synchronized(mLockObj) {
            mCallProfile = profile;
            trackVideoStateHistory(mCallProfile);
        }
    }

    /**
     * Gets the local call profile (local capabilities).
     *
     * @return a {@link ImsCallProfile} object that has the local call profile
     */
    public ImsCallProfile getLocalCallProfile() throws ImsException {
        synchronized(mLockObj) {
            if (mSession == null) {
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            try {
                return mSession.getLocalCallProfile();
            } catch (Throwable t) {
                loge("getLocalCallProfile :: ", t);
                throw new ImsException("getLocalCallProfile()", t, 0);
            }
        }
    }

    /**
     * Gets the remote call profile (remote capabilities).
     *
     * @return a {@link ImsCallProfile} object that has the remote call profile
     */
    public ImsCallProfile getRemoteCallProfile() throws ImsException {
        synchronized(mLockObj) {
            if (mSession == null) {
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            try {
                return mSession.getRemoteCallProfile();
            } catch (Throwable t) {
                loge("getRemoteCallProfile :: ", t);
                throw new ImsException("getRemoteCallProfile()", t, 0);
            }
        }
    }

    /**
     * Gets the call profile proposed by the local/remote user.
     *
     * @return a {@link ImsCallProfile} object that has the proposed call profile
     */
    public ImsCallProfile getProposedCallProfile() {
        synchronized(mLockObj) {
            if (!isInCall()) {
                return null;
            }

            return mProposedCallProfile;
        }
    }

    /**
     * Gets the list of conference participants currently
     * associated with this call.
     *
     * @return Copy of the list of conference participants.
     */
    public List<ConferenceParticipant> getConferenceParticipants() {
        synchronized(mLockObj) {
            logi("getConferenceParticipants :: mConferenceParticipants"
                    + mConferenceParticipants);
            if (mConferenceParticipants == null) {
                return null;
            }
            if (mConferenceParticipants.isEmpty()) {
                return new ArrayList<ConferenceParticipant>(0);
            }
            return new ArrayList<ConferenceParticipant>(mConferenceParticipants);
        }
    }

    /**
     * Gets the state of the {@link ImsCallSession} that carries this call.
     * The value returned must be one of the states in {@link ImsCallSession#State}.
     *
     * @return the session state
     */
    public int getState() {
        synchronized(mLockObj) {
            if (mSession == null) {
                return ImsCallSession.State.IDLE;
            }

            return mSession.getState();
        }
    }

    /**
     * Gets the {@link ImsCallSession} that carries this call.
     *
     * @return the session object that carries this call
     * @hide
     */
    public ImsCallSession getCallSession() {
        synchronized(mLockObj) {
            return mSession;
        }
    }

    /**
     * Gets the {@link ImsStreamMediaSession} that handles the media operation of this call.
     * Almost interface APIs are for the VT (Video Telephony).
     *
     * @return the media session object that handles the media operation of this call
     * @hide
     */
    public ImsStreamMediaSession getMediaSession() {
        synchronized(mLockObj) {
            return mMediaSession;
        }
    }

    /**
     * Gets the specified property of this call.
     *
     * @param name key to get the extra call information defined in {@link ImsCallProfile}
     * @return the extra call information as string
     */
    public String getCallExtra(String name) throws ImsException {
        // Lookup the cache

        synchronized(mLockObj) {
            // If not found, try to get the property from the remote
            if (mSession == null) {
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            try {
                return mSession.getProperty(name);
            } catch (Throwable t) {
                loge("getCallExtra :: ", t);
                throw new ImsException("getCallExtra()", t, 0);
            }
        }
    }

    /**
     * Gets the last reason information when the call is not established, cancelled or terminated.
     *
     * @return the last reason information
     */
    public ImsReasonInfo getLastReasonInfo() {
        synchronized(mLockObj) {
            return mLastReasonInfo;
        }
    }

    /**
     * Checks if the call has a pending update operation.
     *
     * @return true if the call has a pending update operation
     */
    public boolean hasPendingUpdate() {
        synchronized(mLockObj) {
            return (mUpdateRequest != UPDATE_NONE);
        }
    }

    /**
     * Checks if the call is pending a hold operation.
     *
     * @return true if the call is pending a hold operation.
     */
    public boolean isPendingHold() {
        synchronized(mLockObj) {
            return (mUpdateRequest == UPDATE_HOLD);
        }
    }

    /**
     * Checks if the call is established.
     *
     * @return true if the call is established
     */
    public boolean isInCall() {
        synchronized(mLockObj) {
            return mInCall;
        }
    }

    /**
     * Checks if the call is muted.
     *
     * @return true if the call is muted
     */
    public boolean isMuted() {
        synchronized(mLockObj) {
            return mMute;
        }
    }

    /**
     * Checks if the call is on hold.
     *
     * @return true if the call is on hold
     */
    public boolean isOnHold() {
        synchronized(mLockObj) {
            return mHold;
        }
    }

    /**
     * Determines if the call is a multiparty call.
     *
     * @return {@code True} if the call is a multiparty call.
     */
    public boolean isMultiparty() {
        synchronized(mLockObj) {
            if (mSession == null) {
                return false;
            }

            return mSession.isMultiparty();
        }
    }

    /**
     * Where {@link #isMultiparty()} is {@code true}, determines if this {@link ImsCall} is the
     * origin of the conference call (i.e. {@code #isConferenceHost()} is {@code true}), or if this
     * {@link ImsCall} is a member of a conference hosted on another device.
     *
     * @return {@code true} if this call is the origin of the conference call it is a member of,
     *      {@code false} otherwise.
     */
    public boolean isConferenceHost() {
        synchronized(mLockObj) {
            return isMultiparty() && mIsConferenceHost;
        }
    }

    /**
     * Marks whether an IMS call is merged. This should be set {@code true} when the call merges
     * into a conference.
     *
     * @param isMerged Whether the call is merged.
     */
    public void setIsMerged(boolean isMerged) {
        mIsMerged = isMerged;
    }

    /**
     * @return {@code true} if the call recently merged into a conference call.
     */
    public boolean isMerged() {
        return mIsMerged;
    }

    /**
     * Sets the listener to listen to the IMS call events.
     * The method calls {@link #setListener setListener(listener, false)}.
     *
     * @param listener to listen to the IMS call events of this object; null to remove listener
     * @see #setListener(Listener, boolean)
     */
    public void setListener(ImsCall.Listener listener) {
        setListener(listener, false);
    }

    /**
     * Sets the listener to listen to the IMS call events.
     * A {@link ImsCall} can only hold one listener at a time. Subsequent calls
     * to this method override the previous listener.
     *
     * @param listener to listen to the IMS call events of this object; null to remove listener
     * @param callbackImmediately set to true if the caller wants to be called
     *        back immediately on the current state
     */
    public void setListener(ImsCall.Listener listener, boolean callbackImmediately) {
        boolean inCall;
        boolean onHold;
        int state;
        ImsReasonInfo lastReasonInfo;

        synchronized(mLockObj) {
            mListener = listener;

            if ((listener == null) || !callbackImmediately) {
                return;
            }

            inCall = mInCall;
            onHold = mHold;
            state = getState();
            lastReasonInfo = mLastReasonInfo;
        }

        try {
            if (lastReasonInfo != null) {
                listener.onCallError(this, lastReasonInfo);
            } else if (inCall) {
                if (onHold) {
                    listener.onCallHeld(this);
                } else {
                    listener.onCallStarted(this);
                }
            } else {
                switch (state) {
                    case ImsCallSession.State.ESTABLISHING:
                        listener.onCallProgressing(this);
                        break;
                    case ImsCallSession.State.TERMINATED:
                        listener.onCallTerminated(this, lastReasonInfo);
                        break;
                    default:
                        // Ignore it. There is no action in the other state.
                        break;
                }
            }
        } catch (Throwable t) {
            loge("setListener() :: ", t);
        }
    }

    /**
     * Mutes or unmutes the mic for the active call.
     *
     * @param muted true if the call is muted, false otherwise
     */
    public void setMute(boolean muted) throws ImsException {
        synchronized(mLockObj) {
            if (mMute != muted) {
                logi("setMute :: turning mute " + (muted ? "on" : "off"));
                mMute = muted;

                try {
                    mSession.setMute(muted);
                } catch (Throwable t) {
                    loge("setMute :: ", t);
                    throwImsException(t, 0);
                }
            }
        }
    }

     /**
      * Attaches an incoming call to this call object.
      *
      * @param session the session that receives the incoming call
      * @throws ImsException if the IMS service fails to attach this object to the session
      */
     public void attachSession(ImsCallSession session) throws ImsException {
         logi("attachSession :: session=" + session);

         synchronized(mLockObj) {
             mSession = session;

             try {
                 mSession.setListener(createCallSessionListener());
             } catch (Throwable t) {
                 loge("attachSession :: ", t);
                 throwImsException(t, 0);
             }
         }
     }

    /**
     * Initiates an IMS call with the call profile which is provided
     * when creating a {@link ImsCall}.
     *
     * @param session the {@link ImsCallSession} for carrying out the call
     * @param callee callee information to initiate an IMS call
     * @throws ImsException if the IMS service fails to initiate the call
     */
    public void start(ImsCallSession session, String callee)
            throws ImsException {
        logi("start(1) :: session=" + session);

        synchronized(mLockObj) {
            mSession = session;

            try {
                session.setListener(createCallSessionListener());
                session.start(callee, mCallProfile);
            } catch (Throwable t) {
                loge("start(1) :: ", t);
                throw new ImsException("start(1)", t, 0);
            }
        }
    }

    /**
     * Initiates an IMS conferenca call with the call profile which is provided
     * when creating a {@link ImsCall}.
     *
     * @param session the {@link ImsCallSession} for carrying out the call
     * @param participants participant list to initiate an IMS conference call
     * @throws ImsException if the IMS service fails to initiate the call
     */
    public void start(ImsCallSession session, String[] participants)
            throws ImsException {
        logi("start(n) :: session=" + session);

        synchronized(mLockObj) {
            mSession = session;

            try {
                session.setListener(createCallSessionListener());
                session.start(participants, mCallProfile);
            } catch (Throwable t) {
                loge("start(n) :: ", t);
                throw new ImsException("start(n)", t, 0);
            }
        }
    }

    /**
     * Accepts a call.
     *
     * @see Listener#onCallStarted
     *
     * @param callType The call type the user agreed to for accepting the call.
     * @throws ImsException if the IMS service fails to accept the call
     */
    public void accept(int callType) throws ImsException {
        accept(callType, new ImsStreamMediaProfile());
    }

    /**
     * Accepts a call.
     *
     * @param callType call type to be answered in {@link ImsCallProfile}
     * @param profile a media profile to be answered (audio/audio & video, direction, ...)
     * @see Listener#onCallStarted
     * @throws ImsException if the IMS service fails to accept the call
     */
    public void accept(int callType, ImsStreamMediaProfile profile) throws ImsException {
        logi("accept :: callType=" + callType + ", profile=" + profile);

        if (mAnswerWithRtt) {
            profile.mRttMode = ImsStreamMediaProfile.RTT_MODE_FULL;
            logi("accept :: changing media profile RTT mode to full");
        }

        synchronized(mLockObj) {
            if (mSession == null) {
                throw new ImsException("No call to answer",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            try {
                mSession.accept(callType, profile);
            } catch (Throwable t) {
                loge("accept :: ", t);
                throw new ImsException("accept()", t, 0);
            }

            if (mInCall && (mProposedCallProfile != null)) {
                if (DBG) {
                    logi("accept :: call profile will be updated");
                }

                mCallProfile = mProposedCallProfile;
                trackVideoStateHistory(mCallProfile);
                mProposedCallProfile = null;
            }

            // Other call update received
            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
                mUpdateRequest = UPDATE_NONE;
            }
        }
    }

    /**
     * Deflects a call.
     *
     * @param number number to be deflected to.
     * @throws ImsException if the IMS service fails to deflect the call
     */
    public void deflect(String number) throws ImsException {
        logi("deflect :: session=" + mSession + ", number=" + Rlog.pii(TAG, number));

        synchronized(mLockObj) {
            if (mSession == null) {
                throw new ImsException("No call to deflect",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            try {
                mSession.deflect(number);
            } catch (Throwable t) {
                loge("deflect :: ", t);
                throw new ImsException("deflect()", t, 0);
            }
        }
    }

    /**
     * Rejects a call.
     *
     * @param reason reason code to reject an incoming call
     * @see Listener#onCallStartFailed
     * @throws ImsException if the IMS service fails to reject the call
     */
    public void reject(int reason) throws ImsException {
        logi("reject :: reason=" + reason);

        synchronized(mLockObj) {
            if (mSession != null) {
                mSession.reject(reason);
            }

            if (mInCall && (mProposedCallProfile != null)) {
                if (DBG) {
                    logi("reject :: call profile is not updated; destroy it...");
                }

                mProposedCallProfile = null;
            }

            // Other call update received
            if (mInCall && (mUpdateRequest == UPDATE_UNSPECIFIED)) {
                mUpdateRequest = UPDATE_NONE;
            }
        }
    }

    public void terminate(int reason, int overrideReason) {
        logi("terminate :: reason=" + reason + " ; overrideReason=" + overrideReason);
        mOverrideReason = overrideReason;
        terminate(reason);
    }

    /**
     * Terminates an IMS call (e.g. user initiated).
     *
     * @param reason reason code to terminate a call
     */
    public void terminate(int reason) {
        logi("terminate :: reason=" + reason);

        synchronized(mLockObj) {
            mHold = false;
            mInCall = false;
            mTerminationRequestPending = true;

            if (mSession != null) {
                // TODO: Fix the fact that user invoked call terminations during
                // the process of establishing a conference call needs to be handled
                // as a special case.
                // Currently, any terminations (both invoked by the user or
                // by the network results in a callSessionTerminated() callback
                // from the network.  When establishing a conference call we bury
                // these callbacks until we get closure on all participants of the
                // conference. In some situations, we will throw away the callback
                // (when the underlying session of the host of the new conference
                // is terminated) or will will unbury it when the conference has been
                // established, like when the peer of the new conference goes away
                // after the conference has been created.  The UI relies on the callback
                // to reflect the fact that the call is gone.
                // So if a user decides to terminated a call while it is merging, it
                // could take a long time to reflect in the UI due to the conference
                // processing but we should probably cancel that and just terminate
                // the call immediately and clean up.  This is not a huge issue right
                // now because we have not seen instances where establishing a
                // conference takes a long time (more than a second or two).
                mSession.terminate(reason);
            }
        }
    }


    /**
     * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is called.
     *
     * @see Listener#onCallHeld, Listener#onCallHoldFailed
     * @throws ImsException if the IMS service fails to hold the call
     */
    public void hold() throws ImsException {
        logi("hold :: ");

        if (isOnHold()) {
            if (DBG) {
                logi("hold :: call is already on hold");
            }
            return;
        }

        synchronized(mLockObj) {
            if (mUpdateRequest != UPDATE_NONE) {
                loge("hold :: update is in progress; request=" +
                        updateRequestToString(mUpdateRequest));
                throw new ImsException("Call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            if (mSession == null) {
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.hold(createHoldMediaProfile());
            // FIXME: We should update the state on the callback because that is where
            // we can confirm that the hold request was successful or not.
            mHold = true;
            mUpdateRequest = UPDATE_HOLD;
        }
    }

    /**
     * Continues a call that's on hold. When succeeds, {@link Listener#onCallResumed} is called.
     *
     * @see Listener#onCallResumed, Listener#onCallResumeFailed
     * @throws ImsException if the IMS service fails to resume the call
     */
    public void resume() throws ImsException {
        logi("resume :: ");

        if (!isOnHold()) {
            if (DBG) {
                logi("resume :: call is not being held");
            }
            return;
        }

        synchronized(mLockObj) {
            if (mUpdateRequest != UPDATE_NONE) {
                loge("resume :: update is in progress; request=" +
                        updateRequestToString(mUpdateRequest));
                throw new ImsException("Call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            if (mSession == null) {
                loge("resume :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            // mHold is set to false in confirmation callback that the
            // ImsCall was resumed.
            mUpdateRequest = UPDATE_RESUME;
            mSession.resume(createResumeMediaProfile());
        }
    }

    /**
     * Merges the active & hold call.
     *
     * @see Listener#onCallMerged, Listener#onCallMergeFailed
     * @throws ImsException if the IMS service fails to merge the call
     */
    private void merge() throws ImsException {
        logi("merge :: ");

        synchronized(mLockObj) {
            // If the host of the merge is in the midst of some other operation, we cannot merge.
            if (mUpdateRequest != UPDATE_NONE) {
                setCallSessionMergePending(false);
                if (mMergePeer != null) {
                    mMergePeer.setCallSessionMergePending(false);
                }
                loge("merge :: update is in progress; request=" +
                        updateRequestToString(mUpdateRequest));
                throw new ImsException("Call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            // The peer of the merge is in the midst of some other operation, we cannot merge.
            if (mMergePeer != null && mMergePeer.mUpdateRequest != UPDATE_NONE) {
                setCallSessionMergePending(false);
                mMergePeer.setCallSessionMergePending(false);
                loge("merge :: peer call update is in progress; request=" +
                        updateRequestToString(mMergePeer.mUpdateRequest));
                throw new ImsException("Peer call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            if (mSession == null) {
                loge("merge :: no call session");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            // if skipHoldBeforeMerge = true, IMS service implementation will
            // merge without explicitly holding the call.
            if (mHold || (mContext.getResources().getBoolean(
                    com.android.internal.R.bool.skipHoldBeforeMerge))) {

                if (mMergePeer != null && !mMergePeer.isMultiparty() && !isMultiparty()) {
                    // We only set UPDATE_MERGE when we are adding the first
                    // calls to the Conference.  If there is already a conference
                    // no special handling is needed. The existing conference
                    // session will just go active and any other sessions will be terminated
                    // if needed.  There will be no merge failed callback.
                    // Mark both the host and peer UPDATE_MERGE to ensure both are aware that a
                    // merge is pending.
                    mUpdateRequest = UPDATE_MERGE;
                    mMergePeer.mUpdateRequest = UPDATE_MERGE;
                }

                mSession.merge();
            } else {
                // This code basically says, we need to explicitly hold before requesting a merge
                // when we get the callback that the hold was successful (or failed), we should
                // automatically request a merge.
                mSession.hold(createHoldMediaProfile());
                mHold = true;
                mUpdateRequest = UPDATE_HOLD_MERGE;
            }
        }
    }

    /**
     * Merges the active & hold call.
     *
     * @param bgCall the background (holding) call
     * @see Listener#onCallMerged, Listener#onCallMergeFailed
     * @throws ImsException if the IMS service fails to merge the call
     */
    public void merge(ImsCall bgCall) throws ImsException {
        logi("merge(1) :: bgImsCall=" + bgCall);

        if (bgCall == null) {
            throw new ImsException("No background call",
                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_ARGUMENT);
        }

        synchronized(mLockObj) {
            // Mark both sessions as pending merge.
            this.setCallSessionMergePending(true);
            bgCall.setCallSessionMergePending(true);

            if ((!isMultiparty() && !bgCall.isMultiparty()) || isMultiparty()) {
                // If neither call is multiparty, the current call is the merge host and the bg call
                // is the merge peer (ie we're starting a new conference).
                // OR
                // If this call is multiparty, it is the merge host and the other call is the merge
                // peer.
                setMergePeer(bgCall);
            } else {
                // If the bg call is multiparty, it is the merge host.
                setMergeHost(bgCall);
            }
        }

        if (isMultiparty()) {
            mMergeRequestedByConference = true;
        } else {
            logi("merge : mMergeRequestedByConference not set");
        }
        merge();
    }

    /**
     * Updates the current call's properties (ex. call mode change: video upgrade / downgrade).
     */
    public void update(int callType, ImsStreamMediaProfile mediaProfile) throws ImsException {
        logi("update :: callType=" + callType + ", mediaProfile=" + mediaProfile);

        if (isOnHold()) {
            if (DBG) {
                logi("update :: call is on hold");
            }
            throw new ImsException("Not in a call to update call",
                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
        }

        synchronized(mLockObj) {
            if (mUpdateRequest != UPDATE_NONE) {
                if (DBG) {
                    logi("update :: update is in progress; request=" +
                            updateRequestToString(mUpdateRequest));
                }
                throw new ImsException("Call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            if (mSession == null) {
                loge("update :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.update(callType, mediaProfile);
            mUpdateRequest = UPDATE_UNSPECIFIED;
        }
    }

    /**
     * Extends this call (1-to-1 call) to the conference call
     * inviting the specified participants to.
     *
     */
    public void extendToConference(String[] participants) throws ImsException {
        logi("extendToConference ::");

        if (isOnHold()) {
            if (DBG) {
                logi("extendToConference :: call is on hold");
            }
            throw new ImsException("Not in a call to extend a call to conference",
                    ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
        }

        synchronized(mLockObj) {
            if (mUpdateRequest != UPDATE_NONE) {
                if (CONF_DBG) {
                    logi("extendToConference :: update is in progress; request=" +
                            updateRequestToString(mUpdateRequest));
                }
                throw new ImsException("Call update is in progress",
                        ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE);
            }

            if (mSession == null) {
                loge("extendToConference :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.extendToConference(participants);
            mUpdateRequest = UPDATE_EXTEND_TO_CONFERENCE;
        }
    }

    /**
     * Requests the conference server to invite an additional participants to the conference.
     *
     */
    public void inviteParticipants(String[] participants) throws ImsException {
        logi("inviteParticipants ::");

        synchronized(mLockObj) {
            if (mSession == null) {
                loge("inviteParticipants :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.inviteParticipants(participants);
        }
    }

    /**
     * Requests the conference server to remove the specified participants from the conference.
     *
     */
    public void removeParticipants(String[] participants) throws ImsException {
        logi("removeParticipants :: session=" + mSession);
        synchronized(mLockObj) {
            if (mSession == null) {
                loge("removeParticipants :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.removeParticipants(participants);

        }
    }

    /**
     * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
     * and event flash to 16. Currently, event flash is not supported.
     *
     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
     * @param result the result message to send when done.
     */
    public void sendDtmf(char c, Message result) {
        logi("sendDtmf :: ");

        synchronized(mLockObj) {
            if (mSession != null) {
                mSession.sendDtmf(c, result);
            }
        }
    }

    /**
     * Start a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2833</a>,
     * event 0 ~ 9 maps to decimal value 0 ~ 9, '*' to 10, '#' to 11, event 'A' ~ 'D' to 12 ~ 15,
     * and event flash to 16. Currently, event flash is not supported.
     *
     * @param c that represents the DTMF to send. '0' ~ '9', 'A' ~ 'D', '*', '#' are valid inputs.
     */
    public void startDtmf(char c) {
        logi("startDtmf :: ");

        synchronized(mLockObj) {
            if (mSession != null) {
                mSession.startDtmf(c);
            }
        }
    }

    /**
     * Stop a DTMF code.
     */
    public void stopDtmf() {
        logi("stopDtmf :: ");

        synchronized(mLockObj) {
            if (mSession != null) {
                mSession.stopDtmf();
            }
        }
    }

    /**
     * Sends an USSD message.
     *
     * @param ussdMessage USSD message to send
     */
    public void sendUssd(String ussdMessage) throws ImsException {
        logi("sendUssd :: ussdMessage=" + ussdMessage);

        synchronized(mLockObj) {
            if (mSession == null) {
                loge("sendUssd :: ");
                throw new ImsException("No call session",
                        ImsReasonInfo.CODE_LOCAL_CALL_TERMINATED);
            }

            mSession.sendUssd(ussdMessage);
        }
    }

    public void sendRttMessage(String rttMessage) {
        synchronized(mLockObj) {
            if (mSession == null) {
                loge("sendRttMessage::no session");
            }
            if (!mCallProfile.mMediaProfile.isRttCall()) {
                logi("sendRttMessage::Not an rtt call, ignoring");
                return;
            }
            mSession.sendRttMessage(rttMessage);
        }
    }

    /**
     * Sends a user-requested RTT upgrade request.
     * @param rttOn true if the request is to turn on RTT, false to turn off.
     */
    public void sendRttModifyRequest(boolean rttOn) {
        logi("sendRttModifyRequest");

        synchronized(mLockObj) {
            if (mSession == null) {
                loge("sendRttModifyRequest::no session");
            }
            if (rttOn && mCallProfile.mMediaProfile.isRttCall()) {
                logi("sendRttModifyRequest::Already RTT call, ignoring request to turn on.");
                return;
            } else if (!rttOn && !mCallProfile.mMediaProfile.isRttCall()) {
                logi("sendRttModifyRequest::Not RTT call, ignoring request to turn off.");
                return;
            }
            // Make a copy of the current ImsCallProfile and modify it to enable RTT
            Parcel p = Parcel.obtain();
            mCallProfile.writeToParcel(p, 0);
            p.setDataPosition(0);
            ImsCallProfile requestedProfile = new ImsCallProfile(p);
            requestedProfile.mMediaProfile.setRttMode(rttOn
                    ? ImsStreamMediaProfile.RTT_MODE_FULL
                    : ImsStreamMediaProfile.RTT_MODE_DISABLED);

            mSession.sendRttModifyRequest(requestedProfile);
        }
    }

    /**
     * Sends the user's response to a remotely-issued RTT upgrade request
     *
     * @param textStream A valid {@link Connection.RttTextStream} if the user
     *                   accepts, {@code null} if not.
     */
    public void sendRttModifyResponse(boolean status) {
        logi("sendRttModifyResponse");

        synchronized(mLockObj) {
            if (mSession == null) {
                loge("sendRttModifyResponse::no session");
            }
            if (mCallProfile.mMediaProfile.isRttCall()) {
                logi("sendRttModifyResponse::Already RTT call, ignoring.");
                return;
            }
            mSession.sendRttModifyResponse(status);
        }
    }

    public void setAnswerWithRtt() {
        mAnswerWithRtt = true;
    }

    private void clear(ImsReasonInfo lastReasonInfo) {
        mInCall = false;
        mHold = false;
        mUpdateRequest = UPDATE_NONE;
        mLastReasonInfo = lastReasonInfo;
    }

    /**
     * Creates an IMS call session listener.
     */
    private ImsCallSession.Listener createCallSessionListener() {
        mImsCallSessionListenerProxy = new ImsCallSessionListenerProxy();
        return mImsCallSessionListenerProxy;
    }

    /**
     * @return the current ImsCallSessionListenerProxy.  NOTE: ONLY FOR USE WITH TESTING.
     */
    @VisibleForTesting
    public ImsCallSessionListenerProxy getImsCallSessionListenerProxy() {
        return mImsCallSessionListenerProxy;
    }

    private ImsCall createNewCall(ImsCallSession session, ImsCallProfile profile) {
        ImsCall call = new ImsCall(mContext, profile);

        try {
            call.attachSession(session);
        } catch (ImsException e) {
            if (call != null) {
                call.close();
                call = null;
            }
        }

        // Do additional operations...

        return call;
    }

    private ImsStreamMediaProfile createHoldMediaProfile() {
        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();

        if (mCallProfile == null) {
            return mediaProfile;
        }

        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND;

        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND;
        }

        return mediaProfile;
    }

    private ImsStreamMediaProfile createResumeMediaProfile() {
        ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile();

        if (mCallProfile == null) {
            return mediaProfile;
        }

        mediaProfile.mAudioQuality = mCallProfile.mMediaProfile.mAudioQuality;
        mediaProfile.mVideoQuality = mCallProfile.mMediaProfile.mVideoQuality;
        mediaProfile.mAudioDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;

        if (mediaProfile.mVideoQuality != ImsStreamMediaProfile.VIDEO_QUALITY_NONE) {
            mediaProfile.mVideoDirection = ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE;
        }

        return mediaProfile;
    }

    private void enforceConversationMode() {
        if (mInCall) {
            mHold = false;
            mUpdateRequest = UPDATE_NONE;
        }
    }

    private void mergeInternal() {
        if (CONF_DBG) {
            logi("mergeInternal :: ");
        }

        mSession.merge();
        mUpdateRequest = UPDATE_MERGE;
    }

    private void notifyConferenceSessionTerminated(ImsReasonInfo reasonInfo) {
        ImsCall.Listener listener = mListener;
        clear(reasonInfo);

        if (listener != null) {
            try {
                listener.onCallTerminated(this, reasonInfo);
            } catch (Throwable t) {
                loge("notifyConferenceSessionTerminated :: ", t);
            }
        }
    }

    private void notifyConferenceStateUpdated(ImsConferenceState state) {
        if (state == null || state.mParticipants == null) {
            return;
        }

        Set<Entry<String, Bundle>> participants = state.mParticipants.entrySet();

        if (participants == null) {
            return;
        }

        Iterator<Entry<String, Bundle>> iterator = participants.iterator();
        mConferenceParticipants = new ArrayList<>(participants.size());
        while (iterator.hasNext()) {
            Entry<String, Bundle> entry = iterator.next();

            String key = entry.getKey();
            Bundle confInfo = entry.getValue();
            String status = confInfo.getString(ImsConferenceState.STATUS);
            String user = confInfo.getString(ImsConferenceState.USER);
            String displayName = confInfo.getString(ImsConferenceState.DISPLAY_TEXT);
            String endpoint = confInfo.getString(ImsConferenceState.ENDPOINT);

            if (CONF_DBG) {
                logi("notifyConferenceStateUpdated :: key=" + Rlog.pii(TAG, key) +
                        ", status=" + status +
                        ", user=" + Rlog.pii(TAG, user) +
                        ", displayName= " + Rlog.pii(TAG, displayName) +
                        ", endpoint=" + endpoint);
            }

            Uri handle = Uri.parse(user);
            if (endpoint == null) {
                endpoint = "";
            }
            Uri endpointUri = Uri.parse(endpoint);
            int connectionState = ImsConferenceState.getConnectionStateForStatus(status);

            if (connectionState != Connection.STATE_DISCONNECTED) {
                ConferenceParticipant conferenceParticipant = new ConferenceParticipant(handle,
                        displayName, endpointUri, connectionState);
                mConferenceParticipants.add(conferenceParticipant);
            }
        }

        if (mConferenceParticipants != null && mListener != null) {
            try {
                mListener.onConferenceParticipantsStateChanged(this, mConferenceParticipants);
            } catch (Throwable t) {
                loge("notifyConferenceStateUpdated :: ", t);
            }
        }
    }

    /**
     * Perform all cleanup and notification around the termination of a session.
     * Note that there are 2 distinct modes of operation.  The first is when
     * we receive a session termination on the primary session when we are
     * in the processing of merging.  The second is when we are not merging anything
     * and the call is terminated.
     *
     * @param reasonInfo The reason for the session termination
     */
    private void processCallTerminated(ImsReasonInfo reasonInfo) {
        logi("processCallTerminated :: reason=" + reasonInfo + " userInitiated = " +
                mTerminationRequestPending);

        ImsCall.Listener listener = null;
        synchronized(ImsCall.this) {
            // If we are in the midst of establishing a conference, we will bury the termination
            // until the merge has completed.  If necessary we can surface the termination at
            // this point.
            // We will also NOT bury the termination if a termination was initiated locally.
            if (isCallSessionMergePending() && !mTerminationRequestPending) {
                // Since we are in the process of a merge, this trigger means something
                // else because it is probably due to the merge happening vs. the
                // session is really terminated. Let's flag this and revisit if
                // the merge() ends up failing because we will need to take action on the
                // mSession in that case since the termination was not due to the merge
                // succeeding.
                if (CONF_DBG) {
                    logi("processCallTerminated :: burying termination during ongoing merge.");
                }
                mSessionEndDuringMerge = true;
                mSessionEndDuringMergeReasonInfo = reasonInfo;
                return;
            }

            // If we are terminating the conference call, notify using conference listeners.
            if (isMultiparty()) {
                notifyConferenceSessionTerminated(reasonInfo);
                return;
            } else {
                listener = mListener;
                clear(reasonInfo);
            }
        }

        if (listener != null) {
            try {
                listener.onCallTerminated(ImsCall.this, reasonInfo);
            } catch (Throwable t) {
                loge("processCallTerminated :: ", t);
            }
        }
    }

    /**
     * This function determines if the ImsCallSession is our actual ImsCallSession or if is
     * the transient session used in the process of creating a conference. This function should only
     * be called within  callbacks that are not directly related to conference merging but might
     * potentially still be called on the transient ImsCallSession sent to us from
     * callSessionMergeStarted() when we don't really care. In those situations, we probably don't
     * want to take any action so we need to know that we can return early.
     *
     * @param session - The {@link ImsCallSession} that the function needs to analyze
     * @return true if this is the transient {@link ImsCallSession}, false otherwise.
     */
    private boolean isTransientConferenceSession(ImsCallSession session) {
        if (session != null && session != mSession && session == mTransientConferenceSession) {
            return true;
        }
        return false;
    }

    private void setTransientSessionAsPrimary(ImsCallSession transientSession) {
        synchronized (ImsCall.this) {
            mSession.setListener(null);
            mSession = transientSession;
            mSession.setListener(createCallSessionListener());
        }
    }

    private void markCallAsMerged(boolean playDisconnectTone) {
        if (!isSessionAlive(mSession)) {
            // If the peer is dead, let's not play a disconnect sound for it when we
            // unbury the termination callback.
            logi("markCallAsMerged");
            setIsMerged(playDisconnectTone);
            mSessionEndDuringMerge = true;
            String reasonInfo;
            int reasonCode = ImsReasonInfo.CODE_UNSPECIFIED;
            if (playDisconnectTone) {
                reasonCode = ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE;
                reasonInfo = "Call ended by network";
            } else {
                reasonCode = ImsReasonInfo.CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE;
                reasonInfo = "Call ended during conference merge process.";
            }
            mSessionEndDuringMergeReasonInfo = new ImsReasonInfo(
                    reasonCode, 0, reasonInfo);
        }
    }

    /**
     * Checks if the merge was requested by foreground conference call
     *
     * @return true if the merge was requested by foreground conference call
     */
    public boolean isMergeRequestedByConf() {
        synchronized(mLockObj) {
            return mMergeRequestedByConference;
        }
    }

    /**
     * Resets the flag which indicates merge request was sent by
     * foreground conference call
     */
    public void resetIsMergeRequestedByConf(boolean value) {
        synchronized(mLockObj) {
            mMergeRequestedByConference = value;
        }
    }

    /**
     * Returns current ImsCallSession
     *
     * @return current session
     */
    public ImsCallSession getSession() {
        synchronized(mLockObj) {
            return mSession;
        }
    }

    /**
     * We have detected that a initial conference call has been fully configured. The internal
     * state of both {@code ImsCall} objects need to be cleaned up to reflect the new state.
     * This function should only be called in the context of the merge host to simplify logic
     *
     */
    private void processMergeComplete() {
        logi("processMergeComplete :: ");

        // The logic simplifies if we can assume that this function is only called on
        // the merge host.
        if (!isMergeHost()) {
            loge("processMergeComplete :: We are not the merge host!");
            return;
        }

        ImsCall.Listener listener;
        boolean swapRequired = false;

        ImsCall finalHostCall;
        ImsCall finalPeerCall;

        synchronized(ImsCall.this) {
            if (isMultiparty()) {
                setIsMerged(false);
                // if case handles Case 4 explained in callSessionMergeComplete
                // otherwise it is case 5
                if (!mMergeRequestedByConference) {
                    // single call in fg, conference call in bg.
                    // Finally conf call becomes active after conference
                    this.mHold = false;
                    swapRequired = true;
                }
                mMergePeer.markCallAsMerged(false);
                finalHostCall = this;
                finalPeerCall = mMergePeer;
            } else {
                // If we are here, we are not trying to merge a new call into an existing
                // conference.  That means that there is a transient session on the merge
                // host that represents the future conference once all the parties
                // have been added to it.  So make sure that it exists or else something
                // very wrong is going on.
                if (mTransientConferenceSession == null) {
                    loge("processMergeComplete :: No transient session!");
                    return;
                }
                if (mMergePeer == null) {
                    loge("processMergeComplete :: No merge peer!");
                    return;
                }

                // Since we are the host, we have the transient session attached to us. Let's detach
                // it and figure out where we need to set it for the final conference configuration.
                ImsCallSession transientConferenceSession = mTransientConferenceSession;
                mTransientConferenceSession = null;

                // Clear the listener for this transient session, we'll create a new listener
                // when it is attached to the final ImsCall that it should live on.
                transientConferenceSession.setListener(null);

                // Determine which call the transient session should be moved to.  If the current
                // call session is still alive and the merge peer's session is not, we have a
                // situation where the current call failed to merge into the conference but the
                // merge peer did merge in to the conference.  In this type of scenario the current
                // call will continue as a single party call, yet the background call will become
                // the conference.

                // handles Case 3 explained in callSessionMergeComplete
                if (isSessionAlive(mSession) && !isSessionAlive(mMergePeer.getCallSession())) {
                    // I'm the host but we are moving the transient session to the peer since its
                    // session was disconnected and my session is still alive.  This signifies that
                    // their session was properly added to the conference but mine was not because
                    // it is probably in the held state as opposed to part of the final conference.
                    // In this case, we need to set isMerged to false on both calls so the
                    // disconnect sound is called when either call disconnects.
                    // Note that this case is only valid if this is an initial conference being
                    // brought up.
                    mMergePeer.mHold = false;
                    this.mHold = true;
                    if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
                        mMergePeer.mConferenceParticipants = mConferenceParticipants;
                    }
                    // At this point both host & peer will have participant information.
                    // Peer will transition to host & the participant information
                    // from that will be used
                    // HostCall that failed to merge will remain as a single call with
                    // mConferenceParticipants, which should not be used.
                    // Expectation is that if this call becomes part of a conference call in future,
                    // mConferenceParticipants will be overriten with new CEP that is received.
                    finalHostCall = mMergePeer;
                    finalPeerCall = this;
                    swapRequired = true;
                    setIsMerged(false);
                    mMergePeer.setIsMerged(false);
                    if (CONF_DBG) {
                        logi("processMergeComplete :: transient will transfer to merge peer");
                    }
                } else if (!isSessionAlive(mSession) &&
                                isSessionAlive(mMergePeer.getCallSession())) {
                    // Handles case 2 explained in callSessionMergeComplete
                    // The transient session stays with us and the disconnect sound should be played
                    // when the merge peer eventually disconnects since it was not actually added to
                    // the conference and is probably sitting in the held state.
                    finalHostCall = this;
                    finalPeerCall = mMergePeer;
                    swapRequired = false;
                    setIsMerged(false);
                    mMergePeer.setIsMerged(false); // Play the disconnect sound
                    if (CONF_DBG) {
                        logi("processMergeComplete :: transient will stay with the merge host");
                    }
                } else {
                    // Handles case 1 explained in callSessionMergeComplete
                    // The transient session stays with us and the disconnect sound should not be
                    // played when we ripple up the disconnect for the merge peer because it was
                    // only disconnected to be added to the conference.
                    finalHostCall = this;
                    finalPeerCall = mMergePeer;
                    mMergePeer.markCallAsMerged(false);
                    swapRequired = false;
                    setIsMerged(false);
                    mMergePeer.setIsMerged(true);
                    if (CONF_DBG) {
                        logi("processMergeComplete :: transient will stay with us (I'm the host).");
                    }
                }

                if (CONF_DBG) {
                    logi("processMergeComplete :: call=" + finalHostCall + " is the final host");
                }

                // Add the transient session to the ImsCall that ended up being the host for the
                // conference.
                finalHostCall.setTransientSessionAsPrimary(transientConferenceSession);
            }

            listener = finalHostCall.mListener;

            updateCallProfile(finalPeerCall);
            updateCallProfile(finalHostCall);

            // Clear all the merge related flags.
            clearMergeInfo();

            // For the final peer...let's bubble up any possible disconnects that we had
            // during the merge process
            finalPeerCall.notifySessionTerminatedDuringMerge();
            // For the final host, let's just bury the disconnects that we my have received
            // during the merge process since we are now the host of the conference call.
            finalHostCall.clearSessionTerminationFlags();

            // Keep track of the fact that merge host is the origin of a conference call in
            // progress.  This is important so that we can later determine if a multiparty ImsCall
            // is multiparty because it was the origin of a conference call, or because it is a
            // member of a conference on another device.
            finalHostCall.mIsConferenceHost = true;
        }
        if (listener != null) {
            try {
                // finalPeerCall will have the participant that was not merged and
                // it will be held state
                // if peer was merged successfully, finalPeerCall will be null
                listener.onCallMerged(finalHostCall, finalPeerCall, swapRequired);
            } catch (Throwable t) {
                loge("processMergeComplete :: ", t);
            }
            if (mConferenceParticipants != null && !mConferenceParticipants.isEmpty()) {
                try {
                    listener.onConferenceParticipantsStateChanged(finalHostCall,
                            mConferenceParticipants);
                } catch (Throwable t) {
                    loge("processMergeComplete :: ", t);
                }
            }
        }
        return;
    }

    private static void updateCallProfile(ImsCall call) {
        if (call != null) {
            call.updateCallProfile();
        }
    }

    private void updateCallProfile() {
        synchronized (mLockObj) {
            if (mSession != null) {
                setCallProfile(mSession.getCallProfile());
            }
        }
    }

    /**
     * Handles the case where the session has ended during a merge by reporting the termination
     * reason to listeners.
     */
    private void notifySessionTerminatedDuringMerge() {
        ImsCall.Listener listener;
        boolean notifyFailure = false;
        ImsReasonInfo notifyFailureReasonInfo = null;

        synchronized(ImsCall.this) {
            listener = mListener;
            if (mSessionEndDuringMerge) {
                // Set some local variables that will send out a notification about a
                // previously buried termination callback for our primary session now that
                // we know that this is not due to the conference call merging successfully.
                if (CONF_DBG) {
                    logi("notifySessionTerminatedDuringMerge ::reporting terminate during merge");
                }
                notifyFailure = true;
                notifyFailureReasonInfo = mSessionEndDuringMergeReasonInfo;
            }
            clearSessionTerminationFlags();
        }

        if (listener != null && notifyFailure) {
            try {
                processCallTerminated(notifyFailureReasonInfo);
            } catch (Throwable t) {
                loge("notifySessionTerminatedDuringMerge :: ", t);
            }
        }
    }

    private void clearSessionTerminationFlags() {
        mSessionEndDuringMerge = false;
        mSessionEndDuringMergeReasonInfo = null;
    }

   /**
     * We received a callback from ImsCallSession that a merge failed. Clean up all
     * internal state to represent this state change.  The calling function is a callback
     * and should have been called on the session that was in the foreground
     * when merge() was originally called.  It is assumed that this function will be called
     * on the merge host.
     *
     * @param reasonInfo The {@link ImsReasonInfo} why the merge failed.
     */
    private void processMergeFailed(ImsReasonInfo reasonInfo) {
        logi("processMergeFailed :: reason=" + reasonInfo);

        ImsCall.Listener listener;
        synchronized(ImsCall.this) {
            // The logic simplifies if we can assume that this function is only called on
            // the merge host.
            if (!isMergeHost()) {
                loge("processMergeFailed :: We are not the merge host!");
                return;
            }

            // Try to clean up the transient session if it exists.
            if (mTransientConferenceSession != null) {
                mTransientConferenceSession.setListener(null);
                mTransientConferenceSession = null;
            }

            listener = mListener;

            // Ensure the calls being conferenced into the conference has isMerged = false.
            // Ensure any terminations are surfaced from this session.
            markCallAsMerged(true);
            setCallSessionMergePending(false);
            notifySessionTerminatedDuringMerge();

            // Perform the same cleanup on the merge peer if it exists.
            if (mMergePeer != null) {
                mMergePeer.markCallAsMerged(true);
                mMergePeer.setCallSessionMergePending(false);
                mMergePeer.notifySessionTerminatedDuringMerge();
            } else {
                loge("processMergeFailed :: No merge peer!");
            }

            // Clear all the various flags around coordinating this merge.
            clearMergeInfo();
        }
        if (listener != null) {
            try {
                listener.onCallMergeFailed(ImsCall.this, reasonInfo);
            } catch (Throwable t) {
                loge("processMergeFailed :: ", t);
            }
        }

        return;
    }

    @VisibleForTesting
    public class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
        @Override
        public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
            logi("callSessionProgressing :: session=" + session + " profile=" + profile);

            if (isTransientConferenceSession(session)) {
                // If it is a transient (conference) session, there is no action for this signal.
                logi("callSessionProgressing :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mCallProfile.mMediaProfile.copyFrom(profile);
            }

            if (listener != null) {
                try {
                    listener.onCallProgressing(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionProgressing :: ", t);
                }
            }
        }

        @Override
        public void callSessionStarted(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionStarted :: session=" + session + " profile=" + profile);

            if (!isTransientConferenceSession(session)) {
                // In the case that we are in the middle of a merge (either host or peer), we have
                // closure as far as this call's primary session is concerned.  If we are not
                // merging...its a NOOP.
                setCallSessionMergePending(false);
            } else {
                logi("callSessionStarted :: on transient session=" + session);
                return;
            }

            if (isTransientConferenceSession(session)) {
                // No further processing is needed if this is the transient session.
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                setCallProfile(profile);
            }

            if (listener != null) {
                try {
                    listener.onCallStarted(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionStarted :: ", t);
                }
            }
        }

        @Override
        public void callSessionStartFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
            loge("callSessionStartFailed :: session=" + session + " reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                // We should not get this callback for a transient session.
                logi("callSessionStartFailed :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mLastReasonInfo = reasonInfo;
            }

            if (listener != null) {
                try {
                    listener.onCallStartFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionStarted :: ", t);
                }
            }
        }

        @Override
        public void callSessionTerminated(ImsCallSession session, ImsReasonInfo reasonInfo) {
            logi("callSessionTerminated :: session=" + session + " reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionTerminated :: on transient session=" + session);
                // This is bad, it should be treated much a callSessionMergeFailed since the
                // transient session only exists when in the process of a merge and the
                // termination of this session is effectively the end of the merge.
                processMergeFailed(reasonInfo);
                return;
            }

            if (mOverrideReason != ImsReasonInfo.CODE_UNSPECIFIED) {
                logi("callSessionTerminated :: overrideReasonInfo=" + mOverrideReason);
                reasonInfo = new ImsReasonInfo(mOverrideReason, reasonInfo.getExtraCode(),
                        reasonInfo.getExtraMessage());
            }

            // Process the termination first.  If we are in the midst of establishing a conference
            // call, we may bury this callback until we are done.  If there so no conference
            // call, the code after this function will be a NOOP.
            processCallTerminated(reasonInfo);

            // If session has terminated, it is no longer pending merge.
            setCallSessionMergePending(false);

        }

        @Override
        public void callSessionHeld(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionHeld :: session=" + session + "profile=" + profile);
            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                // If the session was held, it is no longer pending a merge -- this means it could
                // not be merged into the conference and was held instead.
                setCallSessionMergePending(false);

                setCallProfile(profile);

                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
                    // This hold request was made to set the stage for a merge.
                    mergeInternal();
                    return;
                }

                mUpdateRequest = UPDATE_NONE;
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallHeld(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionHeld :: ", t);
                }
            }
        }

        @Override
        public void callSessionHoldFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
            loge("callSessionHoldFailed :: session" + session + "reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                // We should not get this callback for a transient session.
                logi("callSessionHoldFailed :: not supported for transient conference session=" +
                        session);
                return;
            }

            logi("callSessionHoldFailed :: session=" + session +
                    ", reasonInfo=" + reasonInfo);

            synchronized (mLockObj) {
                mHold = false;
            }

            boolean isHoldForMerge = false;
            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                if (mUpdateRequest == UPDATE_HOLD_MERGE) {
                    isHoldForMerge = true;
                }

                mUpdateRequest = UPDATE_NONE;
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallHoldFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionHoldFailed :: ", t);
                }
            }
        }

        /**
         * Indicates that an {@link ImsCallSession} has been remotely held.  This can be due to the
         * remote party holding the current call, or swapping between calls.
         * @param session the session which was held.
         * @param profile the profile for the held call.
         */
        @Override
        public void callSessionHoldReceived(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionHoldReceived :: session=" + session + "profile=" + profile);

            if (isTransientConferenceSession(session)) {
                // We should not get this callback for a transient session.
                logi("callSessionHoldReceived :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                setCallProfile(profile);
            }

            if (listener != null) {
                try {
                    listener.onCallHoldReceived(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionHoldReceived :: ", t);
                }
            }
        }

        /**
         * Indicates that an {@link ImsCallSession} has been remotely resumed.  This can be due to
         * the remote party un-holding the current call, or swapping back to this call.
         * @param session the session which was resumed.
         * @param profile the profile for the held call.
         */
        @Override
        public void callSessionResumed(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionResumed :: session=" + session + "profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionResumed :: not supported for transient conference session=" +
                        session);
                return;
            }

            // If this call was pending a merge, it is not anymore. This is the case when we
            // are merging in a new call into an existing conference.
            setCallSessionMergePending(false);

            // TOOD: When we are merging a new call into an existing conference we are waiting
            // for 2 triggers to let us know that the conference has been established, the first
            // is a termination for the new calls (since it is added to the conference) the second
            // would be a resume on the existing conference.  If the resume comes first, then
            // we will make the onCallResumed() callback and its unclear how this will behave if
            // the termination has not come yet.

            ImsCall.Listener listener;
            synchronized(ImsCall.this) {
                listener = mListener;
                setCallProfile(profile);
                mUpdateRequest = UPDATE_NONE;
                mHold = false;
            }

            if (listener != null) {
                try {
                    listener.onCallResumed(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionResumed :: ", t);
                }
            }
        }

        @Override
        public void callSessionResumeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
            loge("callSessionResumeFailed :: session=" + session + "reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionResumeFailed :: not supported for transient conference session=" +
                        session);
                return;
            }

            synchronized(mLockObj) {
                mHold = true;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mUpdateRequest = UPDATE_NONE;
            }

            if (listener != null) {
                try {
                    listener.onCallResumeFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionResumeFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionResumeReceived(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionResumeReceived :: session=" + session + "profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionResumeReceived :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                setCallProfile(profile);
            }

            if (listener != null) {
                try {
                    listener.onCallResumeReceived(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionResumeReceived :: ", t);
                }
            }
        }

        @Override
        public void callSessionMergeStarted(ImsCallSession session,
                ImsCallSession newSession, ImsCallProfile profile) {
            logi("callSessionMergeStarted :: session=" + session + " newSession=" + newSession +
                    ", profile=" + profile);

            return;
        }

        /*
         * This method check if session exists as a session on the current
         * ImsCall or its counterpart if it is in the process of a conference
         */
        private boolean doesCallSessionExistsInMerge(ImsCallSession cs) {
            String callId = cs.getCallId();
            return ((isMergeHost() && Objects.equals(mMergePeer.mSession.getCallId(), callId)) ||
                    (isMergePeer() && Objects.equals(mMergeHost.mSession.getCallId(), callId)) ||
                    Objects.equals(mSession.getCallId(), callId));
        }

        /**
         * We received a callback from ImsCallSession that merge completed.
         * @param newSession - this session can have 2 values based on the below scenarios
         *
	 * Conference Scenarios :
         * Case 1 - 3 way success case
         * Case 2 - 3 way success case but held call fails to merge
         * Case 3 - 3 way success case but active call fails to merge
         * case 4 - 4 way success case, where merge is initiated on the foreground single-party
         *          call and the conference (mergeHost) is the background call.
         * case 5 - 4 way success case, where merge is initiated on the foreground conference
         *          call (mergeHost) and the single party call is in the background.
         *
         * Conference Result:
         * session : new session after conference
         * newSession = new session for case 1, 2, 3.
         *              Should be considered as mTransientConferencession
         * newSession = Active conference session for case 5 will be null
         *              mergehost was foreground call
         *              mTransientConferencession will be null
         * newSession = Active conference session for case 4 will be null
         *              mergeHost was background call
         *              mTransientConferencession will be null
         */
        @Override
        public void callSessionMergeComplete(ImsCallSession newSession) {
            logi("callSessionMergeComplete :: newSession =" + newSession);
            if (!isMergeHost()) {
                // Handles case 4
                mMergeHost.processMergeComplete();
            } else {
                // Handles case 1, 2, 3
                if (newSession != null) {
                    mTransientConferenceSession = doesCallSessionExistsInMerge(newSession) ?
                            null: newSession;
                }
                // Handles case 5
                processMergeComplete();
            }
        }

        @Override
        public void callSessionMergeFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
            loge("callSessionMergeFailed :: session=" + session + "reasonInfo=" + reasonInfo);

            // Its possible that there could be threading issues with the other thread handling
            // the other call. This could affect our state.
            synchronized (ImsCall.this) {
                // Let's tell our parent ImsCall that the merge has failed and we need to clean
                // up any temporary, transient state.  Note this only gets called for an initial
                // conference.  If a merge into an existing conference fails, the two sessions will
                // just go back to their original state (ACTIVE or HELD).
                if (isMergeHost()) {
                    processMergeFailed(reasonInfo);
                } else if (mMergeHost != null) {
                    mMergeHost.processMergeFailed(reasonInfo);
                } else {
                    loge("callSessionMergeFailed :: No merge host for this conference!");
                }
            }
        }

        @Override
        public void callSessionUpdated(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionUpdated :: session=" + session + " profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionUpdated :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                setCallProfile(profile);
            }

            if (listener != null) {
                try {
                    listener.onCallUpdated(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionUpdated :: ", t);
                }
            }
        }

        @Override
        public void callSessionUpdateFailed(ImsCallSession session, ImsReasonInfo reasonInfo) {
            loge("callSessionUpdateFailed :: session=" + session + " reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionUpdateFailed :: not supported for transient conference session=" +
                        session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mUpdateRequest = UPDATE_NONE;
            }

            if (listener != null) {
                try {
                    listener.onCallUpdateFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionUpdateFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionUpdateReceived(ImsCallSession session, ImsCallProfile profile) {
            logi("callSessionUpdateReceived :: session=" + session + " profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionUpdateReceived :: not supported for transient conference " +
                        "session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mProposedCallProfile = profile;
                mUpdateRequest = UPDATE_UNSPECIFIED;
            }

            if (listener != null) {
                try {
                    listener.onCallUpdateReceived(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionUpdateReceived :: ", t);
                }
            }
        }

        @Override
        public void callSessionConferenceExtended(ImsCallSession session, ImsCallSession newSession,
                ImsCallProfile profile) {
            logi("callSessionConferenceExtended :: session=" + session  + " newSession=" +
                    newSession + ", profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionConferenceExtended :: not supported for transient conference " +
                        "session=" + session);
                return;
            }

            ImsCall newCall = createNewCall(newSession, profile);

            if (newCall == null) {
                callSessionConferenceExtendFailed(session, new ImsReasonInfo());
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mUpdateRequest = UPDATE_NONE;
            }

            if (listener != null) {
                try {
                    listener.onCallConferenceExtended(ImsCall.this, newCall);
                } catch (Throwable t) {
                    loge("callSessionConferenceExtended :: ", t);
                }
            }
        }

        @Override
        public void callSessionConferenceExtendFailed(ImsCallSession session,
                ImsReasonInfo reasonInfo) {
            loge("callSessionConferenceExtendFailed :: reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionConferenceExtendFailed :: not supported for transient " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
                mUpdateRequest = UPDATE_NONE;
            }

            if (listener != null) {
                try {
                    listener.onCallConferenceExtendFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionConferenceExtendFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionConferenceExtendReceived(ImsCallSession session,
                ImsCallSession newSession, ImsCallProfile profile) {
            logi("callSessionConferenceExtendReceived :: newSession=" + newSession +
                    ", profile=" + profile);

            if (isTransientConferenceSession(session)) {
                logi("callSessionConferenceExtendReceived :: not supported for transient " +
                        "conference session" + session);
                return;
            }

            ImsCall newCall = createNewCall(newSession, profile);

            if (newCall == null) {
                // Should all the calls be terminated...???
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallConferenceExtendReceived(ImsCall.this, newCall);
                } catch (Throwable t) {
                    loge("callSessionConferenceExtendReceived :: ", t);
                }
            }
        }

        @Override
        public void callSessionInviteParticipantsRequestDelivered(ImsCallSession session) {
            logi("callSessionInviteParticipantsRequestDelivered ::");

            if (isTransientConferenceSession(session)) {
                logi("callSessionInviteParticipantsRequestDelivered :: not supported for " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallInviteParticipantsRequestDelivered(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionInviteParticipantsRequestDelivered :: ", t);
                }
            }
        }

        @Override
        public void callSessionInviteParticipantsRequestFailed(ImsCallSession session,
                ImsReasonInfo reasonInfo) {
            loge("callSessionInviteParticipantsRequestFailed :: reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionInviteParticipantsRequestFailed :: not supported for " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallInviteParticipantsRequestFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionInviteParticipantsRequestFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionRemoveParticipantsRequestDelivered(ImsCallSession session) {
            logi("callSessionRemoveParticipantsRequestDelivered ::");

            if (isTransientConferenceSession(session)) {
                logi("callSessionRemoveParticipantsRequestDelivered :: not supported for " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallRemoveParticipantsRequestDelivered(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionRemoveParticipantsRequestDelivered :: ", t);
                }
            }
        }

        @Override
        public void callSessionRemoveParticipantsRequestFailed(ImsCallSession session,
                ImsReasonInfo reasonInfo) {
            loge("callSessionRemoveParticipantsRequestFailed :: reasonInfo=" + reasonInfo);

            if (isTransientConferenceSession(session)) {
                logi("callSessionRemoveParticipantsRequestFailed :: not supported for " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallRemoveParticipantsRequestFailed(ImsCall.this, reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionRemoveParticipantsRequestFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionConferenceStateUpdated(ImsCallSession session,
                ImsConferenceState state) {
            logi("callSessionConferenceStateUpdated :: state=" + state);

            conferenceStateUpdated(state);
        }

        @Override
        public void callSessionUssdMessageReceived(ImsCallSession session, int mode,
                String ussdMessage) {
            logi("callSessionUssdMessageReceived :: mode=" + mode + ", ussdMessage=" +
                    ussdMessage);

            if (isTransientConferenceSession(session)) {
                logi("callSessionUssdMessageReceived :: not supported for transient " +
                        "conference session=" + session);
                return;
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallUssdMessageReceived(ImsCall.this, mode, ussdMessage);
                } catch (Throwable t) {
                    loge("callSessionUssdMessageReceived :: ", t);
                }
            }
        }

        @Override
        public void callSessionTtyModeReceived(ImsCallSession session, int mode) {
            logi("callSessionTtyModeReceived :: mode=" + mode);

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallSessionTtyModeReceived(ImsCall.this, mode);
                } catch (Throwable t) {
                    loge("callSessionTtyModeReceived :: ", t);
                }
            }
        }

        /**
         * Notifies of a change to the multiparty state for this {@code ImsCallSession}.
         *
         * @param session The call session.
         * @param isMultiParty {@code true} if the session became multiparty, {@code false}
         *      otherwise.
         */
        @Override
        public void callSessionMultipartyStateChanged(ImsCallSession session,
                boolean isMultiParty) {
            if (VDBG) {
                logi("callSessionMultipartyStateChanged isMultiParty: " + (isMultiParty ? "Y"
                        : "N"));
            }

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onMultipartyStateChanged(ImsCall.this, isMultiParty);
                } catch (Throwable t) {
                    loge("callSessionMultipartyStateChanged :: ", t);
                }
            }
        }

        public void callSessionHandover(ImsCallSession session, int srcAccessTech,
            int targetAccessTech, ImsReasonInfo reasonInfo) {
            logi("callSessionHandover :: session=" + session + ", srcAccessTech=" +
                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
                reasonInfo);

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallHandover(ImsCall.this, srcAccessTech, targetAccessTech,
                        reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionHandover :: ", t);
                }
            }
        }

        @Override
        public void callSessionHandoverFailed(ImsCallSession session, int srcAccessTech,
            int targetAccessTech, ImsReasonInfo reasonInfo) {
            loge("callSessionHandoverFailed :: session=" + session + ", srcAccessTech=" +
                srcAccessTech + ", targetAccessTech=" + targetAccessTech + ", reasonInfo=" +
                reasonInfo);

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallHandoverFailed(ImsCall.this, srcAccessTech, targetAccessTech,
                        reasonInfo);
                } catch (Throwable t) {
                    loge("callSessionHandoverFailed :: ", t);
                }
            }
        }

        @Override
        public void callSessionSuppServiceReceived(ImsCallSession session,
                ImsSuppServiceNotification suppServiceInfo ) {
            if (isTransientConferenceSession(session)) {
                logi("callSessionSuppServiceReceived :: not supported for transient conference"
                        + " session=" + session);
                return;
            }

            logi("callSessionSuppServiceReceived :: session=" + session +
                     ", suppServiceInfo" + suppServiceInfo);

            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onCallSuppServiceReceived(ImsCall.this, suppServiceInfo);
                } catch (Throwable t) {
                    loge("callSessionSuppServiceReceived :: ", t);
                }
            }
        }

        @Override
        public void callSessionRttModifyRequestReceived(ImsCallSession session,
                ImsCallProfile callProfile) {
            ImsCall.Listener listener;
            logi("callSessionRttModifyRequestReceived");

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (!callProfile.mMediaProfile.isRttCall()) {
                logi("callSessionRttModifyRequestReceived:: ignoring request, requested profile " +
                        "is not RTT.");
                return;
            }

            if (listener != null) {
                try {
                    listener.onRttModifyRequestReceived(ImsCall.this);
                } catch (Throwable t) {
                    loge("callSessionRttModifyRequestReceived:: ", t);
                }
            }
        }

        @Override
        public void callSessionRttModifyResponseReceived(int status) {
            ImsCall.Listener listener;

            logi("callSessionRttModifyResponseReceived: " + status);
            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onRttModifyResponseReceived(ImsCall.this, status);
                } catch (Throwable t) {
                    loge("callSessionRttModifyResponseReceived:: ", t);
                }
            }
        }

        @Override
        public void callSessionRttMessageReceived(String rttMessage) {
            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onRttMessageReceived(ImsCall.this, rttMessage);
                } catch (Throwable t) {
                    loge("callSessionRttMessageReceived:: ", t);
                }
            }
        }

        @Override
        public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
            ImsCall.Listener listener;

            synchronized(ImsCall.this) {
                listener = mListener;
            }

            if (listener != null) {
                try {
                    listener.onRttAudioIndicatorChanged(ImsCall.this, profile);
                } catch (Throwable t) {
                    loge("callSessionRttAudioIndicatorChanged:: ", t);
                }
            }
        }
    }

    /**
     * Report a new conference state to the current {@link ImsCall} and inform listeners of the
     * change.  Marked as {@code VisibleForTesting} so that the
     * {@code com.android.internal.telephony.TelephonyTester} class can inject a test conference
     * event package into a regular ongoing IMS call.
     *
     * @param state The {@link ImsConferenceState}.
     */
    @VisibleForTesting
    public void conferenceStateUpdated(ImsConferenceState state) {
        Listener listener;

        synchronized(this) {
            notifyConferenceStateUpdated(state);
            listener = mListener;
        }

        if (listener != null) {
            try {
                listener.onCallConferenceStateUpdated(this, state);
            } catch (Throwable t) {
                loge("callSessionConferenceStateUpdated :: ", t);
            }
        }
    }

    /**
     * Provides a human-readable string representation of an update request.
     *
     * @param updateRequest The update request.
     * @return The string representation.
     */
    private String updateRequestToString(int updateRequest) {
        switch (updateRequest) {
            case UPDATE_NONE:
                return "NONE";
            case UPDATE_HOLD:
                return "HOLD";
            case UPDATE_HOLD_MERGE:
                return "HOLD_MERGE";
            case UPDATE_RESUME:
                return "RESUME";
            case UPDATE_MERGE:
                return "MERGE";
            case UPDATE_EXTEND_TO_CONFERENCE:
                return "EXTEND_TO_CONFERENCE";
            case UPDATE_UNSPECIFIED:
                return "UNSPECIFIED";
            default:
                return "UNKNOWN";
        }
    }

    /**
     * Clears the merge peer for this call, ensuring that the peer's connection to this call is also
     * severed at the same time.
     */
    private void clearMergeInfo() {
        if (CONF_DBG) {
            logi("clearMergeInfo :: clearing all merge info");
        }

        // First clear out the merge partner then clear ourselves out.
        if (mMergeHost != null) {
            mMergeHost.mMergePeer = null;
            mMergeHost.mUpdateRequest = UPDATE_NONE;
            mMergeHost.mCallSessionMergePending = false;
        }
        if (mMergePeer != null) {
            mMergePeer.mMergeHost = null;
            mMergePeer.mUpdateRequest = UPDATE_NONE;
            mMergePeer.mCallSessionMergePending = false;
        }
        mMergeHost = null;
        mMergePeer = null;
        mUpdateRequest = UPDATE_NONE;
        mCallSessionMergePending = false;
    }

    /**
     * Sets the merge peer for the current call.  The merge peer is the background call that will be
     * merged into this call.  On the merge peer, sets the merge host to be this call.
     *
     * @param mergePeer The peer call to be merged into this one.
     */
    private void setMergePeer(ImsCall mergePeer) {
        mMergePeer = mergePeer;
        mMergeHost = null;

        mergePeer.mMergeHost = ImsCall.this;
        mergePeer.mMergePeer = null;
    }

    /**
     * Sets the merge hody for the current call.  The merge host is the foreground call this call
     * will be merged into.  On the merge host, sets the merge peer to be this call.
     *
     * @param mergeHost The merge host this call will be merged into.
     */
    public void setMergeHost(ImsCall mergeHost) {
        mMergeHost = mergeHost;
        mMergePeer = null;

        mergeHost.mMergeHost = null;
        mergeHost.mMergePeer = ImsCall.this;
    }

    /**
     * Determines if the current call is in the process of merging with another call or conference.
     *
     * @return {@code true} if in the process of merging.
     */
    private boolean isMerging() {
        return mMergePeer != null || mMergeHost != null;
    }

    /**
     * Determines if the current call is the host of the merge.
     *
     * @return {@code true} if the call is the merge host.
     */
    private boolean isMergeHost() {
        return mMergePeer != null && mMergeHost == null;
    }

    /**
     * Determines if the current call is the peer of the merge.
     *
     * @return {@code true} if the call is the merge peer.
     */
    private boolean isMergePeer() {
        return mMergePeer == null && mMergeHost != null;
    }

    /**
     * Determines if the call session is pending merge into a conference or not.
     *
     * @return {@code true} if a merge into a conference is pending, {@code false} otherwise.
     */
    public boolean isCallSessionMergePending() {
        return mCallSessionMergePending;
    }

    /**
     * Sets flag indicating whether the call session is pending merge into a conference or not.
     *
     * @param callSessionMergePending {@code true} if a merge into the conference is pending,
     *      {@code false} otherwise.
     */
    private void setCallSessionMergePending(boolean callSessionMergePending) {
        mCallSessionMergePending = callSessionMergePending;
    }

    /**
     * Determines if there is a conference merge in process.  If there is a merge in process,
     * determines if both the merge host and peer sessions have completed the merge process.  This
     * means that we have received terminate or hold signals for the sessions, indicating that they
     * are no longer in the process of being merged into the conference.
     * <p>
     * The sessions are considered to have merged if: both calls still have merge peer/host
     * relationships configured,  both sessions are not waiting to be merged into the conference,
     * and the transient conference session is alive in the case of an initial conference.
     *
     * @return {@code true} where the host and peer sessions have finished merging into the
     *      conference, {@code false} if the merge has not yet completed, and {@code false} if there
     *      is no conference merge in progress.
     */
    private boolean shouldProcessConferenceResult() {
        boolean areMergeTriggersDone = false;

        synchronized (ImsCall.this) {
            // if there is a merge going on, then the merge host/peer relationships should have been
            // set up.  This works for both the initial conference or merging a call into an
            // existing conference.
            if (!isMergeHost() && !isMergePeer()) {
                if (CONF_DBG) {
                    loge("shouldProcessConferenceResult :: no merge in progress");
                }
                return false;
            }

            // There is a merge in progress, so check the sessions to ensure:
            // 1. Both calls have completed being merged (or failing to merge) into the conference.
            // 2. The transient conference session is alive.
            if (isMergeHost()) {
                if (CONF_DBG) {
                    logi("shouldProcessConferenceResult :: We are a merge host");
                    logi("shouldProcessConferenceResult :: Here is the merge peer=" + mMergePeer);
                }
                areMergeTriggersDone = !isCallSessionMergePending() &&
                        !mMergePeer.isCallSessionMergePending();
                if (!isMultiparty()) {
                    // Only check the transient session when there is no existing conference
                    areMergeTriggersDone &= isSessionAlive(mTransientConferenceSession);
                }
            } else if (isMergePeer()) {
                if (CONF_DBG) {
                    logi("shouldProcessConferenceResult :: We are a merge peer");
                    logi("shouldProcessConferenceResult :: Here is the merge host=" + mMergeHost);
                }
                areMergeTriggersDone = !isCallSessionMergePending() &&
                        !mMergeHost.isCallSessionMergePending();
                if (!mMergeHost.isMultiparty()) {
                    // Only check the transient session when there is no existing conference
                    areMergeTriggersDone &= isSessionAlive(mMergeHost.mTransientConferenceSession);
                } else {
                    // This else block is a special case for Verizon to handle these steps
                    // 1. Establish a conference call.
                    // 2. Add a new call (conference in in BG)
                    // 3. Swap (conference active on FG)
                    // 4. Merge
                    // What happens here is that the BG call gets a terminated callback
                    // because it was added to the conference. I've seen where
                    // the FG gets no callback at all because its already active.
                    // So if we continue to wait for it to set its isCallSessionMerging
                    // flag to false...we'll be waiting forever.
                    areMergeTriggersDone = !isCallSessionMergePending();
                }
            } else {
                // Realistically this shouldn't happen, but best to be safe.
                loge("shouldProcessConferenceResult : merge in progress but call is neither" +
                        " host nor peer.");
            }
            if (CONF_DBG) {
                logi("shouldProcessConferenceResult :: returning:" +
                        (areMergeTriggersDone ? "true" : "false"));
            }
        }
        return areMergeTriggersDone;
    }

    /**
     * Provides a string representation of the {@link ImsCall}.  Primarily intended for use in log
     * statements.
     *
     * @return String representation of call.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[ImsCall objId:");
        sb.append(System.identityHashCode(this));
        sb.append(" onHold:");
        sb.append(isOnHold() ? "Y" : "N");
        sb.append(" mute:");
        sb.append(isMuted() ? "Y" : "N");
        if (mCallProfile != null) {
            sb.append(" mCallProfile:" + mCallProfile);
            sb.append(" tech:");
            sb.append(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE));
        }
        sb.append(" updateRequest:");
        sb.append(updateRequestToString(mUpdateRequest));
        sb.append(" merging:");
        sb.append(isMerging() ? "Y" : "N");
        if (isMerging()) {
            if (isMergePeer()) {
                sb.append("P");
            } else {
                sb.append("H");
            }
        }
        sb.append(" merge action pending:");
        sb.append(isCallSessionMergePending() ? "Y" : "N");
        sb.append(" merged:");
        sb.append(isMerged() ? "Y" : "N");
        sb.append(" multiParty:");
        sb.append(isMultiparty() ? "Y" : "N");
        sb.append(" confHost:");
        sb.append(isConferenceHost() ? "Y" : "N");
        sb.append(" buried term:");
        sb.append(mSessionEndDuringMerge ? "Y" : "N");
        sb.append(" isVideo: ");
        sb.append(isVideoCall() ? "Y" : "N");
        sb.append(" wasVideo: ");
        sb.append(mWasVideoCall ? "Y" : "N");
        sb.append(" isWifi: ");
        sb.append(isWifiCall() ? "Y" : "N");
        sb.append(" session:");
        sb.append(mSession);
        sb.append(" transientSession:");
        sb.append(mTransientConferenceSession);
        sb.append("]");
        return sb.toString();
    }

    private void throwImsException(Throwable t, int code) throws ImsException {
        if (t instanceof ImsException) {
            throw (ImsException) t;
        } else {
            throw new ImsException(String.valueOf(code), t, code);
        }
    }

    /**
     * Append the ImsCall information to the provided string. Usefull for as a logging helper.
     * @param s The original string
     * @return The original string with {@code ImsCall} information appended to it.
     */
    private String appendImsCallInfoToString(String s) {
        StringBuilder sb = new StringBuilder();
        sb.append(s);
        sb.append(" ImsCall=");
        sb.append(ImsCall.this);
        return sb.toString();
    }

    /**
     * Updates {@link #mWasVideoCall} based on the current {@link ImsCallProfile} for the call.
     *
     * @param profile The current {@link ImsCallProfile} for the call.
     */
    private void trackVideoStateHistory(ImsCallProfile profile) {
        mWasVideoCall = mWasVideoCall || profile.isVideoCall();
    }

    /**
     * @return {@code true} if this call was a video call at some point in its life span,
     *      {@code false} otherwise.
     */
    public boolean wasVideoCall() {
        return mWasVideoCall;
    }

    /**
     * @return {@code true} if this call is a video call, {@code false} otherwise.
     */
    public boolean isVideoCall() {
        synchronized(mLockObj) {
            return mCallProfile != null && mCallProfile.isVideoCall();
        }
    }

    /**
     * Determines if the current call radio access technology is over WIFI.
     * Note: This depends on the RIL exposing the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE} extra.
     * This method is primarily intended to be used when checking if answering an incoming audio
     * call should cause a wifi video call to drop (e.g.
     * {@link android.telephony.CarrierConfigManager#
     * KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL} is set).
     *
     * @return {@code true} if the call is over WIFI, {@code false} otherwise.
     */
    public boolean isWifiCall() {
        synchronized(mLockObj) {
            if (mCallProfile == null) {
                return false;
            }
            int radioTechnology = getRadioTechnology();
            return radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
        }
    }

    /**
     * Determines the radio access technology for the {@link ImsCall}.
     * @return The {@link ServiceState} {@code RIL_RADIO_TECHNOLOGY_*} code in use.
     */
    public int getRadioTechnology() {
        synchronized(mLockObj) {
            if (mCallProfile == null) {
                return ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
            }
            String callType = mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE);
            if (callType == null || callType.isEmpty()) {
                callType = mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT);
            }

            // The RIL (sadly) sends us the EXTRA_CALL_RAT_TYPE as a string extra, rather than an
            // integer extra, so we need to parse it.
            int radioTechnology = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
            try {
                radioTechnology = Integer.parseInt(callType);
            } catch (NumberFormatException nfe) {
                radioTechnology = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
            }

            return radioTechnology;
        }
    }

    /**
     * Log a string to the radio buffer at the info level.
     * @param s The message to log
     */
    private void logi(String s) {
        Log.i(TAG, appendImsCallInfoToString(s));
    }

    /**
     * Log a string to the radio buffer at the debug level.
     * @param s The message to log
     */
    private void logd(String s) {
        Log.d(TAG, appendImsCallInfoToString(s));
    }

    /**
     * Log a string to the radio buffer at the verbose level.
     * @param s The message to log
     */
    private void logv(String s) {
        Log.v(TAG, appendImsCallInfoToString(s));
    }

    /**
     * Log a string to the radio buffer at the error level.
     * @param s The message to log
     */
    private void loge(String s) {
        Log.e(TAG, appendImsCallInfoToString(s));
    }

    /**
     * Log a string to the radio buffer at the error level with a throwable
     * @param s The message to log
     * @param t The associated throwable
     */
    private void loge(String s, Throwable t) {
        Log.e(TAG, appendImsCallInfoToString(s), t);
    }
}
