/*
 * 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.internal.telephony.imsphone;

import android.content.Context;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.Registrant;
import android.os.SystemClock;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsStreamMediaProfile;
import android.text.TextUtils;

import com.android.ims.ImsCall;
import com.android.ims.ImsException;
import com.android.ims.internal.ImsVideoCallProviderWrapper;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.UUSInfo;

import java.util.Objects;

/**
 * {@hide}
 */
public class ImsPhoneConnection extends Connection implements
        ImsVideoCallProviderWrapper.ImsVideoProviderWrapperCallback {

    private static final String LOG_TAG = "ImsPhoneConnection";
    private static final boolean DBG = true;

    //***** Instance Variables

    private ImsPhoneCallTracker mOwner;
    private ImsPhoneCall mParent;
    private ImsCall mImsCall;
    private Bundle mExtras = new Bundle();

    private boolean mDisconnected;

    /*
    int mIndex;          // index in ImsPhoneCallTracker.connections[], -1 if unassigned
                        // The GSM index is 1 + this
    */

    /*
     * These time/timespan values are based on System.currentTimeMillis(),
     * i.e., "wall clock" time.
     */
    private long mDisconnectTime;

    private UUSInfo mUusInfo;
    private Handler mHandler;
    private Messenger mHandlerMessenger;

    private PowerManager.WakeLock mPartialWakeLock;

    // The cached connect time of the connection when it turns into a conference.
    private long mConferenceConnectTime = 0;

    // The cached delay to be used between DTMF tones fetched from carrier config.
    private int mDtmfToneDelay = 0;

    private boolean mIsEmergency = false;

    /**
     * Used to indicate that video state changes detected by
     * {@link #updateMediaCapabilities(ImsCall)} should be ignored.  When a video state change from
     * unpaused to paused occurs, we set this flag and then update the existing video state when
     * new {@link #onReceiveSessionModifyResponse(int, VideoProfile, VideoProfile)} callbacks come
     * in.  When the video un-pauses we continue receiving the video state updates.
     */
    private boolean mShouldIgnoreVideoStateChanges = false;

    private ImsVideoCallProviderWrapper mImsVideoCallProviderWrapper;

    private int mPreciseDisconnectCause = 0;

    private ImsRttTextHandler mRttTextHandler;
    private android.telecom.Connection.RttTextStream mRttTextStream;
    // This reflects the RTT status as reported to us by the IMS stack via the media profile.
    private boolean mIsRttEnabledForCall = false;

    /**
     * Used to indicate that this call is in the midst of being merged into a conference.
     */
    private boolean mIsMergeInProcess = false;

    /**
     * Used as an override to determine whether video is locally available for this call.
     * This allows video availability to be overridden in the case that the modem says video is
     * currently available, but mobile data is off and the carrier is metering data for video
     * calls.
     */
    private boolean mIsVideoEnabled = true;

    //***** Event Constants
    private static final int EVENT_DTMF_DONE = 1;
    private static final int EVENT_PAUSE_DONE = 2;
    private static final int EVENT_NEXT_POST_DIAL = 3;
    private static final int EVENT_WAKE_LOCK_TIMEOUT = 4;
    private static final int EVENT_DTMF_DELAY_DONE = 5;

    //***** Constants
    private static final int PAUSE_DELAY_MILLIS = 3 * 1000;
    private static final int WAKE_LOCK_TIMEOUT_MILLIS = 60*1000;

    //***** Inner Classes

    class MyHandler extends Handler {
        MyHandler(Looper l) {super(l);}

        @Override
        public void
        handleMessage(Message msg) {

            switch (msg.what) {
                case EVENT_NEXT_POST_DIAL:
                case EVENT_DTMF_DELAY_DONE:
                case EVENT_PAUSE_DONE:
                    processNextPostDialChar();
                    break;
                case EVENT_WAKE_LOCK_TIMEOUT:
                    releaseWakeLock();
                    break;
                case EVENT_DTMF_DONE:
                    // We may need to add a delay specified by carrier between DTMF tones that are
                    // sent out.
                    mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_DTMF_DELAY_DONE),
                            mDtmfToneDelay);
                    break;
            }
        }
    }

    //***** Constructors

    /** This is probably an MT call */
    public ImsPhoneConnection(Phone phone, ImsCall imsCall, ImsPhoneCallTracker ct,
           ImsPhoneCall parent, boolean isUnknown) {
        super(PhoneConstants.PHONE_TYPE_IMS);
        createWakeLock(phone.getContext());
        acquireWakeLock();

        mOwner = ct;
        mHandler = new MyHandler(mOwner.getLooper());
        mHandlerMessenger = new Messenger(mHandler);
        mImsCall = imsCall;

        if ((imsCall != null) && (imsCall.getCallProfile() != null)) {
            mAddress = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_OI);
            mCnapName = imsCall.getCallProfile().getCallExtra(ImsCallProfile.EXTRA_CNA);
            mNumberPresentation = ImsCallProfile.OIRToPresentation(
                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_OIR));
            mCnapNamePresentation = ImsCallProfile.OIRToPresentation(
                    imsCall.getCallProfile().getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
            updateMediaCapabilities(imsCall);
        } else {
            mNumberPresentation = PhoneConstants.PRESENTATION_UNKNOWN;
            mCnapNamePresentation = PhoneConstants.PRESENTATION_UNKNOWN;
        }

        mIsIncoming = !isUnknown;
        mCreateTime = System.currentTimeMillis();
        mUusInfo = null;

        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
        // connection is not likely to be associated with a TelephonyConnection yet).
        updateExtras(imsCall);

        mParent = parent;
        mParent.attach(this,
                (mIsIncoming? ImsPhoneCall.State.INCOMING: ImsPhoneCall.State.DIALING));

        fetchDtmfToneDelay(phone);

        if (phone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
            setAudioModeIsVoip(true);
        }
    }

    /** This is an MO call, created when dialing */
    public ImsPhoneConnection(Phone phone, String dialString, ImsPhoneCallTracker ct,
            ImsPhoneCall parent, boolean isEmergency) {
        super(PhoneConstants.PHONE_TYPE_IMS);
        createWakeLock(phone.getContext());
        acquireWakeLock();

        mOwner = ct;
        mHandler = new MyHandler(mOwner.getLooper());

        mDialString = dialString;

        mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
        mPostDialString = PhoneNumberUtils.extractPostDialPortion(dialString);

        //mIndex = -1;

        mIsIncoming = false;
        mCnapName = null;
        mCnapNamePresentation = PhoneConstants.PRESENTATION_ALLOWED;
        mNumberPresentation = PhoneConstants.PRESENTATION_ALLOWED;
        mCreateTime = System.currentTimeMillis();

        mParent = parent;
        parent.attachFake(this, ImsPhoneCall.State.DIALING);

        mIsEmergency = isEmergency;

        fetchDtmfToneDelay(phone);

        if (phone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_use_voip_mode_for_ims)) {
            setAudioModeIsVoip(true);
        }
    }

    public void dispose() {
    }

    static boolean
    equalsHandlesNulls (Object a, Object b) {
        return (a == null) ? (b == null) : a.equals (b);
    }

    static boolean
    equalsBaseDialString (String a, String b) {
        return (a == null) ? (b == null) : (b != null && a.startsWith (b));
    }

    private int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
        Rlog.i(LOG_TAG, "applyLocalCallCapabilities - localProfile = " + localProfile);
        capabilities = removeCapability(capabilities,
                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);

        if (!mIsVideoEnabled) {
            Rlog.i(LOG_TAG, "applyLocalCallCapabilities - disabling video (overidden)");
            return capabilities;
        }
        switch (localProfile.mCallType) {
            case ImsCallProfile.CALL_TYPE_VT:
                // Fall-through
            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
                capabilities = addCapability(capabilities,
                        Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);
                break;
        }
        return capabilities;
    }

    private static int applyRemoteCallCapabilities(ImsCallProfile remoteProfile, int capabilities) {
        Rlog.w(LOG_TAG, "applyRemoteCallCapabilities - remoteProfile = "+remoteProfile);
        capabilities = removeCapability(capabilities,
                Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);

        switch (remoteProfile.mCallType) {
            case ImsCallProfile.CALL_TYPE_VT:
                // fall-through
            case ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE:
                capabilities = addCapability(capabilities,
                        Connection.Capability.SUPPORTS_VT_REMOTE_BIDIRECTIONAL);
                break;
        }
        return capabilities;
    }

    @Override
    public String getOrigDialString(){
        return mDialString;
    }

    @Override
    public ImsPhoneCall getCall() {
        return mParent;
    }

    @Override
    public long getDisconnectTime() {
        return mDisconnectTime;
    }

    @Override
    public long getHoldingStartTime() {
        return mHoldingStartTime;
    }

    @Override
    public long getHoldDurationMillis() {
        if (getState() != ImsPhoneCall.State.HOLDING) {
            // If not holding, return 0
            return 0;
        } else {
            return SystemClock.elapsedRealtime() - mHoldingStartTime;
        }
    }

    public void setDisconnectCause(int cause) {
        mCause = cause;
    }

    @Override
    public String getVendorDisconnectCause() {
      return null;
    }

    public ImsPhoneCallTracker getOwner () {
        return mOwner;
    }

    @Override
    public ImsPhoneCall.State getState() {
        if (mDisconnected) {
            return ImsPhoneCall.State.DISCONNECTED;
        } else {
            return super.getState();
        }
    }

    @Override
    public void deflect(String number) throws CallStateException {
        if (mParent.getState().isRinging()) {
            try {
                if (mImsCall != null) {
                    mImsCall.deflect(number);
                } else {
                    throw new CallStateException("no valid ims call to deflect");
                }
            } catch (ImsException e) {
                throw new CallStateException("cannot deflect call");
            }
        } else {
            throw new CallStateException("phone not ringing");
        }
    }

    @Override
    public void hangup() throws CallStateException {
        if (!mDisconnected) {
            mOwner.hangup(this);
        } else {
            throw new CallStateException ("disconnected");
        }
    }

    @Override
    public void separate() throws CallStateException {
        throw new CallStateException ("not supported");
    }

    @Override
    public void proceedAfterWaitChar() {
        if (mPostDialState != PostDialState.WAIT) {
            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
                    + "getPostDialState() to be WAIT but was " + mPostDialState);
            return;
        }

        setPostDialState(PostDialState.STARTED);

        processNextPostDialChar();
    }

    @Override
    public void proceedAfterWildChar(String str) {
        if (mPostDialState != PostDialState.WILD) {
            Rlog.w(LOG_TAG, "ImsPhoneConnection.proceedAfterWaitChar(): Expected "
                    + "getPostDialState() to be WILD but was " + mPostDialState);
            return;
        }

        setPostDialState(PostDialState.STARTED);

        // make a new postDialString, with the wild char replacement string
        // at the beginning, followed by the remaining postDialString.

        StringBuilder buf = new StringBuilder(str);
        buf.append(mPostDialString.substring(mNextPostDialChar));
        mPostDialString = buf.toString();
        mNextPostDialChar = 0;
        if (Phone.DEBUG_PHONE) {
            Rlog.d(LOG_TAG, "proceedAfterWildChar: new postDialString is " +
                    mPostDialString);
        }

        processNextPostDialChar();
    }

    @Override
    public void cancelPostDial() {
        setPostDialState(PostDialState.CANCELLED);
    }

    /**
     * Called when this Connection is being hung up locally (eg, user pressed "end")
     */
    void
    onHangupLocal() {
        mCause = DisconnectCause.LOCAL;
    }

    /** Called when the connection has been disconnected */
    @Override
    public boolean onDisconnect(int cause) {
        Rlog.d(LOG_TAG, "onDisconnect: cause=" + cause);
        if (mCause != DisconnectCause.LOCAL || cause == DisconnectCause.INCOMING_REJECTED) {
            mCause = cause;
        }
        return onDisconnect();
    }

    public boolean onDisconnect() {
        boolean changed = false;

        if (!mDisconnected) {
            //mIndex = -1;

            mDisconnectTime = System.currentTimeMillis();
            mDuration = SystemClock.elapsedRealtime() - mConnectTimeReal;
            mDisconnected = true;

            mOwner.mPhone.notifyDisconnect(this);
            notifyDisconnect(mCause);

            if (mParent != null) {
                changed = mParent.connectionDisconnected(this);
            } else {
                Rlog.d(LOG_TAG, "onDisconnect: no parent");
            }
            synchronized (this) {
                if (mImsCall != null) mImsCall.close();
                mImsCall = null;
            }
        }
        releaseWakeLock();
        return changed;
    }

    /**
     * An incoming or outgoing call has connected
     */
    void
    onConnectedInOrOut() {
        mConnectTime = System.currentTimeMillis();
        mConnectTimeReal = SystemClock.elapsedRealtime();
        mDuration = 0;

        if (Phone.DEBUG_PHONE) {
            Rlog.d(LOG_TAG, "onConnectedInOrOut: connectTime=" + mConnectTime);
        }

        if (!mIsIncoming) {
            // outgoing calls only
            processNextPostDialChar();
        }
        releaseWakeLock();
    }

    /*package*/ void
    onStartedHolding() {
        mHoldingStartTime = SystemClock.elapsedRealtime();
    }
    /**
     * Performs the appropriate action for a post-dial char, but does not
     * notify application. returns false if the character is invalid and
     * should be ignored
     */
    private boolean
    processPostDialChar(char c) {
        if (PhoneNumberUtils.is12Key(c)) {
            Message dtmfComplete = mHandler.obtainMessage(EVENT_DTMF_DONE);
            dtmfComplete.replyTo = mHandlerMessenger;
            mOwner.sendDtmf(c, dtmfComplete);
        } else if (c == PhoneNumberUtils.PAUSE) {
            // From TS 22.101:
            // It continues...
            // Upon the called party answering the UE shall send the DTMF digits
            // automatically to the network after a delay of 3 seconds( 20 ).
            // The digits shall be sent according to the procedures and timing
            // specified in 3GPP TS 24.008 [13]. The first occurrence of the
            // "DTMF Control Digits Separator" shall be used by the ME to
            // distinguish between the addressing digits (i.e. the phone number)
            // and the DTMF digits. Upon subsequent occurrences of the
            // separator,
            // the UE shall pause again for 3 seconds ( 20 ) before sending
            // any further DTMF digits.
            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_PAUSE_DONE),
                    PAUSE_DELAY_MILLIS);
        } else if (c == PhoneNumberUtils.WAIT) {
            setPostDialState(PostDialState.WAIT);
        } else if (c == PhoneNumberUtils.WILD) {
            setPostDialState(PostDialState.WILD);
        } else {
            return false;
        }

        return true;
    }

    @Override
    protected void finalize() {
        releaseWakeLock();
    }

    private void
    processNextPostDialChar() {
        char c = 0;
        Registrant postDialHandler;

        if (mPostDialState == PostDialState.CANCELLED) {
            //Rlog.d(LOG_TAG, "##### processNextPostDialChar: postDialState == CANCELLED, bail");
            return;
        }

        if (mPostDialString == null || mPostDialString.length() <= mNextPostDialChar) {
            setPostDialState(PostDialState.COMPLETE);

            // notifyMessage.arg1 is 0 on complete
            c = 0;
        } else {
            boolean isValid;

            setPostDialState(PostDialState.STARTED);

            c = mPostDialString.charAt(mNextPostDialChar++);

            isValid = processPostDialChar(c);

            if (!isValid) {
                // Will call processNextPostDialChar
                mHandler.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
                // Don't notify application
                Rlog.e(LOG_TAG, "processNextPostDialChar: c=" + c + " isn't valid!");
                return;
            }
        }

        notifyPostDialListenersNextChar(c);

        // TODO: remove the following code since the handler no longer executes anything.
        postDialHandler = mOwner.mPhone.getPostDialHandler();

        Message notifyMessage;

        if (postDialHandler != null
                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
            // The AsyncResult.result is the Connection object
            PostDialState state = mPostDialState;
            AsyncResult ar = AsyncResult.forMessage(notifyMessage);
            ar.result = this;
            ar.userObj = state;

            // arg1 is the character that was/is being processed
            notifyMessage.arg1 = c;

            //Rlog.v(LOG_TAG,
            //      "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
            notifyMessage.sendToTarget();
        }
    }

    /**
     * Set post dial state and acquire wake lock while switching to "started"
     * state, the wake lock will be released if state switches out of "started"
     * state or after WAKE_LOCK_TIMEOUT_MILLIS.
     * @param s new PostDialState
     */
    private void setPostDialState(PostDialState s) {
        if (mPostDialState != PostDialState.STARTED
                && s == PostDialState.STARTED) {
            acquireWakeLock();
            Message msg = mHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT);
            mHandler.sendMessageDelayed(msg, WAKE_LOCK_TIMEOUT_MILLIS);
        } else if (mPostDialState == PostDialState.STARTED
                && s != PostDialState.STARTED) {
            mHandler.removeMessages(EVENT_WAKE_LOCK_TIMEOUT);
            releaseWakeLock();
        }
        mPostDialState = s;
        notifyPostDialListeners();
    }

    private void
    createWakeLock(Context context) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
    }

    private void
    acquireWakeLock() {
        Rlog.d(LOG_TAG, "acquireWakeLock");
        mPartialWakeLock.acquire();
    }

    void
    releaseWakeLock() {
        if (mPartialWakeLock != null) {
            synchronized (mPartialWakeLock) {
                if (mPartialWakeLock.isHeld()) {
                    Rlog.d(LOG_TAG, "releaseWakeLock");
                    mPartialWakeLock.release();
                }
            }
        }
    }

    private void fetchDtmfToneDelay(Phone phone) {
        CarrierConfigManager configMgr = (CarrierConfigManager)
                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle b = configMgr.getConfigForSubId(phone.getSubId());
        if (b != null) {
            mDtmfToneDelay = b.getInt(CarrierConfigManager.KEY_IMS_DTMF_TONE_DELAY_INT);
        }
    }

    @Override
    public int getNumberPresentation() {
        return mNumberPresentation;
    }

    @Override
    public UUSInfo getUUSInfo() {
        return mUusInfo;
    }

    @Override
    public Connection getOrigConnection() {
        return null;
    }

    @Override
    public synchronized boolean isMultiparty() {
        return mImsCall != null && mImsCall.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.
     */
    @Override
    public synchronized boolean isConferenceHost() {
        return mImsCall != null && mImsCall.isConferenceHost();
    }

    @Override
    public boolean isMemberOfPeerConference() {
        return !isConferenceHost();
    }

    public synchronized ImsCall getImsCall() {
        return mImsCall;
    }

    public synchronized void setImsCall(ImsCall imsCall) {
        mImsCall = imsCall;
    }

    public void changeParent(ImsPhoneCall parent) {
        mParent = parent;
    }

    /**
     * @return {@code true} if the {@link ImsPhoneConnection} or its media capabilities have been
     *     changed, and {@code false} otherwise.
     */
    public boolean update(ImsCall imsCall, ImsPhoneCall.State state) {
        if (state == ImsPhoneCall.State.ACTIVE) {
            // If the state of the call is active, but there is a pending request to the RIL to hold
            // the call, we will skip this update.  This is really a signalling delay or failure
            // from the RIL, but we will prevent it from going through as we will end up erroneously
            // making this call active when really it should be on hold.
            if (imsCall.isPendingHold()) {
                Rlog.w(LOG_TAG, "update : state is ACTIVE, but call is pending hold, skipping");
                return false;
            }

            if (mParent.getState().isRinging() || mParent.getState().isDialing()) {
                onConnectedInOrOut();
            }

            if (mParent.getState().isRinging() || mParent == mOwner.mBackgroundCall) {
                //mForegroundCall should be IDLE
                //when accepting WAITING call
                //before accept WAITING call,
                //the ACTIVE call should be held ahead
                mParent.detach(this);
                mParent = mOwner.mForegroundCall;
                mParent.attach(this);
            }
        } else if (state == ImsPhoneCall.State.HOLDING) {
            onStartedHolding();
        }

        boolean updateParent = mParent.update(this, imsCall, state);
        boolean updateAddressDisplay = updateAddressDisplay(imsCall);
        boolean updateMediaCapabilities = updateMediaCapabilities(imsCall);
        boolean updateExtras = updateExtras(imsCall);

        return updateParent || updateAddressDisplay || updateMediaCapabilities || updateExtras;
    }

    @Override
    public int getPreciseDisconnectCause() {
        return mPreciseDisconnectCause;
    }

    public void setPreciseDisconnectCause(int cause) {
        mPreciseDisconnectCause = cause;
    }

    /**
     * Notifies this Connection of a request to disconnect a participant of the conference managed
     * by the connection.
     *
     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
     */
    @Override
    public void onDisconnectConferenceParticipant(Uri endpoint) {
        ImsCall imsCall = getImsCall();
        if (imsCall == null) {
            return;
        }
        try {
            imsCall.removeParticipants(new String[]{endpoint.toString()});
        } catch (ImsException e) {
            // No session in place -- no change
            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
                    "Failed to disconnect endpoint = " + endpoint);
        }
    }

    /**
     * Sets the conference connect time.  Used when an {@code ImsConference} is created to out of
     * this phone connection.
     *
     * @param conferenceConnectTime The conference connect time.
     */
    public void setConferenceConnectTime(long conferenceConnectTime) {
        mConferenceConnectTime = conferenceConnectTime;
    }

    /**
     * @return The conference connect time.
     */
    public long getConferenceConnectTime() {
        return mConferenceConnectTime;
    }

    /**
     * Check for a change in the address display related fields for the {@link ImsCall}, and
     * update the {@link ImsPhoneConnection} with this information.
     *
     * @param imsCall The call to check for changes in address display fields.
     * @return Whether the address display fields have been changed.
     */
    public boolean updateAddressDisplay(ImsCall imsCall) {
        if (imsCall == null) {
            return false;
        }

        boolean changed = false;
        ImsCallProfile callProfile = imsCall.getCallProfile();
        if (callProfile != null && isIncoming()) {
            // Only look for changes to the address for incoming calls.  The originating identity
            // can change for outgoing calls due to, for example, a call being forwarded to
            // voicemail.  This address change does not need to be presented to the user.
            String address = callProfile.getCallExtra(ImsCallProfile.EXTRA_OI);
            String name = callProfile.getCallExtra(ImsCallProfile.EXTRA_CNA);
            int nump = ImsCallProfile.OIRToPresentation(
                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_OIR));
            int namep = ImsCallProfile.OIRToPresentation(
                    callProfile.getCallExtraInt(ImsCallProfile.EXTRA_CNAP));
            if (Phone.DEBUG_PHONE) {
                Rlog.d(LOG_TAG, "updateAddressDisplay: callId = " + getTelecomCallId()
                        + " address = " + Rlog.pii(LOG_TAG, address) + " name = "
                        + Rlog.pii(LOG_TAG, name) + " nump = " + nump + " namep = " + namep);
            }
            if (!mIsMergeInProcess) {
                // Only process changes to the name and address when a merge is not in process.
                // When call A initiated a merge with call B to form a conference C, there is a
                // point in time when the ImsCall transfers the conference call session into A,
                // at which point the ImsConferenceController creates the conference in Telecom.
                // For some carriers C will have a unique conference URI address.  Swapping the
                // conference session into A, which is about to be disconnected, to be logged to
                // the call log using the conference address.  To prevent this we suppress updates
                // to the call address while a merge is in process.
                if (!equalsBaseDialString(mAddress, address)) {
                    mAddress = address;
                    changed = true;
                }
                if (TextUtils.isEmpty(name)) {
                    if (!TextUtils.isEmpty(mCnapName)) {
                        mCnapName = "";
                        changed = true;
                    }
                } else if (!name.equals(mCnapName)) {
                    mCnapName = name;
                    changed = true;
                }
                if (mNumberPresentation != nump) {
                    mNumberPresentation = nump;
                    changed = true;
                }
                if (mCnapNamePresentation != namep) {
                    mCnapNamePresentation = namep;
                    changed = true;
                }
            }
        }
        return changed;
    }

    /**
     * Check for a change in the video capabilities and audio quality for the {@link ImsCall}, and
     * update the {@link ImsPhoneConnection} with this information.
     *
     * @param imsCall The call to check for changes in media capabilities.
     * @return Whether the media capabilities have been changed.
     */
    public boolean updateMediaCapabilities(ImsCall imsCall) {
        if (imsCall == null) {
            return false;
        }

        boolean changed = false;

        try {
            // The actual call profile (negotiated between local and peer).
            ImsCallProfile negotiatedCallProfile = imsCall.getCallProfile();

            if (negotiatedCallProfile != null) {
                int oldVideoState = getVideoState();
                int newVideoState = ImsCallProfile
                        .getVideoStateFromImsCallProfile(negotiatedCallProfile);

                if (oldVideoState != newVideoState) {
                    // The video state has changed.  See also code in onReceiveSessionModifyResponse
                    // below.  When the video enters a paused state, subsequent changes to the video
                    // state will not be reported by the modem.  In onReceiveSessionModifyResponse
                    // we will be updating the current video state while paused to include any
                    // changes the modem reports via the video provider.  When the video enters an
                    // unpaused state, we will resume passing the video states from the modem as is.
                    if (VideoProfile.isPaused(oldVideoState) &&
                            !VideoProfile.isPaused(newVideoState)) {
                        // Video entered un-paused state; recognize updates from now on; we want to
                        // ensure that the new un-paused state is propagated to Telecom, so change
                        // this now.
                        mShouldIgnoreVideoStateChanges = false;
                    }

                    if (!mShouldIgnoreVideoStateChanges) {
                        updateVideoState(newVideoState);
                        changed = true;
                    } else {
                        Rlog.d(LOG_TAG, "updateMediaCapabilities - ignoring video state change " +
                                "due to paused state.");
                    }

                    if (!VideoProfile.isPaused(oldVideoState) &&
                            VideoProfile.isPaused(newVideoState)) {
                        // Video entered pause state; ignore updates until un-paused.  We do this
                        // after setVideoState is called above to ensure Telecom is notified that
                        // the device has entered paused state.
                        mShouldIgnoreVideoStateChanges = true;
                    }
                }

                if (negotiatedCallProfile.mMediaProfile != null) {
                    mIsRttEnabledForCall = negotiatedCallProfile.mMediaProfile.isRttCall();

                    if (mIsRttEnabledForCall && mRttTextHandler == null) {
                        Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT on, profile="
                                + negotiatedCallProfile);
                        startRttTextProcessing();
                        onRttInitiated();
                        changed = true;
                    } else if (!mIsRttEnabledForCall && mRttTextHandler != null) {
                        Rlog.d(LOG_TAG, "updateMediaCapabilities -- turning RTT off, profile="
                                + negotiatedCallProfile);
                        mRttTextHandler.tearDown();
                        mRttTextHandler = null;
                        onRttTerminated();
                        changed = true;
                    }
                }
            }

            // Check for a change in the capabilities for the call and update
            // {@link ImsPhoneConnection} with this information.
            int capabilities = getConnectionCapabilities();

            // Use carrier config to determine if downgrading directly to audio-only is supported.
            if (mOwner.isCarrierDowngradeOfVtCallSupported()) {
                capabilities = addCapability(capabilities,
                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
            } else {
                capabilities = removeCapability(capabilities,
                        Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE |
                                Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL);
            }

            // Get the current local call capabilities which might be voice or video or both.
            ImsCallProfile localCallProfile = imsCall.getLocalCallProfile();
            Rlog.v(LOG_TAG, "update localCallProfile=" + localCallProfile);
            if (localCallProfile != null) {
                capabilities = applyLocalCallCapabilities(localCallProfile, capabilities);
            }

            // Get the current remote call capabilities which might be voice or video or both.
            ImsCallProfile remoteCallProfile = imsCall.getRemoteCallProfile();
            Rlog.v(LOG_TAG, "update remoteCallProfile=" + remoteCallProfile);
            if (remoteCallProfile != null) {
                capabilities = applyRemoteCallCapabilities(remoteCallProfile, capabilities);
            }
            if (getConnectionCapabilities() != capabilities) {
                setConnectionCapabilities(capabilities);
                changed = true;
            }

            int newAudioQuality =
                    getAudioQualityFromCallProfile(localCallProfile, remoteCallProfile);
            if (getAudioQuality() != newAudioQuality) {
                setAudioQuality(newAudioQuality);
                changed = true;
            }
        } catch (ImsException e) {
            // No session in place -- no change
        }

        return changed;
    }

    private void updateVideoState(int newVideoState) {
        if (mImsVideoCallProviderWrapper != null) {
            mImsVideoCallProviderWrapper.onVideoStateChanged(newVideoState);
        }
        setVideoState(newVideoState);
    }

    public void sendRttModifyRequest(android.telecom.Connection.RttTextStream textStream) {
        getImsCall().sendRttModifyRequest();
        setCurrentRttTextStream(textStream);
    }

    /**
     * Sends the user's response to a remotely-issued RTT upgrade request
     *
     * @param textStream A valid {@link android.telecom.Connection.RttTextStream} if the user
     *                   accepts, {@code null} if not.
     */
    public void sendRttModifyResponse(android.telecom.Connection.RttTextStream textStream) {
        boolean accept = textStream != null;
        ImsCall imsCall = getImsCall();

        imsCall.sendRttModifyResponse(accept);
        if (accept) {
            setCurrentRttTextStream(textStream);
        } else {
            Rlog.e(LOG_TAG, "sendRttModifyResponse: foreground call has no connections");
        }
    }

    public void onRttMessageReceived(String message) {
        synchronized (this) {
            if (mRttTextHandler == null) {
                Rlog.w(LOG_TAG, "onRttMessageReceived: RTT text handler not available."
                        + " Attempting to create one.");
                if (mRttTextStream == null) {
                    Rlog.e(LOG_TAG, "onRttMessageReceived:"
                            + " Unable to process incoming message. No textstream available");
                    return;
                }
                createRttTextHandler();
            }
        }
        mRttTextHandler.sendToInCall(message);
    }

    public void setCurrentRttTextStream(android.telecom.Connection.RttTextStream rttTextStream) {
        synchronized (this) {
            mRttTextStream = rttTextStream;
            if (mRttTextHandler == null && mIsRttEnabledForCall) {
                Rlog.i(LOG_TAG, "setCurrentRttTextStream: Creating a text handler");
                createRttTextHandler();
            }
        }
    }

    public boolean hasRttTextStream() {
        return mRttTextStream != null;
    }

    public boolean isRttEnabledForCall() {
        return mIsRttEnabledForCall;
    }

    public void startRttTextProcessing() {
        synchronized (this) {
            if (mRttTextStream == null) {
                Rlog.w(LOG_TAG, "startRttTextProcessing: no RTT text stream. Ignoring.");
                return;
            }
            if (mRttTextHandler != null) {
                Rlog.w(LOG_TAG, "startRttTextProcessing: RTT text handler already exists");
                return;
            }
            createRttTextHandler();
        }
    }

    // Make sure to synchronize on ImsPhoneConnection.this before calling.
    private void createRttTextHandler() {
        mRttTextHandler = new ImsRttTextHandler(Looper.getMainLooper(),
                (message) -> getImsCall().sendRttMessage(message));
        mRttTextHandler.initialize(mRttTextStream);
    }

    /**
     * Updates the wifi state based on the {@link ImsCallProfile#EXTRA_CALL_RAT_TYPE}.
     * The call is considered to be a WIFI call if the extra value is
     * {@link ServiceState#RIL_RADIO_TECHNOLOGY_IWLAN}.
     *
     * @param extras The ImsCallProfile extras.
     */
    private void updateWifiStateFromExtras(Bundle extras) {
        if (extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE) ||
                extras.containsKey(ImsCallProfile.EXTRA_CALL_RAT_TYPE_ALT)) {

            ImsCall call = getImsCall();
            boolean isWifi = false;
            if (call != null) {
                isWifi = call.isWifiCall();
            }

            // Report any changes
            if (isWifi() != isWifi) {
                setWifi(isWifi);
            }
        }
    }

    /**
     * Check for a change in call extras of {@link ImsCall}, and
     * update the {@link ImsPhoneConnection} accordingly.
     *
     * @param imsCall The call to check for changes in extras.
     * @return Whether the extras fields have been changed.
     */
     boolean updateExtras(ImsCall imsCall) {
        if (imsCall == null) {
            return false;
        }

        final ImsCallProfile callProfile = imsCall.getCallProfile();
        final Bundle extras = callProfile != null ? callProfile.mCallExtras : null;
        if (extras == null && DBG) {
            Rlog.d(LOG_TAG, "Call profile extras are null.");
        }

        final boolean changed = !areBundlesEqual(extras, mExtras);
        if (changed) {
            updateWifiStateFromExtras(extras);

            mExtras.clear();
            mExtras.putAll(extras);
            setConnectionExtras(mExtras);
        }
        return changed;
    }

    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
        if (extras == null || newExtras == null) {
            return extras == newExtras;
        }

        if (extras.size() != newExtras.size()) {
            return false;
        }

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

    /**
     * Determines the {@link ImsPhoneConnection} audio quality based on the local and remote
     * {@link ImsCallProfile}. Indicate a HD audio call if the local stream profile
     * is AMR_WB, EVRC_WB, EVS_WB, EVS_SWB, EVS_FB and
     * there is no remote restrict cause.
     *
     * @param localCallProfile The local call profile.
     * @param remoteCallProfile The remote call profile.
     * @return The audio quality.
     */
    private int getAudioQualityFromCallProfile(
            ImsCallProfile localCallProfile, ImsCallProfile remoteCallProfile) {
        if (localCallProfile == null || remoteCallProfile == null
                || localCallProfile.mMediaProfile == null) {
            return AUDIO_QUALITY_STANDARD;
        }

        final boolean isEvsCodecHighDef = (localCallProfile.mMediaProfile.mAudioQuality
                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_WB
                || localCallProfile.mMediaProfile.mAudioQuality
                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB
                || localCallProfile.mMediaProfile.mAudioQuality
                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVS_FB);

        final boolean isHighDef = (localCallProfile.mMediaProfile.mAudioQuality
                        == ImsStreamMediaProfile.AUDIO_QUALITY_AMR_WB
                || localCallProfile.mMediaProfile.mAudioQuality
                        == ImsStreamMediaProfile.AUDIO_QUALITY_EVRC_WB
                || isEvsCodecHighDef)
                && remoteCallProfile.mRestrictCause == ImsCallProfile.CALL_RESTRICT_CAUSE_NONE;
        return isHighDef ? AUDIO_QUALITY_HIGH_DEFINITION : AUDIO_QUALITY_STANDARD;
    }

    /**
     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
     * use in log statements.
     *
     * @return String representation of call.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[ImsPhoneConnection objId: ");
        sb.append(System.identityHashCode(this));
        sb.append(" telecomCallID: ");
        sb.append(getTelecomCallId());
        sb.append(" address: ");
        sb.append(Rlog.pii(LOG_TAG, getAddress()));
        sb.append(" ImsCall: ");
        synchronized (this) {
            if (mImsCall == null) {
                sb.append("null");
            } else {
                sb.append(mImsCall);
            }
        }
        sb.append("]");
        return sb.toString();
    }

    @Override
    public void setVideoProvider(android.telecom.Connection.VideoProvider videoProvider) {
        super.setVideoProvider(videoProvider);

        if (videoProvider instanceof ImsVideoCallProviderWrapper) {
            mImsVideoCallProviderWrapper = (ImsVideoCallProviderWrapper) videoProvider;
        }
    }

    /**
     * Indicates whether current phone connection is emergency or not
     * @return boolean: true if emergency, false otherwise
     */
    protected boolean isEmergency() {
        return mIsEmergency;
    }

    /**
     * Handles notifications from the {@link ImsVideoCallProviderWrapper} of session modification
     * responses received.
     *
     * @param status The status of the original request.
     * @param requestProfile The requested video profile.
     * @param responseProfile The response upon video profile.
     */
    @Override
    public void onReceiveSessionModifyResponse(int status, VideoProfile requestProfile,
            VideoProfile responseProfile) {
        if (status == android.telecom.Connection.VideoProvider.SESSION_MODIFY_REQUEST_SUCCESS &&
                mShouldIgnoreVideoStateChanges) {
            int currentVideoState = getVideoState();
            int newVideoState = responseProfile.getVideoState();

            // If the current video state is paused, the modem will not send us any changes to
            // the TX and RX bits of the video state.  Until the video is un-paused we will
            // "fake out" the video state by applying the changes that the modem reports via a
            // response.

            // First, find out whether there was a change to the TX or RX bits:
            int changedBits = currentVideoState ^ newVideoState;
            changedBits &= VideoProfile.STATE_BIDIRECTIONAL;
            if (changedBits == 0) {
                // No applicable change, bail out.
                return;
            }

            // Turn off any existing bits that changed.
            currentVideoState &= ~(changedBits & currentVideoState);
            // Turn on any new bits that turned on.
            currentVideoState |= changedBits & newVideoState;

            Rlog.d(LOG_TAG, "onReceiveSessionModifyResponse : received " +
                    VideoProfile.videoStateToString(requestProfile.getVideoState()) +
                    " / " +
                    VideoProfile.videoStateToString(responseProfile.getVideoState()) +
                    " while paused ; sending new videoState = " +
                    VideoProfile.videoStateToString(currentVideoState));
            setVideoState(currentVideoState);
        }
    }

    /**
     * Issues a request to pause the video using {@link VideoProfile#STATE_PAUSED} from a source
     * other than the InCall UI.
     *
     * @param source The source of the pause request.
     */
    public void pauseVideo(int source) {
        if (mImsVideoCallProviderWrapper == null) {
            return;
        }

        mImsVideoCallProviderWrapper.pauseVideo(getVideoState(), source);
    }

    /**
     * Issues a request to resume the video using {@link VideoProfile#STATE_PAUSED} from a source
     * other than the InCall UI.
     *
     * @param source The source of the resume request.
     */
    public void resumeVideo(int source) {
        if (mImsVideoCallProviderWrapper == null) {
            return;
        }

        mImsVideoCallProviderWrapper.resumeVideo(getVideoState(), source);
    }

    /**
     * Determines if a specified source has issued a pause request.
     *
     * @param source The source.
     * @return {@code true} if the source issued a pause request, {@code false} otherwise.
     */
    public boolean wasVideoPausedFromSource(int source) {
        if (mImsVideoCallProviderWrapper == null) {
            return false;
        }

        return mImsVideoCallProviderWrapper.wasVideoPausedFromSource(source);
    }

    /**
     * Mark the call as in the process of being merged and inform the UI of the merge start.
     */
    public void handleMergeStart() {
        mIsMergeInProcess = true;
        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_START, null);
    }

    /**
     * Mark the call as done merging and inform the UI of the merge start.
     */
    public void handleMergeComplete() {
        mIsMergeInProcess = false;
        onConnectionEvent(android.telecom.Connection.EVENT_MERGE_COMPLETE, null);
    }

    public void changeToPausedState() {
        int newVideoState = getVideoState() | VideoProfile.STATE_PAUSED;
        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToPausedState - setting paused bit; "
                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
        updateVideoState(newVideoState);
        mShouldIgnoreVideoStateChanges = true;
    }

    public void changeToUnPausedState() {
        int newVideoState = getVideoState() & ~VideoProfile.STATE_PAUSED;
        Rlog.i(LOG_TAG, "ImsPhoneConnection: changeToUnPausedState - unsetting paused bit; "
                + "newVideoState=" + VideoProfile.videoStateToString(newVideoState));
        updateVideoState(newVideoState);
        mShouldIgnoreVideoStateChanges = false;
    }

    public void handleDataEnabledChange(boolean isDataEnabled) {
        mIsVideoEnabled = isDataEnabled;
        Rlog.i(LOG_TAG, "handleDataEnabledChange: isDataEnabled=" + isDataEnabled
                + "; updating local video availability.");
        updateMediaCapabilities(getImsCall());
        if (mImsVideoCallProviderWrapper != null) {
            mImsVideoCallProviderWrapper.setIsVideoEnabled(
                    hasCapabilities(Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
        }
    }
}
