FileDocCategorySizeDatePackage
SipPhone.javaAPI DocAndroid 5.1 API38629Thu Mar 12 22:22:54 GMT 2015com.android.internal.telephony.sip

SipPhone

public class SipPhone extends SipPhoneBase
{@hide}

Fields Summary
private static final String
LOG_TAG
private static final boolean
DBG
private static final boolean
VDBG
private static final int
TIMEOUT_MAKE_CALL
private static final int
TIMEOUT_ANSWER_CALL
private static final int
TIMEOUT_HOLD_CALL
private SipCall
mRingingCall
private SipCall
mForegroundCall
private SipCall
mBackgroundCall
private android.net.sip.SipManager
mSipManager
private android.net.sip.SipProfile
mProfile
Constructors Summary
SipPhone(android.content.Context context, com.android.internal.telephony.PhoneNotifier notifier, android.net.sip.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);
    
Methods Summary
public voidacceptCall(int videoState)

        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");
            }
        }
    
public booleancanConference()

        if (DBG) log("canConference: ret=true");
        return true;
    
public booleancanTransfer()

        return false;
    
public voidclearDisconnected()

        synchronized (SipPhone.class) {
            mRingingCall.clearDisconnected();
            mForegroundCall.clearDisconnected();
            mBackgroundCall.clearDisconnected();

            updatePhoneState();
            notifyPreciseCallStateChanged();
        }
    
public voidconference()

        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 voidconference(com.android.internal.telephony.Call that)

        synchronized (SipPhone.class) {
            if (!(that instanceof SipCall)) {
                throw new CallStateException("expect " + SipCall.class
                        + ", cannot merge with " + that.getClass());
            }
            mForegroundCall.merge((SipCall) that);
        }
    
public com.android.internal.telephony.Connectiondial(java.lang.String dialString, int videoState)

        synchronized (SipPhone.class) {
            return dialInternal(dialString, videoState);
        }
    
private com.android.internal.telephony.ConnectiondialInternal(java.lang.String dialString, int videoState)

        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);
        }
    
public booleanequals(java.lang.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 booleanequals(com.android.internal.telephony.sip.SipPhone phone)

        return getSipUri().equals(phone.getSipUri());
    
public voidexplicitCallTransfer()

        //mCT.explicitCallTransfer();
    
public com.android.internal.telephony.CallgetBackgroundCall()

        return mBackgroundCall;
    
private static Call.StategetCallStateFrom(android.net.sip.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;
        }
    
public voidgetCallWaiting(android.os.Message onComplete)

        // FIXME: what to reply?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    
public com.android.internal.telephony.CallgetForegroundCall()

        return mForegroundCall;
    
public booleangetMute()

        return (mForegroundCall.getState().isAlive()
                ? mForegroundCall.getMute()
                : mBackgroundCall.getMute());
    
public voidgetOutgoingCallerIdDisplay(android.os.Message onComplete)

        // FIXME: what to reply?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    
public com.android.internal.telephony.CallgetRingingCall()

        return mRingingCall;
    
public android.telephony.ServiceStategetServiceState()

        // FIXME: we may need to provide this when data connectivity is lost
        // or when server is down
        return super.getServiceState();
    
private java.lang.StringgetSipDomain(android.net.sip.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;
        }
    
public java.lang.StringgetSipUri()

        return mProfile.getUriString();
    
private java.lang.StringgetUriString(android.net.sip.SipProfile p)

        // SipProfile.getUriString() may contain "SIP:" and port
        return p.getUserName() + "@" + getSipDomain(p);
    
private voidlog(java.lang.String s)

        Rlog.d(LOG_TAG, s);
    
private voidloge(java.lang.String s)

        Rlog.e(LOG_TAG, s);
    
private voidloge(java.lang.String s, java.lang.Exception e)

        Rlog.e(LOG_TAG, s, e);
    
public voidrejectCall()

        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");
            }
        }
    
public voidsendBurstDtmf(java.lang.String dtmfString)

        loge("sendBurstDtmf() is a CDMA method");
    
public voidsendDtmf(char c)

        if (!PhoneNumberUtils.is12Key(c)) {
            loge("sendDtmf called with invalid character '" + c + "'");
        } else if (mForegroundCall.getState().isAlive()) {
            synchronized (SipPhone.class) {
                mForegroundCall.sendDtmf(c);
            }
        }
    
public voidsetCallWaiting(boolean enable, android.os.Message onComplete)

        // FIXME: what to reply?
        loge("call waiting not supported");
    
public voidsetEchoSuppressionEnabled()

        // 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();
            }
        }
    
public voidsetMute(boolean muted)

        synchronized (SipPhone.class) {
            mForegroundCall.setMute(muted);
        }
    
public voidsetOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, android.os.Message onComplete)

        // FIXME: what's this for SIP?
        AsyncResult.forMessage(onComplete, null, null);
        onComplete.sendToTarget();
    
private static voidslog(java.lang.String s)

        Rlog.d(LOG_TAG, s);
    
public voidstartDtmf(char c)

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

        // no op
    
public voidswitchHoldingAndActive()

        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();
        }
    
public com.android.internal.telephony.ConnectiontakeIncomingCall(java.lang.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;
        }