/*
 * Copyright (C) 2010 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.sip;

import android.content.Context;
import android.media.AudioManager;
import android.net.rtp.AudioGroup;
import android.net.sip.SipAudioCall;
import android.net.sip.SipErrorCode;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.net.sip.SipSession;
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.text.TextUtils;
import android.telephony.Rlog;

import com.android.internal.telephony.Call;
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.PhoneNotifier;

import java.text.ParseException;
import java.util.List;
import java.util.regex.Pattern;

/**
 * {@hide}
 */
public class SipPhone extends SipPhoneBase {
    private static final String LOG_TAG = "SipPhone";
    private static final boolean DBG = true;
    private static final boolean VDBG = false; // STOPSHIP if true
    private static final int TIMEOUT_MAKE_CALL = 15; // in seconds
    private static final int TIMEOUT_ANSWER_CALL = 8; // in seconds
    private static final int TIMEOUT_HOLD_CALL = 15; // in seconds

    // A call that is ringing or (call) waiting
    private SipCall mRingingCall = new SipCall();
    private SipCall mForegroundCall = new SipCall();
    private SipCall mBackgroundCall = new SipCall();

    private SipManager mSipManager;
    private SipProfile mProfile;

    SipPhone (Context context, PhoneNotifier notifier, SipProfile profile) {
        super("SIP:" + profile.getUriString(), context, notifier);

        if (DBG) log("new SipPhone: " + profile.getUriString());
        mRingingCall = new SipCall();
        mForegroundCall = new SipCall();
        mBackgroundCall = new SipCall();
        mProfile = profile;
        mSipManager = SipManager.newInstance(context);
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof SipPhone)) return false;
        SipPhone that = (SipPhone) o;
        return mProfile.getUriString().equals(that.mProfile.getUriString());
    }

    public String getSipUri() {
        return mProfile.getUriString();
    }

    public boolean equals(SipPhone phone) {
        return getSipUri().equals(phone.getSipUri());
    }

    public Connection takeIncomingCall(Object incomingCall) {
        // FIXME: Is synchronizing on the class necessary, should we use a mLockObj?
        // Also there are many things not synchronized, of course
        // this may be true of CdmaPhone and GsmPhone too!!!
        synchronized (SipPhone.class) {
            if (!(incomingCall instanceof SipAudioCall)) {
                if (DBG) log("takeIncomingCall: ret=null, not a SipAudioCall");
                return null;
            }
            if (mRingingCall.getState().isAlive()) {
                if (DBG) log("takeIncomingCall: ret=null, ringingCall not alive");
                return null;
            }

            // FIXME: is it true that we cannot take any incoming call if
            // both foreground and background are active
            if (mForegroundCall.getState().isAlive()
                    && mBackgroundCall.getState().isAlive()) {
                if (DBG) {
                    log("takeIncomingCall: ret=null," + " foreground and background both alive");
                }
                return null;
            }

            try {
                SipAudioCall sipAudioCall = (SipAudioCall) incomingCall;
                if (DBG) log("takeIncomingCall: taking call from: "
                        + sipAudioCall.getPeerProfile().getUriString());
                String localUri = sipAudioCall.getLocalProfile().getUriString();
                if (localUri.equals(mProfile.getUriString())) {
                    boolean makeCallWait = mForegroundCall.getState().isAlive();
                    SipConnection connection = mRingingCall.initIncomingCall(sipAudioCall,
                            makeCallWait);
                    if (sipAudioCall.getState() != SipSession.State.INCOMING_CALL) {
                        // Peer cancelled the call!
                        if (DBG) log("    takeIncomingCall: call cancelled !!");
                        mRingingCall.reset();
                        connection = null;
                    }
                    return connection;
                }
            } catch (Exception e) {
                // Peer may cancel the call at any time during the time we hook
                // up ringingCall with sipAudioCall. Clean up ringingCall when
                // that happens.
                if (DBG) log("    takeIncomingCall: exception e=" + e);
                mRingingCall.reset();
            }
            if (DBG) log("takeIncomingCall: NOT taking !!");
            return null;
        }
    }

    @Override
    public void acceptCall(int videoState) throws CallStateException {
        synchronized (SipPhone.class) {
            if ((mRingingCall.getState() == Call.State.INCOMING) ||
                    (mRingingCall.getState() == Call.State.WAITING)) {
                if (DBG) log("acceptCall: accepting");
                // Always unmute when answering a new call
                mRingingCall.setMute(false);
                mRingingCall.acceptCall();
            } else {
                if (DBG) {
                    log("acceptCall:" +
                        " throw CallStateException(\"phone not ringing\")");
                }
                throw new CallStateException("phone not ringing");
            }
        }
    }

    @Override
    public void rejectCall() throws CallStateException {
        synchronized (SipPhone.class) {
            if (mRingingCall.getState().isRinging()) {
                if (DBG) log("rejectCall: rejecting");
                mRingingCall.rejectCall();
            } else {
                if (DBG) {
                    log("rejectCall:" +
                        " throw CallStateException(\"phone not ringing\")");
                }
                throw new CallStateException("phone not ringing");
            }
        }
    }

    @Override
    public Connection dial(String dialString, int videoState) throws CallStateException {
        synchronized (SipPhone.class) {
            return dialInternal(dialString, videoState);
        }
    }

    private Connection dialInternal(String dialString, int videoState)
            throws CallStateException {
        if (DBG) log("dialInternal: dialString=" + (VDBG ? dialString : "xxxxxx"));
        clearDisconnected();

        if (!canDial()) {
            throw new CallStateException("dialInternal: cannot dial in current state");
        }
        if (mForegroundCall.getState() == SipCall.State.ACTIVE) {
            switchHoldingAndActive();
        }
        if (mForegroundCall.getState() != SipCall.State.IDLE) {
            //we should have failed in !canDial() above before we get here
            throw new CallStateException("cannot dial in current state");
        }

        mForegroundCall.setMute(false);
        try {
            Connection c = mForegroundCall.dial(dialString);
            return c;
        } catch (SipException e) {
            loge("dialInternal: ", e);
            throw new CallStateException("dial error: " + e);
        }
    }

    @Override
    public void switchHoldingAndActive() throws CallStateException {
        if (DBG) log("dialInternal: switch fg and bg");
        synchronized (SipPhone.class) {
            mForegroundCall.switchWith(mBackgroundCall);
            if (mBackgroundCall.getState().isAlive()) mBackgroundCall.hold();
            if (mForegroundCall.getState().isAlive()) mForegroundCall.unhold();
        }
    }

    @Override
    public boolean canConference() {
        if (DBG) log("canConference: ret=true");
        return true;
    }

    @Override
    public void conference() throws CallStateException {
        synchronized (SipPhone.class) {
            if ((mForegroundCall.getState() != SipCall.State.ACTIVE)
                    || (mForegroundCall.getState() != SipCall.State.ACTIVE)) {
                throw new CallStateException("wrong state to merge calls: fg="
                        + mForegroundCall.getState() + ", bg="
                        + mBackgroundCall.getState());
            }
            if (DBG) log("conference: merge fg & bg");
            mForegroundCall.merge(mBackgroundCall);
        }
    }

    public void conference(Call that) throws CallStateException {
        synchronized (SipPhone.class) {
            if (!(that instanceof SipCall)) {
                throw new CallStateException("expect " + SipCall.class
                        + ", cannot merge with " + that.getClass());
            }
            mForegroundCall.merge((SipCall) that);
        }
    }

    @Override
    public boolean canTransfer() {
        return false;
    }

    @Override
    public void explicitCallTransfer() {
        //mCT.explicitCallTransfer();
    }

    @Override
    public void clearDisconnected() {
        synchronized (SipPhone.class) {
            mRingingCall.clearDisconnected();
            mForegroundCall.clearDisconnected();
            mBackgroundCall.clearDisconnected();

            updatePhoneState();
            notifyPreciseCallStateChanged();
        }
    }

    @Override
    public void sendDtmf(char c) {
        if (!PhoneNumberUtils.is12Key(c)) {
            loge("sendDtmf called with invalid character '" + c + "'");
        } else if (mForegroundCall.getState().isAlive()) {
            synchronized (SipPhone.class) {
                mForegroundCall.sendDtmf(c);
            }
        }
    }

    @Override
    public void startDtmf(char c) {
        if (!PhoneNumberUtils.is12Key(c)) {
            loge("startDtmf called with invalid character '" + c + "'");
        } else {
            sendDtmf(c);
        }
    }

    @Override
    public void stopDtmf() {
        // no op
    }

    public void sendBurstDtmf(String dtmfString) {
        loge("sendBurstDtmf() is a CDMA method");
    }

    @Override
    public void getOutgoingCallerIdDisplay(Message onComplete) {
        // FIXME: what to reply?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    }

    @Override
    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
                                           Message onComplete) {
        // FIXME: what's this for SIP?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    }

    @Override
    public void getCallWaiting(Message onComplete) {
        // FIXME: what to reply?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    }

    @Override
    public void setCallWaiting(boolean enable, Message onComplete) {
        // FIXME: what to reply?
        loge("call waiting not supported");
    }

    @Override
    public void setEchoSuppressionEnabled() {
        // Echo suppression may not be available on every device. So, check
        // whether it is supported
        synchronized (SipPhone.class) {
            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            String echoSuppression = audioManager.getParameters("ec_supported");
            if (echoSuppression.contains("off")) {
                mForegroundCall.setAudioGroupMode();
            }
        }
    }

    @Override
    public void setMute(boolean muted) {
        synchronized (SipPhone.class) {
            mForegroundCall.setMute(muted);
        }
    }

    @Override
    public boolean getMute() {
        return (mForegroundCall.getState().isAlive()
                ? mForegroundCall.getMute()
                : mBackgroundCall.getMute());
    }

    @Override
    public Call getForegroundCall() {
        return mForegroundCall;
    }

    @Override
    public Call getBackgroundCall() {
        return mBackgroundCall;
    }

    @Override
    public Call getRingingCall() {
        return mRingingCall;
    }

    @Override
    public ServiceState getServiceState() {
        // FIXME: we may need to provide this when data connectivity is lost
        // or when server is down
        return super.getServiceState();
    }

    private String getUriString(SipProfile p) {
        // SipProfile.getUriString() may contain "SIP:" and port
        return p.getUserName() + "@" + getSipDomain(p);
    }

    private String getSipDomain(SipProfile p) {
        String domain = p.getSipDomain();
        // TODO: move this to SipProfile
        if (domain.endsWith(":5060")) {
            return domain.substring(0, domain.length() - 5);
        } else {
            return domain;
        }
    }

    private static Call.State getCallStateFrom(SipAudioCall sipAudioCall) {
        if (sipAudioCall.isOnHold()) return Call.State.HOLDING;
        int sessionState = sipAudioCall.getState();
        switch (sessionState) {
            case SipSession.State.READY_TO_CALL:            return Call.State.IDLE;
            case SipSession.State.INCOMING_CALL:
            case SipSession.State.INCOMING_CALL_ANSWERING:  return Call.State.INCOMING;
            case SipSession.State.OUTGOING_CALL:            return Call.State.DIALING;
            case SipSession.State.OUTGOING_CALL_RING_BACK:  return Call.State.ALERTING;
            case SipSession.State.OUTGOING_CALL_CANCELING:  return Call.State.DISCONNECTING;
            case SipSession.State.IN_CALL:                  return Call.State.ACTIVE;
            default:
                slog("illegal connection state: " + sessionState);
                return Call.State.DISCONNECTED;
        }
    }

    private void log(String s) {
        Rlog.d(LOG_TAG, s);
    }

    private static void slog(String s) {
        Rlog.d(LOG_TAG, s);
    }

    private void loge(String s) {
        Rlog.e(LOG_TAG, s);
    }

    private void loge(String s, Exception e) {
        Rlog.e(LOG_TAG, s, e);
    }

    private class SipCall extends SipCallBase {
        private static final String SC_TAG = "SipCall";
        private static final boolean SC_DBG = true;
        private static final boolean SC_VDBG = false; // STOPSHIP if true

        void reset() {
            if (SC_DBG) log("reset");
            mConnections.clear();
            setState(Call.State.IDLE);
        }

        void switchWith(SipCall that) {
            if (SC_DBG) log("switchWith");
            synchronized (SipPhone.class) {
                SipCall tmp = new SipCall();
                tmp.takeOver(this);
                this.takeOver(that);
                that.takeOver(tmp);
            }
        }

        private void takeOver(SipCall that) {
            if (SC_DBG) log("takeOver");
            mConnections = that.mConnections;
            mState = that.mState;
            for (Connection c : mConnections) {
                ((SipConnection) c).changeOwner(this);
            }
        }

        @Override
        public Phone getPhone() {
            return SipPhone.this;
        }

        @Override
        public List<Connection> getConnections() {
            if (SC_VDBG) log("getConnections");
            synchronized (SipPhone.class) {
                // FIXME should return Collections.unmodifiableList();
                return mConnections;
            }
        }

        Connection dial(String originalNumber) throws SipException {
            if (SC_DBG) log("dial: num=" + (SC_VDBG ? originalNumber : "xxx"));
            // TODO: Should this be synchronized?
            String calleeSipUri = originalNumber;
            if (!calleeSipUri.contains("@")) {
                String replaceStr = Pattern.quote(mProfile.getUserName() + "@");
                calleeSipUri = mProfile.getUriString().replaceFirst(replaceStr,
                        calleeSipUri + "@");
            }
            try {
                SipProfile callee =
                        new SipProfile.Builder(calleeSipUri).build();
                SipConnection c = new SipConnection(this, callee,
                        originalNumber);
                c.dial();
                mConnections.add(c);
                setState(Call.State.DIALING);
                return c;
            } catch (ParseException e) {
                throw new SipException("dial", e);
            }
        }

        @Override
        public void hangup() throws CallStateException {
            synchronized (SipPhone.class) {
                if (mState.isAlive()) {
                    if (SC_DBG) log("hangup: call " + getState()
                            + ": " + this + " on phone " + getPhone());
                    setState(State.DISCONNECTING);
                    CallStateException excp = null;
                    for (Connection c : mConnections) {
                        try {
                            c.hangup();
                        } catch (CallStateException e) {
                            excp = e;
                        }
                    }
                    if (excp != null) throw excp;
                } else {
                    if (SC_DBG) log("hangup: dead call " + getState()
                            + ": " + this + " on phone " + getPhone());
                }
            }
        }

        SipConnection initIncomingCall(SipAudioCall sipAudioCall, boolean makeCallWait) {
            SipProfile callee = sipAudioCall.getPeerProfile();
            SipConnection c = new SipConnection(this, callee);
            mConnections.add(c);

            Call.State newState = makeCallWait ? State.WAITING : State.INCOMING;
            c.initIncomingCall(sipAudioCall, newState);

            setState(newState);
            notifyNewRingingConnectionP(c);
            return c;
        }

        void rejectCall() throws CallStateException {
            if (SC_DBG) log("rejectCall:");
            hangup();
        }

        void acceptCall() throws CallStateException {
            if (SC_DBG) log("acceptCall: accepting");
            if (this != mRingingCall) {
                throw new CallStateException("acceptCall() in a non-ringing call");
            }
            if (mConnections.size() != 1) {
                throw new CallStateException("acceptCall() in a conf call");
            }
            ((SipConnection) mConnections.get(0)).acceptCall();
        }

        private boolean isSpeakerOn() {
            Boolean ret = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
                    .isSpeakerphoneOn();
            if (SC_VDBG) log("isSpeakerOn: ret=" + ret);
            return ret;
        }

        void setAudioGroupMode() {
            AudioGroup audioGroup = getAudioGroup();
            if (audioGroup == null) {
                if (SC_DBG) log("setAudioGroupMode: audioGroup == null ignore");
                return;
            }
            int mode = audioGroup.getMode();
            if (mState == State.HOLDING) {
                audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
            } else if (getMute()) {
                audioGroup.setMode(AudioGroup.MODE_MUTED);
            } else if (isSpeakerOn()) {
                audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
            } else {
                audioGroup.setMode(AudioGroup.MODE_NORMAL);
            }
            if (SC_DBG) log(String.format(
                    "setAudioGroupMode change: %d --> %d", mode,
                    audioGroup.getMode()));
        }

        void hold() throws CallStateException {
            if (SC_DBG) log("hold:");
            setState(State.HOLDING);
            for (Connection c : mConnections) ((SipConnection) c).hold();
            setAudioGroupMode();
        }

        void unhold() throws CallStateException {
            if (SC_DBG) log("unhold:");
            setState(State.ACTIVE);
            AudioGroup audioGroup = new AudioGroup();
            for (Connection c : mConnections) {
                ((SipConnection) c).unhold(audioGroup);
            }
            setAudioGroupMode();
        }

        void setMute(boolean muted) {
            if (SC_DBG) log("setMute: muted=" + muted);
            for (Connection c : mConnections) {
                ((SipConnection) c).setMute(muted);
            }
        }

        boolean getMute() {
            boolean ret = mConnections.isEmpty()
                    ? false
                    : ((SipConnection) mConnections.get(0)).getMute();
            if (SC_DBG) log("getMute: ret=" + ret);
            return ret;
        }

        void merge(SipCall that) throws CallStateException {
            if (SC_DBG) log("merge:");
            AudioGroup audioGroup = getAudioGroup();

            // copy to an array to avoid concurrent modification as connections
            // in that.connections will be removed in add(SipConnection).
            Connection[] cc = that.mConnections.toArray(
                    new Connection[that.mConnections.size()]);
            for (Connection c : cc) {
                SipConnection conn = (SipConnection) c;
                add(conn);
                if (conn.getState() == Call.State.HOLDING) {
                    conn.unhold(audioGroup);
                }
            }
            that.setState(Call.State.IDLE);
        }

        private void add(SipConnection conn) {
            if (SC_DBG) log("add:");
            SipCall call = conn.getCall();
            if (call == this) return;
            if (call != null) call.mConnections.remove(conn);

            mConnections.add(conn);
            conn.changeOwner(this);
        }

        void sendDtmf(char c) {
            if (SC_DBG) log("sendDtmf: c=" + c);
            AudioGroup audioGroup = getAudioGroup();
            if (audioGroup == null) {
                if (SC_DBG) log("sendDtmf: audioGroup == null, ignore c=" + c);
                return;
            }
            audioGroup.sendDtmf(convertDtmf(c));
        }

        private int convertDtmf(char c) {
            int code = c - '0';
            if ((code < 0) || (code > 9)) {
                switch (c) {
                    case '*': return 10;
                    case '#': return 11;
                    case 'A': return 12;
                    case 'B': return 13;
                    case 'C': return 14;
                    case 'D': return 15;
                    default:
                        throw new IllegalArgumentException(
                                "invalid DTMF char: " + (int) c);
                }
            }
            return code;
        }

        @Override
        protected void setState(State newState) {
            if (mState != newState) {
                if (SC_DBG) log("setState: cur state" + mState
                        + " --> " + newState + ": " + this + ": on phone "
                        + getPhone() + " " + mConnections.size());

                if (newState == Call.State.ALERTING) {
                    mState = newState; // need in ALERTING to enable ringback
                    startRingbackTone();
                } else if (mState == Call.State.ALERTING) {
                    stopRingbackTone();
                }
                mState = newState;
                updatePhoneState();
                notifyPreciseCallStateChanged();
            }
        }

        void onConnectionStateChanged(SipConnection conn) {
            // this can be called back when a conf call is formed
            if (SC_DBG) log("onConnectionStateChanged: conn=" + conn);
            if (mState != State.ACTIVE) {
                setState(conn.getState());
            }
        }

        void onConnectionEnded(SipConnection conn) {
            // set state to DISCONNECTED only when all conns are disconnected
            if (SC_DBG) log("onConnectionEnded: conn=" + conn);
            if (mState != State.DISCONNECTED) {
                boolean allConnectionsDisconnected = true;
                if (SC_DBG) log("---check connections: "
                        + mConnections.size());
                for (Connection c : mConnections) {
                    if (SC_DBG) log("   state=" + c.getState() + ": "
                            + c);
                    if (c.getState() != State.DISCONNECTED) {
                        allConnectionsDisconnected = false;
                        break;
                    }
                }
                if (allConnectionsDisconnected) setState(State.DISCONNECTED);
            }
            notifyDisconnectP(conn);
        }

        private AudioGroup getAudioGroup() {
            if (mConnections.isEmpty()) return null;
            return ((SipConnection) mConnections.get(0)).getAudioGroup();
        }

        private void log(String s) {
            Rlog.d(SC_TAG, s);
        }
    }

    private class SipConnection extends SipConnectionBase {
        private static final String SCN_TAG = "SipConnection";
        private static final boolean SCN_DBG = true;

        private SipCall mOwner;
        private SipAudioCall mSipAudioCall;
        private Call.State mState = Call.State.IDLE;
        private SipProfile mPeer;
        private boolean mIncoming = false;
        private String mOriginalNumber; // may be a PSTN number

        private SipAudioCallAdapter mAdapter = new SipAudioCallAdapter() {
            @Override
            protected void onCallEnded(int cause) {
                if (getDisconnectCause() != DisconnectCause.LOCAL) {
                    setDisconnectCause(cause);
                }
                synchronized (SipPhone.class) {
                    setState(Call.State.DISCONNECTED);
                    SipAudioCall sipAudioCall = mSipAudioCall;
                    // FIXME: This goes null and is synchronized, but many uses aren't sync'd
                    mSipAudioCall = null;
                    String sessionState = (sipAudioCall == null)
                            ? ""
                            : (sipAudioCall.getState() + ", ");
                    if (SCN_DBG) log("[SipAudioCallAdapter] onCallEnded: "
                            + mPeer.getUriString() + ": " + sessionState
                            + "cause: " + getDisconnectCause() + ", on phone "
                            + getPhone());
                    if (sipAudioCall != null) {
                        sipAudioCall.setListener(null);
                        sipAudioCall.close();
                    }
                    mOwner.onConnectionEnded(SipConnection.this);
                }
            }

            @Override
            public void onCallEstablished(SipAudioCall call) {
                onChanged(call);
                // Race onChanged synchronized this isn't
                if (mState == Call.State.ACTIVE) call.startAudio();
            }

            @Override
            public void onCallHeld(SipAudioCall call) {
                onChanged(call);
                // Race onChanged synchronized this isn't
                if (mState == Call.State.HOLDING) call.startAudio();
            }

            @Override
            public void onChanged(SipAudioCall call) {
                synchronized (SipPhone.class) {
                    Call.State newState = getCallStateFrom(call);
                    if (mState == newState) return;
                    if (newState == Call.State.INCOMING) {
                        setState(mOwner.getState()); // INCOMING or WAITING
                    } else {
                        if (mOwner == mRingingCall) {
                            if (mRingingCall.getState() == Call.State.WAITING) {
                                try {
                                    switchHoldingAndActive();
                                } catch (CallStateException e) {
                                    // disconnect the call.
                                    onCallEnded(DisconnectCause.LOCAL);
                                    return;
                                }
                            }
                            mForegroundCall.switchWith(mRingingCall);
                        }
                        setState(newState);
                    }
                    mOwner.onConnectionStateChanged(SipConnection.this);
                    if (SCN_DBG) log("onChanged: "
                            + mPeer.getUriString() + ": " + mState
                            + " on phone " + getPhone());
                }
            }

            @Override
            protected void onError(int cause) {
                if (SCN_DBG) log("onError: " + cause);
                onCallEnded(cause);
            }
        };

        public SipConnection(SipCall owner, SipProfile callee,
                String originalNumber) {
            super(originalNumber);
            mOwner = owner;
            mPeer = callee;
            mOriginalNumber = originalNumber;
        }

        public SipConnection(SipCall owner, SipProfile callee) {
            this(owner, callee, getUriString(callee));
        }

        @Override
        public String getCnapName() {
            String displayName = mPeer.getDisplayName();
            return TextUtils.isEmpty(displayName) ? null
                                                  : displayName;
        }

        @Override
        public int getNumberPresentation() {
            return PhoneConstants.PRESENTATION_ALLOWED;
        }

        void initIncomingCall(SipAudioCall sipAudioCall, Call.State newState) {
            setState(newState);
            mSipAudioCall = sipAudioCall;
            sipAudioCall.setListener(mAdapter); // call back to set state
            mIncoming = true;
        }

        void acceptCall() throws CallStateException {
            try {
                mSipAudioCall.answerCall(TIMEOUT_ANSWER_CALL);
            } catch (SipException e) {
                throw new CallStateException("acceptCall(): " + e);
            }
        }

        void changeOwner(SipCall owner) {
            mOwner = owner;
        }

        AudioGroup getAudioGroup() {
            if (mSipAudioCall == null) return null;
            return mSipAudioCall.getAudioGroup();
        }

        void dial() throws SipException {
            setState(Call.State.DIALING);
            mSipAudioCall = mSipManager.makeAudioCall(mProfile, mPeer, null,
                    TIMEOUT_MAKE_CALL);
            mSipAudioCall.setListener(mAdapter);
        }

        void hold() throws CallStateException {
            setState(Call.State.HOLDING);
            try {
                mSipAudioCall.holdCall(TIMEOUT_HOLD_CALL);
            } catch (SipException e) {
                throw new CallStateException("hold(): " + e);
            }
        }

        void unhold(AudioGroup audioGroup) throws CallStateException {
            mSipAudioCall.setAudioGroup(audioGroup);
            setState(Call.State.ACTIVE);
            try {
                mSipAudioCall.continueCall(TIMEOUT_HOLD_CALL);
            } catch (SipException e) {
                throw new CallStateException("unhold(): " + e);
            }
        }

        void setMute(boolean muted) {
            if ((mSipAudioCall != null) && (muted != mSipAudioCall.isMuted())) {
                if (SCN_DBG) log("setState: prev muted=" + !muted + " new muted=" + muted);
                mSipAudioCall.toggleMute();
            }
        }

        boolean getMute() {
            return (mSipAudioCall == null) ? false
                                           : mSipAudioCall.isMuted();
        }

        @Override
        protected void setState(Call.State state) {
            if (state == mState) return;
            super.setState(state);
            mState = state;
        }

        @Override
        public Call.State getState() {
            return mState;
        }

        @Override
        public boolean isIncoming() {
            return mIncoming;
        }

        @Override
        public String getAddress() {
            // Phone app uses this to query caller ID. Return the original dial
            // number (which may be a PSTN number) instead of the peer's SIP
            // URI.
            return mOriginalNumber;
        }

        @Override
        public SipCall getCall() {
            return mOwner;
        }

        @Override
        protected Phone getPhone() {
            return mOwner.getPhone();
        }

        @Override
        public void hangup() throws CallStateException {
            synchronized (SipPhone.class) {
                if (SCN_DBG) log("hangup: conn=" + mPeer.getUriString()
                        + ": " + mState + ": on phone "
                        + getPhone().getPhoneName());
                if (!mState.isAlive()) return;
                try {
                    SipAudioCall sipAudioCall = mSipAudioCall;
                    if (sipAudioCall != null) {
                        sipAudioCall.setListener(null);
                        sipAudioCall.endCall();
                    }
                } catch (SipException e) {
                    throw new CallStateException("hangup(): " + e);
                } finally {
                    mAdapter.onCallEnded(((mState == Call.State.INCOMING)
                            || (mState == Call.State.WAITING))
                            ? DisconnectCause.INCOMING_REJECTED
                            : DisconnectCause.LOCAL);
                }
            }
        }

        @Override
        public void separate() throws CallStateException {
            synchronized (SipPhone.class) {
                SipCall call = (getPhone() == SipPhone.this)
                        ? (SipCall) getBackgroundCall()
                        : (SipCall) getForegroundCall();
                if (call.getState() != Call.State.IDLE) {
                    throw new CallStateException(
                            "cannot put conn back to a call in non-idle state: "
                            + call.getState());
                }
                if (SCN_DBG) log("separate: conn="
                        + mPeer.getUriString() + " from " + mOwner + " back to "
                        + call);

                // separate the AudioGroup and connection from the original call
                Phone originalPhone = getPhone();
                AudioGroup audioGroup = call.getAudioGroup(); // may be null
                call.add(this);
                mSipAudioCall.setAudioGroup(audioGroup);

                // put the original call to bg; and the separated call becomes
                // fg if it was in bg
                originalPhone.switchHoldingAndActive();

                // start audio and notify the phone app of the state change
                call = (SipCall) getForegroundCall();
                mSipAudioCall.startAudio();
                call.onConnectionStateChanged(this);
            }
        }

        private void log(String s) {
            Rlog.d(SCN_TAG, s);
        }
    }

    private abstract class SipAudioCallAdapter extends SipAudioCall.Listener {
        private static final String SACA_TAG = "SipAudioCallAdapter";
        private static final boolean SACA_DBG = true;
        /** Call ended with cause defined in {@link DisconnectCause}. */
        protected abstract void onCallEnded(int cause);
        /** Call failed with cause defined in {@link DisconnectCause}. */
        protected abstract void onError(int cause);

        @Override
        public void onCallEnded(SipAudioCall call) {
            if (SACA_DBG) log("onCallEnded: call=" + call);
            onCallEnded(call.isInCall()
                    ? DisconnectCause.NORMAL
                    : DisconnectCause.INCOMING_MISSED);
        }

        @Override
        public void onCallBusy(SipAudioCall call) {
            if (SACA_DBG) log("onCallBusy: call=" + call);
            onCallEnded(DisconnectCause.BUSY);
        }

        @Override
        public void onError(SipAudioCall call, int errorCode,
                String errorMessage) {
            if (SACA_DBG) {
                log("onError: call=" + call + " code="+ SipErrorCode.toString(errorCode)
                    + ": " + errorMessage);
            }
            switch (errorCode) {
                case SipErrorCode.SERVER_UNREACHABLE:
                    onError(DisconnectCause.SERVER_UNREACHABLE);
                    break;
                case SipErrorCode.PEER_NOT_REACHABLE:
                    onError(DisconnectCause.NUMBER_UNREACHABLE);
                    break;
                case SipErrorCode.INVALID_REMOTE_URI:
                    onError(DisconnectCause.INVALID_NUMBER);
                    break;
                case SipErrorCode.TIME_OUT:
                case SipErrorCode.TRANSACTION_TERMINTED:
                    onError(DisconnectCause.TIMED_OUT);
                    break;
                case SipErrorCode.DATA_CONNECTION_LOST:
                    onError(DisconnectCause.LOST_SIGNAL);
                    break;
                case SipErrorCode.INVALID_CREDENTIALS:
                    onError(DisconnectCause.INVALID_CREDENTIALS);
                    break;
                case SipErrorCode.CROSS_DOMAIN_AUTHENTICATION:
                    onError(DisconnectCause.OUT_OF_NETWORK);
                    break;
                case SipErrorCode.SERVER_ERROR:
                    onError(DisconnectCause.SERVER_ERROR);
                    break;
                case SipErrorCode.SOCKET_ERROR:
                case SipErrorCode.CLIENT_ERROR:
                default:
                    onError(DisconnectCause.ERROR_UNSPECIFIED);
            }
        }

        private void log(String s) {
            Rlog.d(SACA_TAG, s);
        }
    }
}
