diff options
6 files changed, 142 insertions, 94 deletions
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java index 8e08592..980affa 100644 --- a/telephony/java/com/android/internal/telephony/CallManager.java +++ b/telephony/java/com/android/internal/telephony/CallManager.java @@ -322,7 +322,9 @@ public final class CallManager { } break; } - audioManager.setMode(mode); + // calling audioManager.setMode() multiple times in a short period of + // time seems to break the audio recorder in in-call mode + if (audioManager.getMode() != mode) audioManager.setMode(mode); } private Context getContext() { diff --git a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java index ad05b82..f5d84eb 100644 --- a/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipConnectionBase.java @@ -85,8 +85,10 @@ abstract class SipConnectionBase extends Connection { protected void setState(Call.State state) { switch (state) { case ACTIVE: - connectTimeReal = SystemClock.elapsedRealtime(); - connectTime = System.currentTimeMillis(); + if (connectTime == 0) { + connectTimeReal = SystemClock.elapsedRealtime(); + connectTime = System.currentTimeMillis(); + } break; case DISCONNECTED: duration = SystemClock.elapsedRealtime() - connectTimeReal; diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java index 81dfaeb..9a45d3a 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java @@ -107,7 +107,7 @@ public class SipPhone extends SipPhoneBase { } public String getPhoneName() { - return mProfile.getProfileName(); + return "SIP:" + getUriString(mProfile); } public String getSipUri() { @@ -225,21 +225,25 @@ public class SipPhone extends SipPhoneBase { } public void conference() throws CallStateException { - if ((foregroundCall.getState() != SipCall.State.ACTIVE) - || (foregroundCall.getState() != SipCall.State.ACTIVE)) { - throw new CallStateException("wrong state to merge calls: fg=" - + foregroundCall.getState() + ", bg=" - + backgroundCall.getState()); + synchronized (SipPhone.class) { + if ((foregroundCall.getState() != SipCall.State.ACTIVE) + || (foregroundCall.getState() != SipCall.State.ACTIVE)) { + throw new CallStateException("wrong state to merge calls: fg=" + + foregroundCall.getState() + ", bg=" + + backgroundCall.getState()); + } + foregroundCall.merge(backgroundCall); } - foregroundCall.merge(backgroundCall); } public void conference(Call that) throws CallStateException { - if (!(that instanceof SipCall)) { - throw new CallStateException("expect " + SipCall.class - + ", cannot merge with " + that.getClass()); + synchronized (SipPhone.class) { + if (!(that instanceof SipCall)) { + throw new CallStateException("expect " + SipCall.class + + ", cannot merge with " + that.getClass()); + } + foregroundCall.merge((SipCall) that); } - foregroundCall.merge((SipCall) that); } public boolean canTransfer() { @@ -251,12 +255,14 @@ public class SipPhone extends SipPhoneBase { } public void clearDisconnected() { - ringingCall.clearDisconnected(); - foregroundCall.clearDisconnected(); - backgroundCall.clearDisconnected(); + synchronized (SipPhone.class) { + ringingCall.clearDisconnected(); + foregroundCall.clearDisconnected(); + backgroundCall.clearDisconnected(); - updatePhoneState(); - notifyPreciseCallStateChanged(); + updatePhoneState(); + notifyPreciseCallStateChanged(); + } } public void sendDtmf(char c) { @@ -264,7 +270,9 @@ public class SipPhone extends SipPhoneBase { Log.e(LOG_TAG, "sendDtmf called with invalid character '" + c + "'"); } else if (foregroundCall.getState().isAlive()) { - foregroundCall.sendDtmf(c); + synchronized (SipPhone.class) { + foregroundCall.sendDtmf(c); + } } } @@ -310,7 +318,9 @@ public class SipPhone extends SipPhoneBase { } public void setMute(boolean muted) { - foregroundCall.setMute(muted); + synchronized (SipPhone.class) { + foregroundCall.setMute(muted); + } } public boolean getMute() { @@ -413,18 +423,20 @@ public class SipPhone extends SipPhoneBase { @Override public void hangup() throws CallStateException { - Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this - + " on phone " + getPhone()); - CallStateException excp = null; - for (Connection c : connections) { - try { - c.hangup(); - } catch (CallStateException e) { - excp = e; + synchronized (SipPhone.class) { + Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this + + " on phone " + getPhone()); + CallStateException excp = null; + for (Connection c : connections) { + try { + c.hangup(); + } catch (CallStateException e) { + excp = e; + } } + if (excp != null) throw excp; + setState(State.DISCONNECTING); } - if (excp != null) throw excp; - setState(State.DISCONNECTING); } void initIncomingCall(SipAudioCall sipAudioCall, boolean makeCallWait) { @@ -457,19 +469,20 @@ public class SipPhone extends SipPhoneBase { } void hold() throws CallStateException { - AudioGroup audioGroup = getAudioGroup(); - if (audioGroup == null) return; - audioGroup.setMode(AudioGroup.MODE_ON_HOLD); setState(State.HOLDING); + AudioGroup audioGroup = getAudioGroup(); + if (audioGroup != null) { + audioGroup.setMode(AudioGroup.MODE_ON_HOLD); + } for (Connection c : connections) ((SipConnection) c).hold(); } void unhold() throws CallStateException { - AudioGroup audioGroup = getAudioGroup(); - if (audioGroup == null) return; - audioGroup.setMode(AudioGroup.MODE_NORMAL); setState(State.ACTIVE); - for (Connection c : connections) ((SipConnection) c).unhold(); + AudioGroup audioGroup = new AudioGroup(); + for (Connection c : connections) { + ((SipConnection) c).unhold(audioGroup); + } } void setMute(boolean muted) { @@ -486,17 +499,26 @@ public class SipPhone extends SipPhoneBase { } void merge(SipCall that) throws CallStateException { - AudioGroup myGroup = getAudioGroup(); + AudioGroup audioGroup = getAudioGroup(); for (Connection c : that.connections) { SipConnection conn = (SipConnection) c; - conn.mergeTo(myGroup); - connections.add(conn); - conn.changeOwner(this); + add(conn); + if (conn.getState() == Call.State.HOLDING) { + conn.unhold(audioGroup); + } } - that.connections.clear(); that.setState(Call.State.IDLE); } + private void add(SipConnection conn) { + SipCall call = conn.getCall(); + if (call == this) return; + if (call != null) call.connections.remove(conn); + + connections.add(conn); + conn.changeOwner(this); + } + void sendDtmf(char c) { AudioGroup audioGroup = getAudioGroup(); if (audioGroup == null) return; @@ -571,7 +593,6 @@ public class SipPhone extends SipPhoneBase { private class SipConnection extends SipConnectionBase { private SipCall mOwner; private SipAudioCall mSipAudioCall; - private AudioGroup mOriginalGroup; private Call.State mState = Call.State.IDLE; private SipProfile mPeer; private boolean mIncoming = false; @@ -676,6 +697,7 @@ public class SipPhone extends SipPhoneBase { } void hold() throws CallStateException { + setState(Call.State.HOLDING); try { mSipAudioCall.holdCall(); } catch (SipException e) { @@ -683,7 +705,9 @@ public class SipPhone extends SipPhoneBase { } } - void unhold() throws CallStateException { + void unhold(AudioGroup audioGroup) throws CallStateException { + mSipAudioCall.setAudioGroup(audioGroup); + setState(Call.State.ACTIVE); try { mSipAudioCall.continueCall(); } catch (SipException e) { @@ -691,16 +715,6 @@ public class SipPhone extends SipPhoneBase { } } - void mergeTo(AudioGroup group) throws CallStateException { - AudioStream stream = mSipAudioCall.getAudioStream(); - if (stream == null) { - throw new CallStateException("wrong state to merge: " - + mSipAudioCall.getState()); - } - if (mOriginalGroup == null) mOriginalGroup = getAudioGroup(); - stream.join(group); - } - @Override protected void setState(Call.State state) { if (state == mState) return; @@ -735,29 +749,36 @@ public class SipPhone extends SipPhoneBase { @Override public void hangup() throws CallStateException { - // TODO: need to pull AudioStream out of the AudioGroup in case - // this conn was part of a conf call - Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": " - + ": on phone " + getPhone()); - try { - mSipAudioCall.endCall(); - setState(Call.State.DISCONNECTING); - setDisconnectCause(DisconnectCause.LOCAL); - } catch (SipException e) { - throw new CallStateException("hangup(): " + e); + synchronized (SipPhone.class) { + Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": " + + ": on phone " + getPhone().getPhoneName()); + try { + mSipAudioCall.endCall(); + setState(Call.State.DISCONNECTING); + setDisconnectCause(DisconnectCause.LOCAL); + } catch (SipException e) { + throw new CallStateException("hangup(): " + e); + } } } @Override public void separate() throws CallStateException { - // TODO: what's this for SIP? - /* - if (!disconnected) { - owner.separate(this); - } else { - throw new CallStateException ("disconnected"); + synchronized (SipPhone.class) { + SipCall call = (SipCall) SipPhone.this.getBackgroundCall(); + if (call.getState() != Call.State.IDLE) { + throw new CallStateException( + "cannot put conn back to a call in non-idle state: " + + call.getState()); + } + Log.v(LOG_TAG, "separate conn: " + mPeer.getUriString() + + " from " + mOwner + " back to " + call); + + AudioGroup audioGroup = call.getAudioGroup(); // may be null + call.add(this); + mSipAudioCall.setAudioGroup(audioGroup); + call.hold(); } - */ } } diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java index 721b8af..1d33be9 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java @@ -174,10 +174,6 @@ abstract class SipPhoneBase extends PhoneBase { return state; } - public String getPhoneName() { - return "SIP"; - } - public int getPhoneType() { // FIXME: add SIP phone type return Phone.PHONE_TYPE_GSM; diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java index f4be839..3cdd114 100644 --- a/voip/java/android/net/sip/SipAudioCall.java +++ b/voip/java/android/net/sip/SipAudioCall.java @@ -244,7 +244,8 @@ public interface SipAudioCall { * Also, the {@code AudioStream} may change its group during a call (e.g., * after the call is held/un-held). Finally, the {@code AudioGroup} object * returned by this method is undefined after the call ends or the - * {@link #close} method is called. + * {@link #close} method is called. If a group object is set by + * {@link #setAudioGroup(AudioGroup)}, then this method returns that object. * * @return the {@link AudioGroup} object or null if the RTP stream has not * yet been set up @@ -253,6 +254,15 @@ public interface SipAudioCall { AudioGroup getAudioGroup(); /** + * Sets the {@link AudioGroup} object which the {@link AudioStream} object + * joins. If {@code audioGroup} is null, then the {@code AudioGroup} object + * will be dynamically created when needed. + * + * @see #getAudioStream + */ + void setAudioGroup(AudioGroup audioGroup); + + /** * Checks if the call is established. * * @return true if the call is established diff --git a/voip/java/android/net/sip/SipAudioCallImpl.java b/voip/java/android/net/sip/SipAudioCallImpl.java index 7161309..b8ac6d7 100644 --- a/voip/java/android/net/sip/SipAudioCallImpl.java +++ b/voip/java/android/net/sip/SipAudioCallImpl.java @@ -70,7 +70,8 @@ public class SipAudioCallImpl extends SipSessionAdapter private ISipSession mSipSession; private SdpSessionDescription mPeerSd; - private AudioStream mRtpSession; + private AudioStream mAudioStream; + private AudioGroup mAudioGroup; private SdpSessionDescription.AudioCodec mCodec; private long mSessionId = -1L; // SDP session ID private boolean mInCall = false; @@ -505,11 +506,19 @@ public class SipAudioCallImpl extends SipSessionAdapter } public synchronized AudioStream getAudioStream() { - return mRtpSession; + return mAudioStream; } public synchronized AudioGroup getAudioGroup() { - return ((mRtpSession == null) ? null : mRtpSession.getAudioGroup()); + if (mAudioGroup != null) return mAudioGroup; + return ((mAudioStream == null) ? null : mAudioStream.getAudioGroup()); + } + + public synchronized void setAudioGroup(AudioGroup group) { + if ((mAudioStream != null) && (mAudioStream.getAudioGroup() != null)) { + mAudioStream.join(group); + } + mAudioGroup = group; } private SdpSessionDescription.AudioCodec getCodec(SdpSessionDescription sd) { @@ -561,7 +570,7 @@ public class SipAudioCallImpl extends SipSessionAdapter // TODO: get sample rate from sdp mCodec = getCodec(peerSd); - AudioStream audioStream = mRtpSession; + AudioStream audioStream = mAudioStream; audioStream.associate(InetAddress.getByName(peerMediaAddress), peerMediaPort); audioStream.setCodec(convert(mCodec), mCodec.payloadType); @@ -580,7 +589,7 @@ public class SipAudioCallImpl extends SipSessionAdapter Log.d(TAG, " not sending"); audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY); } - } else { + /* The recorder volume will be very low if the device is in * IN_CALL mode. Therefore, we have to set the mode to NORMAL * in order to have the normal microphone level. @@ -590,14 +599,22 @@ public class SipAudioCallImpl extends SipSessionAdapter .setMode(AudioManager.MODE_NORMAL); } - AudioGroup audioGroup = new AudioGroup(); - audioStream.join(audioGroup); + // AudioGroup logic: + AudioGroup audioGroup = getAudioGroup(); if (mHold) { - audioGroup.setMode(AudioGroup.MODE_ON_HOLD); - } else if (mMuted) { - audioGroup.setMode(AudioGroup.MODE_MUTED); + if (audioGroup != null) { + audioGroup.setMode(AudioGroup.MODE_ON_HOLD); + } + // don't create an AudioGroup here; doing so will fail if + // there's another AudioGroup out there that's active } else { - audioGroup.setMode(AudioGroup.MODE_NORMAL); + if (audioGroup == null) audioGroup = new AudioGroup(); + audioStream.join(audioGroup); + if (mMuted) { + audioGroup.setMode(AudioGroup.MODE_MUTED); + } else { + audioGroup.setMode(AudioGroup.MODE_NORMAL); + } } } catch (Exception e) { Log.e(TAG, "call()", e); @@ -606,20 +623,20 @@ public class SipAudioCallImpl extends SipSessionAdapter private void stopCall(boolean releaseSocket) { Log.d(TAG, "stop audiocall"); - if (mRtpSession != null) { - mRtpSession.join(null); + if (mAudioStream != null) { + mAudioStream.join(null); if (releaseSocket) { - mRtpSession.release(); - mRtpSession = null; + mAudioStream.release(); + mAudioStream = null; } } } private int getLocalMediaPort() { - if (mRtpSession != null) return mRtpSession.getLocalPort(); + if (mAudioStream != null) return mAudioStream.getLocalPort(); try { - AudioStream s = mRtpSession = + AudioStream s = mAudioStream = new AudioStream(InetAddress.getByName(getLocalIp())); return s.getLocalPort(); } catch (IOException e) { |
