summaryrefslogtreecommitdiffstats
path: root/voip
diff options
context:
space:
mode:
authorChia-chi Yeh <chiachi@android.com>2010-11-30 19:45:47 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-11-30 19:45:47 -0800
commit4c7cc83827458945fe7a1f4bd2bfe0629f0d30ae (patch)
tree4fa585b3536dd2b65eaf5ef92fbd12a357507605 /voip
parent1f2451007c660091b7b090c1ea332f9044515d2d (diff)
parent53aa6ef70d8692277f9403f94d43918ad9712dd0 (diff)
downloadframeworks_base-4c7cc83827458945fe7a1f4bd2bfe0629f0d30ae.zip
frameworks_base-4c7cc83827458945fe7a1f4bd2bfe0629f0d30ae.tar.gz
frameworks_base-4c7cc83827458945fe7a1f4bd2bfe0629f0d30ae.tar.bz2
Merge "RTP: Prepare to unhide the APIs."
Diffstat (limited to 'voip')
-rw-r--r--voip/java/android/net/rtp/AudioGroup.java110
-rw-r--r--voip/java/android/net/rtp/AudioStream.java28
-rw-r--r--voip/java/android/net/rtp/RtpStream.java7
-rw-r--r--voip/jni/rtp/AmrCodec.cpp2
-rw-r--r--voip/jni/rtp/AudioGroup.cpp18
5 files changed, 107 insertions, 58 deletions
diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java
index 43a3827..a6b54d8 100644
--- a/voip/java/android/net/rtp/AudioGroup.java
+++ b/voip/java/android/net/rtp/AudioGroup.java
@@ -21,14 +21,14 @@ import java.util.Map;
/**
* An AudioGroup acts as a router connected to the speaker, the microphone, and
- * {@link AudioStream}s. Its pipeline has four steps. First, for each
- * AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its incoming
- * packets and stores in its buffer. Then, if the microphone is enabled,
- * processes the recorded audio and stores in its buffer. Third, if the speaker
- * is enabled, mixes and playbacks buffers of all AudioStreams. Finally, for
- * each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all other
- * buffers and sends back the encoded packets. An AudioGroup does nothing if
- * there is no AudioStream in it.
+ * {@link AudioStream}s. Its execution loop consists of four steps. First, for
+ * each AudioStream not in {@link RtpStream#MODE_SEND_ONLY}, decodes its
+ * incoming packets and stores in its buffer. Then, if the microphone is
+ * enabled, processes the recorded audio and stores in its buffer. Third, if the
+ * speaker is enabled, mixes and playbacks buffers of all AudioStreams. Finally,
+ * for each AudioStream not in {@link RtpStream#MODE_RECEIVE_ONLY}, mixes all
+ * other buffers and sends back the encoded packets. An AudioGroup does nothing
+ * if there is no AudioStream in it.
*
* <p>Few things must be noticed before using these classes. The performance is
* highly related to the system load and the network bandwidth. Usually a
@@ -47,7 +47,12 @@ import java.util.Map;
* modes other than {@link #MODE_ON_HOLD}. In addition, before adding an
* AudioStream into an AudioGroup, one should always put all other AudioGroups
* into {@link #MODE_ON_HOLD}. That will make sure the audio driver correctly
- * initialized.
+ * initialized.</p>
+ *
+ * <p class="note">Using this class requires
+ * {@link android.Manifest.permission#RECORD_AUDIO} permission.</p>
+ *
+ * @see AudioStream
* @hide
*/
public class AudioGroup {
@@ -78,6 +83,8 @@ public class AudioGroup {
*/
public static final int MODE_ECHO_SUPPRESSION = 3;
+ private static final int MODE_LAST = 3;
+
private final Map<AudioStream, Integer> mStreams;
private int mMode = MODE_ON_HOLD;
@@ -94,6 +101,15 @@ public class AudioGroup {
}
/**
+ * Returns the {@link AudioStream}s in this group.
+ */
+ public AudioStream[] getStreams() {
+ synchronized (this) {
+ return mStreams.keySet().toArray(new AudioStream[mStreams.size()]);
+ }
+ }
+
+ /**
* Returns the current mode.
*/
public int getMode() {
@@ -108,49 +124,77 @@ public class AudioGroup {
* @param mode The mode to change to.
* @throws IllegalArgumentException if the mode is invalid.
*/
- public synchronized native void setMode(int mode);
-
- private native void add(int mode, int socket, String remoteAddress,
- int remotePort, String codecSpec, int dtmfType);
+ public void setMode(int mode) {
+ if (mode < 0 || mode > MODE_LAST) {
+ throw new IllegalArgumentException("Invalid mode");
+ }
+ synchronized (this) {
+ nativeSetMode(mode);
+ mMode = mode;
+ }
+ }
- synchronized void add(AudioStream stream, AudioCodec codec, int dtmfType) {
- if (!mStreams.containsKey(stream)) {
- try {
- int socket = stream.dup();
- String codecSpec = String.format("%d %s %s", codec.type,
- codec.rtpmap, codec.fmtp);
- add(stream.getMode(), socket,
- stream.getRemoteAddress().getHostAddress(),
- stream.getRemotePort(), codecSpec, dtmfType);
- mStreams.put(stream, socket);
- } catch (NullPointerException e) {
- throw new IllegalStateException(e);
+ private native void nativeSetMode(int mode);
+
+ // Package-private method used by AudioStream.join().
+ void add(AudioStream stream, AudioCodec codec, int dtmfType) {
+ synchronized (this) {
+ if (!mStreams.containsKey(stream)) {
+ try {
+ int socket = stream.dup();
+ String codecSpec = String.format("%d %s %s", codec.type,
+ codec.rtpmap, codec.fmtp);
+ nativeAdd(stream.getMode(), socket,
+ stream.getRemoteAddress().getHostAddress(),
+ stream.getRemotePort(), codecSpec, dtmfType);
+ mStreams.put(stream, socket);
+ } catch (NullPointerException e) {
+ throw new IllegalStateException(e);
+ }
}
}
}
- private native void remove(int socket);
+ private native void nativeAdd(int mode, int socket, String remoteAddress,
+ int remotePort, String codecSpec, int dtmfType);
- synchronized void remove(AudioStream stream) {
- Integer socket = mStreams.remove(stream);
- if (socket != null) {
- remove(socket);
+ // Package-private method used by AudioStream.join().
+ void remove(AudioStream stream) {
+ synchronized (this) {
+ Integer socket = mStreams.remove(stream);
+ if (socket != null) {
+ nativeRemove(socket);
+ }
}
}
+ private native void nativeRemove(int socket);
+
/**
* Sends a DTMF digit to every {@link AudioStream} in this group. Currently
* only event {@code 0} to {@code 15} are supported.
*
* @throws IllegalArgumentException if the event is invalid.
*/
- public native synchronized void sendDtmf(int event);
+ public void sendDtmf(int event) {
+ if (event < 0 || event > 15) {
+ throw new IllegalArgumentException("Invalid event");
+ }
+ synchronized (this) {
+ nativeSendDtmf(event);
+ }
+ }
+
+ private native void nativeSendDtmf(int event);
/**
* Removes every {@link AudioStream} in this group.
*/
- public synchronized void clear() {
- remove(-1);
+ public void clear() {
+ synchronized (this) {
+ mStreams.clear();
+ nativeRemove(-1);
+ }
}
@Override
diff --git a/voip/java/android/net/rtp/AudioStream.java b/voip/java/android/net/rtp/AudioStream.java
index e5197ce..0edae6b 100644
--- a/voip/java/android/net/rtp/AudioStream.java
+++ b/voip/java/android/net/rtp/AudioStream.java
@@ -34,8 +34,12 @@ import java.net.SocketException;
* of the setter methods are disabled. This is designed to ease the task of
* managing native resources. One can always make an AudioStream leave its
* AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it
- * back after the modification is done.
+ * back after the modification is done.</p>
*
+ * <p class="note">Using this class requires
+ * {@link android.Manifest.permission#INTERNET} permission.</p>
+ *
+ * @see RtpStream
* @see AudioGroup
* @hide
*/
@@ -82,16 +86,18 @@ public class AudioStream extends RtpStream {
* @see AudioGroup
*/
public void join(AudioGroup group) {
- if (mGroup == group) {
- return;
- }
- if (mGroup != null) {
- mGroup.remove(this);
- mGroup = null;
- }
- if (group != null) {
- group.add(this, mCodec, mDtmfType);
- mGroup = group;
+ synchronized (this) {
+ if (mGroup == group) {
+ return;
+ }
+ if (mGroup != null) {
+ mGroup.remove(this);
+ mGroup = null;
+ }
+ if (group != null) {
+ group.add(this, mCodec, mDtmfType);
+ mGroup = group;
+ }
}
}
diff --git a/voip/java/android/net/rtp/RtpStream.java b/voip/java/android/net/rtp/RtpStream.java
index 23fb258..87d8bc6 100644
--- a/voip/java/android/net/rtp/RtpStream.java
+++ b/voip/java/android/net/rtp/RtpStream.java
@@ -24,6 +24,9 @@ import java.net.SocketException;
/**
* RtpStream represents the base class of streams which send and receive network
* packets with media payloads over Real-time Transport Protocol (RTP).
+ *
+ * <p class="note">Using this class requires
+ * {@link android.Manifest.permission#INTERNET} permission.</p>
* @hide
*/
public class RtpStream {
@@ -43,6 +46,8 @@ public class RtpStream {
*/
public static final int MODE_RECEIVE_ONLY = 2;
+ private static final int MODE_LAST = 2;
+
private final InetAddress mLocalAddress;
private final int mLocalPort;
@@ -129,7 +134,7 @@ public class RtpStream {
if (isBusy()) {
throw new IllegalStateException("Busy");
}
- if (mode != MODE_NORMAL && mode != MODE_SEND_ONLY && mode != MODE_RECEIVE_ONLY) {
+ if (mode < 0 || mode > MODE_LAST) {
throw new IllegalArgumentException("Invalid mode");
}
mMode = mode;
diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp
index 72ee44e..84c7166 100644
--- a/voip/jni/rtp/AmrCodec.cpp
+++ b/voip/jni/rtp/AmrCodec.cpp
@@ -73,7 +73,7 @@ int AmrCodec::set(int sampleRate, const char *fmtp)
}
// Handle mode-set and octet-align.
- char *modes = (char*)strcasestr(fmtp, "mode-set=");
+ const char *modes = strcasestr(fmtp, "mode-set=");
if (modes) {
mMode = 0;
mModeSet = 0;
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 0c8a725..cba1123 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -90,6 +90,7 @@ public:
void encode(int tick, AudioStream *chain);
void decode(int tick);
+private:
enum {
NORMAL = 0,
SEND_ONLY = 1,
@@ -97,7 +98,6 @@ public:
LAST_MODE = 2,
};
-private:
int mMode;
int mSocket;
sockaddr_storage mRemote;
@@ -463,6 +463,7 @@ public:
bool add(AudioStream *stream);
bool remove(int socket);
+private:
enum {
ON_HOLD = 0,
MUTED = 1,
@@ -471,7 +472,6 @@ public:
LAST_MODE = 3,
};
-private:
AudioStream *mChain;
int mEventQueue;
volatile int mDtmfEvent;
@@ -948,16 +948,10 @@ void remove(JNIEnv *env, jobject thiz, jint socket)
void setMode(JNIEnv *env, jobject thiz, jint mode)
{
- if (mode < 0 || mode > AudioGroup::LAST_MODE) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
- }
AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative);
if (group && !group->setMode(mode)) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
- return;
}
- env->SetIntField(thiz, gMode, mode);
}
void sendDtmf(JNIEnv *env, jobject thiz, jint event)
@@ -969,10 +963,10 @@ void sendDtmf(JNIEnv *env, jobject thiz, jint event)
}
JNINativeMethod gMethods[] = {
- {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add},
- {"remove", "(I)V", (void *)remove},
- {"setMode", "(I)V", (void *)setMode},
- {"sendDtmf", "(I)V", (void *)sendDtmf},
+ {"nativeAdd", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add},
+ {"nativeRemove", "(I)V", (void *)remove},
+ {"nativeSetMode", "(I)V", (void *)setMode},
+ {"nativeSendDtmf", "(I)V", (void *)sendDtmf},
};
} // namespace