SipAudioCall: expose startAudio()

so that apps can start audio when time is right.

Change-Id: I7ae96689d3a8006b34097533bc2434bc3814b82a
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index d7dc4ab..3e8867b 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -626,6 +626,7 @@
                     if (newState == Call.State.INCOMING) {
                         setState(mOwner.getState()); // INCOMING or WAITING
                     } else {
+                        if (newState == Call.State.ACTIVE) call.startAudio();
                         setState(newState);
                     }
                     mOwner.onConnectionStateChanged(SipConnection.this);
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index 2a9a65b..4abea20 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -153,7 +153,7 @@
     void setListener(Listener listener, boolean callbackImmediately);
 
     /**
-     * Closes this object. The object is not usable after being closed.
+     * Closes this object. This object is not usable after being closed.
      */
     void close();
 
@@ -172,6 +172,12 @@
             throws SipException;
 
     /**
+     * Starts the audio for the established call. This method should be called
+     * after {@link Listener#onCallEstablished} is called.
+     */
+    void startAudio();
+
+    /**
      * Attaches an incoming call to this call object.
      *
      * @param session the session that receives the incoming call
diff --git a/voip/java/android/net/sip/SipAudioCallImpl.java b/voip/java/android/net/sip/SipAudioCallImpl.java
index fcabcc4..e61e878 100644
--- a/voip/java/android/net/sip/SipAudioCallImpl.java
+++ b/voip/java/android/net/sip/SipAudioCallImpl.java
@@ -37,6 +37,7 @@
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -239,24 +240,18 @@
         }
     }
 
-    private synchronized void establishCall(String sessionDescription) {
-        stopRingbackTone();
-        stopRinging();
-        try {
-            SdpSessionDescription sd =
-                    new SdpSessionDescription(sessionDescription);
-            Log.d(TAG, "sip call established: " + sd);
-            startCall(sd);
-            mInCall = true;
-        } catch (SdpException e) {
-            Log.e(TAG, "createSessionDescription()", e);
-        }
-    }
-
     @Override
     public void onCallEstablished(ISipSession session,
             String sessionDescription) {
-        establishCall(sessionDescription);
+        stopRingbackTone();
+        stopRinging();
+        try {
+            mPeerSd = new SdpSessionDescription(sessionDescription);
+            Log.d(TAG, "sip call established: " + mPeerSd);
+        } catch (SdpException e) {
+            Log.e(TAG, "createSessionDescription()", e);
+        }
+
         Listener listener = mListener;
         if (listener != null) {
             try {
@@ -609,10 +604,23 @@
         return copies;
     }
 
-    private void startCall(SdpSessionDescription peerSd) {
+    public void startAudio() {
+        try {
+            startAudioInternal();
+        } catch (UnknownHostException e) {
+            onError(mSipSession, SipErrorCode.PEER_NOT_REACHABLE.toString(),
+                    e.getMessage());
+        } catch (Throwable e) {
+            onError(mSipSession, SipErrorCode.CLIENT_ERROR.toString(),
+                    e.getMessage());
+        }
+    }
+
+    private synchronized void startAudioInternal() throws UnknownHostException {
         stopCall(DONT_RELEASE_SOCKET);
+        mInCall = true;
+        SdpSessionDescription peerSd = mPeerSd;
         if (isWifiOn()) grabWifiHighPerfLock();
-        mPeerSd = peerSd;
         String peerMediaAddress = peerSd.getPeerMediaAddress(AUDIO);
         // TODO: handle multiple media fields
         int peerMediaPort = peerSd.getPeerMediaPort(AUDIO);
@@ -621,58 +629,55 @@
         int localPort = getLocalMediaPort();
         int sampleRate = 8000;
         int frameSize = sampleRate / 50; // 160
-        try {
-            // TODO: get sample rate from sdp
-            mCodec = getCodec(peerSd);
 
-            AudioStream audioStream = mAudioStream;
-            audioStream.associate(InetAddress.getByName(peerMediaAddress),
-                    peerMediaPort);
-            audioStream.setCodec(convert(mCodec), mCodec.payloadType);
-            audioStream.setDtmfType(DTMF);
-            Log.d(TAG, "start media: localPort=" + localPort + ", peer="
-                    + peerMediaAddress + ":" + peerMediaPort);
+        // TODO: get sample rate from sdp
+        mCodec = getCodec(peerSd);
 
-            audioStream.setMode(RtpStream.MODE_NORMAL);
-            if (!mHold) {
-                // FIXME: won't work if peer is not sending nor receiving
-                if (!peerSd.isSending(AUDIO)) {
-                    Log.d(TAG, "   not receiving");
-                    audioStream.setMode(RtpStream.MODE_SEND_ONLY);
-                }
-                if (!peerSd.isReceiving(AUDIO)) {
-                    Log.d(TAG, "   not sending");
-                    audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY);
-                }
+        AudioStream audioStream = mAudioStream;
+        audioStream.associate(InetAddress.getByName(peerMediaAddress),
+                peerMediaPort);
+        audioStream.setCodec(convert(mCodec), mCodec.payloadType);
+        audioStream.setDtmfType(DTMF);
+        Log.d(TAG, "start media: localPort=" + localPort + ", peer="
+                + peerMediaAddress + ":" + peerMediaPort);
 
-                /* 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.
-                 */
-                ((AudioManager) mContext.getSystemService
-                        (Context.AUDIO_SERVICE))
-                        .setMode(AudioManager.MODE_NORMAL);
+        audioStream.setMode(RtpStream.MODE_NORMAL);
+        if (!mHold) {
+            // FIXME: won't work if peer is not sending nor receiving
+            if (!peerSd.isSending(AUDIO)) {
+                Log.d(TAG, "   not receiving");
+                audioStream.setMode(RtpStream.MODE_SEND_ONLY);
+            }
+            if (!peerSd.isReceiving(AUDIO)) {
+                Log.d(TAG, "   not sending");
+                audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY);
             }
 
-            // AudioGroup logic:
-            AudioGroup audioGroup = getAudioGroup();
-            if (mHold) {
-                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
+            /* 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.
+             */
+            ((AudioManager) mContext.getSystemService
+                    (Context.AUDIO_SERVICE))
+                    .setMode(AudioManager.MODE_NORMAL);
+        }
+
+        // AudioGroup logic:
+        AudioGroup audioGroup = getAudioGroup();
+        if (mHold) {
+            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 {
+            if (audioGroup == null) audioGroup = new AudioGroup();
+            audioStream.join(audioGroup);
+            if (mMuted) {
+                audioGroup.setMode(AudioGroup.MODE_MUTED);
             } else {
-                if (audioGroup == null) audioGroup = new AudioGroup();
-                audioStream.join(audioGroup);
-                if (mMuted) {
-                    audioGroup.setMode(AudioGroup.MODE_MUTED);
-                } else {
-                    audioGroup.setMode(AudioGroup.MODE_NORMAL);
-                }
+                audioGroup.setMode(AudioGroup.MODE_NORMAL);
             }
-        } catch (Exception e) {
-            Log.e(TAG, "call()", e);
         }
     }