Add CTS test for android.net.rtp.

Bug: 5975113
Change-Id: I20ec3b172a2d6501048418f4c3da06d1b7144fd3
diff --git a/tests/cts/net/AndroidManifest.xml b/tests/cts/net/AndroidManifest.xml
index 4fa0565..b3556f5 100644
--- a/tests/cts/net/AndroidManifest.xml
+++ b/tests/cts/net/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java
new file mode 100644
index 0000000..412498c
--- /dev/null
+++ b/tests/cts/net/src/android/net/rtp/cts/AudioCodecTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.rtp.cts;
+
+import android.net.rtp.AudioCodec;
+import android.test.AndroidTestCase;
+
+public class AudioCodecTest extends AndroidTestCase {
+
+    private void assertEquals(AudioCodec codec, int type, String rtpmap, String fmtp) {
+        if (type >= 0) {
+            assertEquals(codec.type, type);
+        } else {
+            assertTrue(codec.type >= 96 && codec.type <= 127);
+        }
+        assertEquals(codec.rtpmap.compareToIgnoreCase(rtpmap), 0);
+        assertEquals(codec.fmtp, fmtp);
+    }
+
+    public void testConstants() throws Exception {
+        assertEquals(AudioCodec.PCMU, 0, "PCMU/8000", null);
+        assertEquals(AudioCodec.PCMA, 8, "PCMA/8000", null);
+        assertEquals(AudioCodec.GSM, 3, "GSM/8000", null);
+        assertEquals(AudioCodec.GSM_EFR, -1, "GSM-EFR/8000", null);
+        assertEquals(AudioCodec.AMR, -1, "AMR/8000", null);
+
+        assertFalse(AudioCodec.AMR.type == AudioCodec.GSM_EFR.type);
+    }
+
+    public void testGetCodec() throws Exception {
+        // Bad types.
+        assertNull(AudioCodec.getCodec(128, "PCMU/8000", null));
+        assertNull(AudioCodec.getCodec(-1, "PCMU/8000", null));
+        assertNull(AudioCodec.getCodec(96, null, null));
+
+        // Fixed types.
+        assertEquals(AudioCodec.getCodec(0, null, null), 0, "PCMU/8000", null);
+        assertEquals(AudioCodec.getCodec(8, null, null), 8, "PCMA/8000", null);
+        assertEquals(AudioCodec.getCodec(3, null, null), 3, "GSM/8000", null);
+
+        // Dynamic types.
+        assertEquals(AudioCodec.getCodec(96, "pcmu/8000", null), 96, "PCMU/8000", null);
+        assertEquals(AudioCodec.getCodec(97, "pcma/8000", null), 97, "PCMA/8000", null);
+        assertEquals(AudioCodec.getCodec(98, "gsm/8000", null), 98, "GSM/8000", null);
+        assertEquals(AudioCodec.getCodec(99, "gsm-efr/8000", null), 99, "GSM-EFR/8000", null);
+        assertEquals(AudioCodec.getCodec(100, "amr/8000", null), 100, "AMR/8000", null);
+    }
+
+    public void testGetCodecs() throws Exception {
+        AudioCodec[] codecs = AudioCodec.getCodecs();
+        assertTrue(codecs.length >= 5);
+
+        // The types of the codecs should be different.
+        boolean[] types = new boolean[128];
+        for (AudioCodec codec : codecs) {
+            assertFalse(types[codec.type]);
+            types[codec.type] = true;
+        }
+    }
+}
diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java
new file mode 100644
index 0000000..f06d7e9
--- /dev/null
+++ b/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.rtp.cts;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.net.rtp.AudioCodec;
+import android.net.rtp.AudioGroup;
+import android.net.rtp.AudioStream;
+import android.net.rtp.RtpStream;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+
+public class AudioGroupTest extends AndroidTestCase {
+
+    private static final String TAG = AudioGroupTest.class.getSimpleName();
+
+    private AudioManager mAudioManager;
+
+    private AudioStream mStreamA;
+    private DatagramSocket mSocketA;
+    private AudioStream mStreamB;
+    private DatagramSocket mSocketB;
+    private AudioGroup mGroup;
+
+    @Override
+    public void setUp() throws Exception {
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+
+        InetAddress local = InetAddress.getByName("::1");
+
+        mStreamA = new AudioStream(local);
+        mStreamA.setMode(RtpStream.MODE_NORMAL);
+        mStreamA.setCodec(AudioCodec.PCMU);
+        mSocketA = new DatagramSocket();
+        mSocketA.connect(mStreamA.getLocalAddress(), mStreamA.getLocalPort());
+        mStreamA.associate(mSocketA.getLocalAddress(), mSocketA.getLocalPort());
+
+        mStreamB = new AudioStream(local);
+        mStreamB.setMode(RtpStream.MODE_NORMAL);
+        mStreamB.setCodec(AudioCodec.PCMU);
+        mSocketB = new DatagramSocket();
+        mSocketB.connect(mStreamB.getLocalAddress(), mStreamB.getLocalPort());
+        mStreamB.associate(mSocketB.getLocalAddress(), mSocketB.getLocalPort());
+
+        mGroup = new AudioGroup();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mGroup.clear();
+        mStreamA.release();
+        mSocketA.close();
+        mStreamB.release();
+        mSocketB.close();
+        mAudioManager.setMode(AudioManager.MODE_NORMAL);
+    }
+
+    private void assertPacket(DatagramSocket socket, int length) throws Exception {
+        DatagramPacket packet = new DatagramPacket(new byte[length + 1], length + 1);
+        socket.setSoTimeout(3000);
+        socket.receive(packet);
+        assertEquals(packet.getLength(), length);
+    }
+
+    private void drain(DatagramSocket socket) throws Exception {
+        DatagramPacket packet = new DatagramPacket(new byte[1], 1);
+        socket.setSoTimeout(1);
+        try {
+            // Drain the socket by retrieving all the packets queued on it.
+            // A SocketTimeoutException will be thrown when it becomes empty.
+            while (true) {
+                socket.receive(packet);
+            }
+        } catch (Exception e) {
+            // ignore.
+        }
+    }
+
+    public void testTraffic() throws Exception {
+        mStreamA.join(mGroup);
+        assertPacket(mSocketA, 12 + 160);
+
+        mStreamB.join(mGroup);
+        assertPacket(mSocketB, 12 + 160);
+
+        mStreamA.join(null);
+        drain(mSocketA);
+
+        drain(mSocketB);
+        assertPacket(mSocketB, 12 + 160);
+
+        mStreamA.join(mGroup);
+        assertPacket(mSocketA, 12 + 160);
+    }
+
+    public void testSetMode() throws Exception {
+        mGroup.setMode(AudioGroup.MODE_NORMAL);
+        assertEquals(mGroup.getMode(), AudioGroup.MODE_NORMAL);
+
+        mGroup.setMode(AudioGroup.MODE_MUTED);
+        assertEquals(mGroup.getMode(), AudioGroup.MODE_MUTED);
+
+        mStreamA.join(mGroup);
+        mStreamB.join(mGroup);
+
+        mGroup.setMode(AudioGroup.MODE_NORMAL);
+        assertEquals(mGroup.getMode(), AudioGroup.MODE_NORMAL);
+
+        mGroup.setMode(AudioGroup.MODE_MUTED);
+        assertEquals(mGroup.getMode(), AudioGroup.MODE_MUTED);
+    }
+
+    public void testAdd() throws Exception {
+        mStreamA.join(mGroup);
+        assertEquals(mGroup.getStreams().length, 1);
+
+        mStreamB.join(mGroup);
+        assertEquals(mGroup.getStreams().length, 2);
+
+        mStreamA.join(mGroup);
+        assertEquals(mGroup.getStreams().length, 2);
+    }
+
+    public void testRemove() throws Exception {
+        mStreamA.join(mGroup);
+        assertEquals(mGroup.getStreams().length, 1);
+
+        mStreamA.join(null);
+        assertEquals(mGroup.getStreams().length, 0);
+
+        mStreamA.join(mGroup);
+        assertEquals(mGroup.getStreams().length, 1);
+    }
+
+    public void testClear() throws Exception {
+        mStreamA.join(mGroup);
+        mStreamB.join(mGroup);
+        mGroup.clear();
+
+        assertEquals(mGroup.getStreams().length, 0);
+        assertFalse(mStreamA.isBusy());
+        assertFalse(mStreamB.isBusy());
+    }
+
+    public void testDoubleClear() throws Exception {
+        mStreamA.join(mGroup);
+        mStreamB.join(mGroup);
+        mGroup.clear();
+        mGroup.clear();
+    }
+}
diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java
new file mode 100644
index 0000000..323b022
--- /dev/null
+++ b/tests/cts/net/src/android/net/rtp/cts/AudioStreamTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.rtp.cts;
+
+import android.net.rtp.AudioCodec;
+import android.net.rtp.AudioStream;
+import android.test.AndroidTestCase;
+
+import java.net.InetAddress;
+
+public class AudioStreamTest extends AndroidTestCase {
+
+    private void testRtpStream(InetAddress address) throws Exception {
+        AudioStream stream = new AudioStream(address);
+        assertEquals(stream.getLocalAddress(), address);
+        assertEquals(stream.getLocalPort() % 2, 0);
+
+        assertNull(stream.getRemoteAddress());
+        assertEquals(stream.getRemotePort(), -1);
+        stream.associate(address, 1000);
+        assertEquals(stream.getRemoteAddress(), address);
+        assertEquals(stream.getRemotePort(), 1000);
+
+        assertFalse(stream.isBusy());
+        stream.release();
+    }
+
+    public void testV4Stream() throws Exception {
+        testRtpStream(InetAddress.getByName("127.0.0.1"));
+    }
+
+    public void testV6Stream() throws Exception {
+        testRtpStream(InetAddress.getByName("::1"));
+    }
+
+    public void testSetDtmfType() throws Exception {
+        AudioStream stream = new AudioStream(InetAddress.getByName("::1"));
+
+        assertEquals(stream.getDtmfType(), -1);
+        try {
+            stream.setDtmfType(0);
+            fail("Expecting IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
+        stream.setDtmfType(96);
+        assertEquals(stream.getDtmfType(), 96);
+
+        stream.setCodec(AudioCodec.getCodec(97, "PCMU/8000", null));
+        try {
+            stream.setDtmfType(97);
+            fail("Expecting IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
+        stream.release();
+    }
+
+    public void testSetCodec() throws Exception {
+        AudioStream stream = new AudioStream(InetAddress.getByName("::1"));
+
+        assertNull(stream.getCodec());
+        stream.setCodec(AudioCodec.getCodec(97, "PCMU/8000", null));
+        assertNotNull(stream.getCodec());
+
+        stream.setDtmfType(96);
+        try {
+            stream.setCodec(AudioCodec.getCodec(96, "PCMU/8000", null));
+            fail("Expecting IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
+        stream.release();
+    }
+
+    public void testDoubleRelease() throws Exception {
+        AudioStream stream = new AudioStream(InetAddress.getByName("::1"));
+        stream.release();
+        stream.release();
+    }
+}