Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9404e633 authored by Hung-ying Tyan's avatar Hung-ying Tyan Committed by Android (Google) Code Review
Browse files

Merge "Add timer to SIP session creation process." into gingerbread

parents 36f429d3 9352cf1a
Loading
Loading
Loading
Loading
+96 −23
Original line number Diff line number Diff line
@@ -84,7 +84,8 @@ class SipSessionGroup implements SipListener {
    private static final boolean DEBUG_PING = DEBUG && false;
    private static final String ANONYMOUS = "anonymous";
    private static final String SERVER_ERROR_PREFIX = "Response: ";
    private static final int EXPIRY_TIME = 3600;
    private static final int EXPIRY_TIME = 3600; // in seconds
    private static final int CANCEL_CALL_TIMER = 5; // in seconds

    private static final EventObject DEREGISTER = new EventObject("Deregister");
    private static final EventObject END_CALL = new EventObject("End call");
@@ -363,6 +364,40 @@ class SipSessionGroup implements SipListener {
        String mPeerSessionDescription;
        boolean mInCall;
        boolean mReRegisterFlag = false;
        SessionTimer mTimer;

        // lightweight timer
        class SessionTimer {
            private boolean mRunning = true;

            void start(final int timeout) {
                new Thread(new Runnable() {
                    public void run() {
                        sleep(timeout);
                        if (mRunning) timeout();
                    }
                }).start();
            }

            synchronized void cancel() {
                mRunning = false;
                this.notify();
            }

            private void timeout() {
                synchronized (SipSessionGroup.this) {
                    onError(SipErrorCode.TIME_OUT, "Session timed out!");
                }
            }

            private synchronized void sleep(int timeout) {
                try {
                    this.wait(timeout * 1000);
                } catch (InterruptedException e) {
                    Log.e(TAG, "session timer interrupted!");
                }
            }
        }

        public SipSessionImpl(ISipSessionListener listener) {
            setListener(listener);
@@ -382,6 +417,8 @@ class SipSessionGroup implements SipListener {
            mServerTransaction = null;
            mClientTransaction = null;
            mPeerSessionDescription = null;

            cancelSessionTimer();
        }

        public boolean isInCall() {
@@ -434,16 +471,16 @@ class SipSessionGroup implements SipListener {
            }).start();
        }

        public void makeCall(SipProfile peerProfile,
                String sessionDescription) {
            doCommandAsync(
                    new MakeCallCommand(peerProfile, sessionDescription));
        public void makeCall(SipProfile peerProfile, String sessionDescription,
                int timeout) {
            doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription,
                    timeout));
        }

        public void answerCall(String sessionDescription) {
        public void answerCall(String sessionDescription, int timeout) {
            try {
                processCommand(
                        new MakeCallCommand(mPeerProfile, sessionDescription));
                processCommand(new MakeCallCommand(mPeerProfile,
                        sessionDescription, timeout));
            } catch (SipException e) {
                onError(e);
            }
@@ -453,9 +490,15 @@ class SipSessionGroup implements SipListener {
            doCommandAsync(END_CALL);
        }

        public void changeCall(String sessionDescription) {
            doCommandAsync(
                    new MakeCallCommand(mPeerProfile, sessionDescription));
        public void changeCall(String sessionDescription, int timeout) {
            doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
                    timeout));
        }

        public void changeCallWithTimeout(
                String sessionDescription, int timeout) {
            doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
                    timeout));
        }

        public void register(int duration) {
@@ -800,6 +843,7 @@ class SipSessionGroup implements SipListener {
                addSipSession(this);
                mState = SipSessionState.OUTGOING_CALL;
                mProxy.onCalling(this);
                startSessionTimer(cmd.getTimeout());
                return true;
            } else if (evt instanceof RegisterCommand) {
                int duration = ((RegisterCommand) evt).getDuration();
@@ -831,6 +875,7 @@ class SipSessionGroup implements SipListener {
                        ((MakeCallCommand) evt).getSessionDescription(),
                        mServerTransaction);
                mState = SipSessionState.INCOMING_CALL_ANSWERING;
                startSessionTimer(((MakeCallCommand) evt).getTimeout());
                return true;
            } else if (END_CALL == evt) {
                mSipHelper.sendInviteBusyHere(mInviteReceived,
@@ -873,6 +918,7 @@ class SipSessionGroup implements SipListener {
                    if (mState == SipSessionState.OUTGOING_CALL) {
                        mState = SipSessionState.OUTGOING_CALL_RING_BACK;
                        mProxy.onRingingBack(this);
                        cancelSessionTimer();
                    }
                    return true;
                case Response.OK:
@@ -885,10 +931,10 @@ class SipSessionGroup implements SipListener {
                    if (handleAuthentication(event)) {
                        addSipSession(this);
                    } else if (mLastNonce == null) {
                        endCallOnError(SipErrorCode.SERVER_ERROR,
                        onError(SipErrorCode.SERVER_ERROR,
                                "server does not provide challenge");
                    } else {
                        endCallOnError(SipErrorCode.INVALID_CREDENTIALS,
                        onError(SipErrorCode.INVALID_CREDENTIALS,
                                "incorrect username or password");
                    }
                    return true;
@@ -914,6 +960,7 @@ class SipSessionGroup implements SipListener {
                // response.
                mSipHelper.sendCancel(mClientTransaction);
                mState = SipSessionState.OUTGOING_CALL_CANCELING;
                startSessionTimer(CANCEL_CALL_TIMER);
                return true;
            }
            return false;
@@ -926,9 +973,13 @@ class SipSessionGroup implements SipListener {
                Response response = event.getResponse();
                int statusCode = response.getStatusCode();
                if (expectResponse(Request.CANCEL, evt)) {
                    if (statusCode == Response.OK) {
                    switch (statusCode) {
                        case Response.OK:
                            // do nothing; wait for REQUEST_TERMINATED
                            return true;
                        case Response.REQUEST_TERMINATED:
                            endCallNormally();
                            return true;
                    }
                } else if (expectResponse(Request.INVITE, evt)) {
                    if (statusCode == Response.OK) {
@@ -978,11 +1029,27 @@ class SipSessionGroup implements SipListener {
                mClientTransaction = mSipHelper.sendReinvite(mDialog,
                        ((MakeCallCommand) evt).getSessionDescription());
                mState = SipSessionState.OUTGOING_CALL;
                startSessionTimer(((MakeCallCommand) evt).getTimeout());
                return true;
            }
            return false;
        }

        // timeout in seconds
        private void startSessionTimer(int timeout) {
            if (timeout > 0) {
                mTimer = new SessionTimer();
                mTimer.start(timeout);
            }
        }

        private void cancelSessionTimer() {
            if (mTimer != null) {
                mTimer.cancel();
                mTimer = null;
            }
        }

        private String createErrorMessage(Response response) {
            return String.format(SERVER_ERROR_PREFIX + "%s (%d)",
                    response.getReasonPhrase(), response.getStatusCode());
@@ -991,15 +1058,10 @@ class SipSessionGroup implements SipListener {
        private void establishCall() {
            mState = SipSessionState.IN_CALL;
            mInCall = true;
            cancelSessionTimer();
            mProxy.onCallEstablished(this, mPeerSessionDescription);
        }

        private void fallbackToPreviousInCall(Throwable exception) {
            exception = getRootCause(exception);
            fallbackToPreviousInCall(getErrorCode(exception),
                    exception.toString());
        }

        private void fallbackToPreviousInCall(SipErrorCode errorCode,
                String message) {
            mState = SipSessionState.IN_CALL;
@@ -1022,6 +1084,7 @@ class SipSessionGroup implements SipListener {
        }

        private void onError(SipErrorCode errorCode, String message) {
            cancelSessionTimer();
            switch (mState) {
                case REGISTERING:
                case DEREGISTERING:
@@ -1255,11 +1318,18 @@ class SipSessionGroup implements SipListener {

    private class MakeCallCommand extends EventObject {
        private String mSessionDescription;
        private int mTimeout; // in seconds

        public MakeCallCommand(SipProfile peerProfile,
                String sessionDescription) {
            this(peerProfile, sessionDescription, -1);
        }

        public MakeCallCommand(SipProfile peerProfile,
                String sessionDescription, int timeout) {
            super(peerProfile);
            mSessionDescription = sessionDescription;
            mTimeout = timeout;
        }

        public SipProfile getPeerProfile() {
@@ -1269,6 +1339,9 @@ class SipSessionGroup implements SipListener {
        public String getSessionDescription() {
            return mSessionDescription;
        }
    }

        public int getTimeout() {
            return mTimeout;
        }
    }
}
+5 −4
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import java.util.List;
public class SipPhone extends SipPhoneBase {
    private static final String LOG_TAG = "SipPhone";
    private static final boolean LOCAL_DEBUG = true;
    private static final int SESSION_TIMEOUT = 8; // in seconds

    // A call that is ringing or (call) waiting
    private SipCall ringingCall = new SipCall();
@@ -675,7 +676,7 @@ public class SipPhone extends SipPhoneBase {

        void acceptCall() throws CallStateException {
            try {
                mSipAudioCall.answerCall();
                mSipAudioCall.answerCall(SESSION_TIMEOUT);
            } catch (SipException e) {
                throw new CallStateException("acceptCall(): " + e);
            }
@@ -693,7 +694,7 @@ public class SipPhone extends SipPhoneBase {
        void dial() throws SipException {
            setState(Call.State.DIALING);
            mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile,
                    mPeer, null);
                    mPeer, null, SESSION_TIMEOUT);
            mSipAudioCall.setRingbackToneEnabled(false);
            mSipAudioCall.setListener(mAdapter);
        }
@@ -701,7 +702,7 @@ public class SipPhone extends SipPhoneBase {
        void hold() throws CallStateException {
            setState(Call.State.HOLDING);
            try {
                mSipAudioCall.holdCall();
                mSipAudioCall.holdCall(SESSION_TIMEOUT);
            } catch (SipException e) {
                throw new CallStateException("hold(): " + e);
            }
@@ -711,7 +712,7 @@ public class SipPhone extends SipPhoneBase {
            mSipAudioCall.setAudioGroup(audioGroup);
            setState(Call.State.ACTIVE);
            try {
                mSipAudioCall.continueCall();
                mSipAudioCall.continueCall(SESSION_TIMEOUT);
            } catch (SipException e) {
                throw new CallStateException("unhold(): " + e);
            }
+9 −3
Original line number Diff line number Diff line
@@ -112,9 +112,11 @@ interface ISipSession {
     *
     * @param callee the SIP profile to make the call to
     * @param sessionDescription the session description of this call
     * @param timeout the session will be timed out if the call is not
     *        established within {@code timeout} seconds
     * @see ISipSessionListener
     */
    void makeCall(in SipProfile callee, String sessionDescription);
    void makeCall(in SipProfile callee, String sessionDescription, int timeout);

    /**
     * Answers an incoming call with the specified session description. The
@@ -122,8 +124,10 @@ interface ISipSession {
     * {@link SipSessionState#INCOMING_CALL}.
     *
     * @param sessionDescription the session description to answer this call
     * @param timeout the session will be timed out if the call is not
     *        established within {@code timeout} seconds
     */
    void answerCall(String sessionDescription);
    void answerCall(String sessionDescription, int timeout);

    /**
     * Ends an established call, terminates an outgoing call or rejects an
@@ -140,6 +144,8 @@ interface ISipSession {
     * to call when the session state is in {@link SipSessionState#IN_CALL}.
     *
     * @param sessionDescription the new session description
     * @param timeout the session will be timed out if the call is not
     *        established within {@code timeout} seconds
     */
    void changeCall(String sessionDescription);
    void changeCall(String sessionDescription, int timeout);
}
+34 −8
Original line number Diff line number Diff line
@@ -158,12 +158,18 @@ public interface SipAudioCall {
    void close();

    /**
     * Initiates an audio call to the specified profile.
     * Initiates an audio call to the specified profile. The attempt will be
     * timed out if the call is not established within {@code timeout} seconds
     * and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
     * will be called.
     *
     * @param callee the SIP profile to make the call to
     * @param sipManager the {@link SipManager} object to help make call with
     * @param timeout the timeout value in seconds
     * @see Listener.onError
     */
    void makeCall(SipProfile callee, SipManager sipManager) throws SipException;
    void makeCall(SipProfile callee, SipManager sipManager, int timeout)
            throws SipException;

    /**
     * Attaches an incoming call to this call object.
@@ -179,18 +185,38 @@ public interface SipAudioCall {

    /**
     * Puts a call on hold.  When succeeds, {@link Listener#onCallHeld} is
     * called.
     * called. The attempt will be timed out if the call is not established
     * within {@code timeout} seconds and
     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
     * will be called.
     *
     * @param timeout the timeout value in seconds
     * @see Listener.onError
     */
    void holdCall() throws SipException;
    void holdCall(int timeout) throws SipException;

    /** Answers a call. */
    void answerCall() throws SipException;
    /**
     * Answers a call. The attempt will be timed out if the call is not
     * established within {@code timeout} seconds and
     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
     * will be called.
     *
     * @param timeout the timeout value in seconds
     * @see Listener.onError
     */
    void answerCall(int timeout) throws SipException;

    /**
     * Continues a call that's on hold. When succeeds,
     * {@link Listener#onCallEstablished} is called.
     * {@link Listener#onCallEstablished} is called. The attempt will be timed
     * out if the call is not established within {@code timeout} seconds and
     * {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
     * will be called.
     *
     * @param timeout the timeout value in seconds
     * @see Listener.onError
     */
    void continueCall() throws SipException;
    void continueCall(int timeout) throws SipException;

    /** Puts the device to speaker mode. */
    void setSpeakerMode(boolean speakerMode);
+21 −10
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ public class SipAudioCallImpl extends SipSessionAdapter
    private static final boolean DONT_RELEASE_SOCKET = false;
    private static final String AUDIO = "audio";
    private static final int DTMF = 101;
    private static final int SESSION_TIMEOUT = 5; // in seconds

    private Context mContext;
    private SipProfile mLocalProfile;
@@ -144,12 +145,21 @@ public class SipAudioCallImpl extends SipSessionAdapter
        if (closeRtp) stopCall(RELEASE_SOCKET);
        stopRingbackTone();
        stopRinging();
        mSipSession = null;

        mInCall = false;
        mHold = false;
        mSessionId = -1L;
        mErrorCode = null;
        mErrorMessage = null;

        if (mSipSession != null) {
            try {
                mSipSession.setListener(null);
            } catch (RemoteException e) {
                // don't care
            }
            mSipSession = null;
        }
    }

    public synchronized SipProfile getLocalProfile() {
@@ -219,7 +229,7 @@ public class SipAudioCallImpl extends SipSessionAdapter
            // session changing request
            try {
                mPeerSd = new SdpSessionDescription(sessionDescription);
                answerCall();
                answerCall(SESSION_TIMEOUT);
            } catch (Throwable e) {
                Log.e(TAG, "onRinging()", e);
                session.endCall();
@@ -346,14 +356,15 @@ public class SipAudioCallImpl extends SipSessionAdapter
    }

    public synchronized void makeCall(SipProfile peerProfile,
            SipManager sipManager) throws SipException {
            SipManager sipManager, int timeout) throws SipException {
        try {
            mSipSession = sipManager.createSipSession(mLocalProfile, this);
            if (mSipSession == null) {
                throw new SipException(
                        "Failed to create SipSession; network available?");
            }
            mSipSession.makeCall(peerProfile, createOfferSessionDescription());
            mSipSession.makeCall(peerProfile, createOfferSessionDescription(),
                    timeout);
        } catch (Throwable e) {
            if (e instanceof SipException) {
                throw (SipException) e;
@@ -376,10 +387,10 @@ public class SipAudioCallImpl extends SipSessionAdapter
        }
    }

    public synchronized void holdCall() throws SipException {
    public synchronized void holdCall(int timeout) throws SipException {
        if (mHold) return;
        try {
            mSipSession.changeCall(createHoldSessionDescription());
            mSipSession.changeCall(createHoldSessionDescription(), timeout);
            mHold = true;
        } catch (Throwable e) {
            throwSipException(e);
@@ -389,21 +400,21 @@ public class SipAudioCallImpl extends SipSessionAdapter
        if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
    }

    public synchronized void answerCall() throws SipException {
    public synchronized void answerCall(int timeout) throws SipException {
        try {
            stopRinging();
            mSipSession.answerCall(createAnswerSessionDescription());
            mSipSession.answerCall(createAnswerSessionDescription(), timeout);
        } catch (Throwable e) {
            Log.e(TAG, "answerCall()", e);
            throwSipException(e);
        }
    }

    public synchronized void continueCall() throws SipException {
    public synchronized void continueCall(int timeout) throws SipException {
        if (!mHold) return;
        try {
            mHold = false;
            mSipSession.changeCall(createContinueSessionDescription());
            mSipSession.changeCall(createContinueSessionDescription(), timeout);
        } catch (Throwable e) {
            throwSipException(e);
        }
Loading