1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.rtp;
18 
19 import java.net.InetAddress;
20 import java.net.SocketException;
21 
22 /**
23  * An AudioStream is a {@link RtpStream} which carrys audio payloads over
24  * Real-time Transport Protocol (RTP). Two different classes are developed in
25  * order to support various usages such as audio conferencing. An AudioStream
26  * represents a remote endpoint which consists of a network mapping and a
27  * configured {@link AudioCodec}. On the other side, An {@link AudioGroup}
28  * represents a local endpoint which mixes all the AudioStreams and optionally
29  * interacts with the speaker and the microphone at the same time. The simplest
30  * usage includes one for each endpoints. For other combinations, developers
31  * should be aware of the limitations described in {@link AudioGroup}.
32  *
33  * <p>An AudioStream becomes busy when it joins an AudioGroup. In this case most
34  * of the setter methods are disabled. This is designed to ease the task of
35  * managing native resources. One can always make an AudioStream leave its
36  * AudioGroup by calling {@link #join(AudioGroup)} with {@code null} and put it
37  * back after the modification is done.</p>
38  *
39  * <p class="note">Using this class requires
40  * {@link android.Manifest.permission#INTERNET} permission.</p>
41  *
42  * @see RtpStream
43  * @see AudioGroup
44  * @deprecated {@link android.net.sip.SipManager} and associated classes are no longer supported and
45  * should not be used as the basis of future VOIP apps.
46  */
47 public class AudioStream extends RtpStream {
48     private AudioCodec mCodec;
49     private int mDtmfType = -1;
50     private AudioGroup mGroup;
51 
52     /**
53      * Creates an AudioStream on the given local address. Note that the local
54      * port is assigned automatically to conform with RFC 3550.
55      *
56      * @param address The network address of the local host to bind to.
57      * @throws SocketException if the address cannot be bound or a problem
58      *     occurs during binding.
59      */
AudioStream(InetAddress address)60     public AudioStream(InetAddress address) throws SocketException {
61         super(address);
62     }
63 
64     /**
65      * Returns {@code true} if the stream has already joined an
66      * {@link AudioGroup}.
67      */
68     @Override
isBusy()69     public final boolean isBusy() {
70         return mGroup != null;
71     }
72 
73     /**
74      * Returns the joined {@link AudioGroup}.
75      */
getGroup()76     public AudioGroup getGroup() {
77         return mGroup;
78     }
79 
80     /**
81      * Joins an {@link AudioGroup}. Each stream can join only one group at a
82      * time. The group can be changed by passing a different one or removed
83      * by calling this method with {@code null}.
84      *
85      * @param group The AudioGroup to join or {@code null} to leave.
86      * @throws IllegalStateException if the stream is not properly configured.
87      * @see AudioGroup
88      */
join(AudioGroup group)89     public void join(AudioGroup group) {
90         synchronized (this) {
91             if (mGroup == group) {
92                 return;
93             }
94             if (mGroup != null) {
95                 mGroup.remove(this);
96                 mGroup = null;
97             }
98             if (group != null) {
99                 group.add(this);
100                 mGroup = group;
101             }
102         }
103     }
104 
105     /**
106      * Returns the {@link AudioCodec}, or {@code null} if it is not set.
107      *
108      * @see #setCodec(AudioCodec)
109      */
getCodec()110     public AudioCodec getCodec() {
111         return mCodec;
112     }
113 
114     /**
115      * Sets the {@link AudioCodec}.
116      *
117      * @param codec The AudioCodec to be used.
118      * @throws IllegalArgumentException if its type is used by DTMF.
119      * @throws IllegalStateException if the stream is busy.
120      */
setCodec(AudioCodec codec)121     public void setCodec(AudioCodec codec) {
122         if (isBusy()) {
123             throw new IllegalStateException("Busy");
124         }
125         if (codec.type == mDtmfType) {
126             throw new IllegalArgumentException("The type is used by DTMF");
127         }
128         mCodec = codec;
129     }
130 
131     /**
132      * Returns the RTP payload type for dual-tone multi-frequency (DTMF) digits,
133      * or {@code -1} if it is not enabled.
134      *
135      * @see #setDtmfType(int)
136      */
getDtmfType()137     public int getDtmfType() {
138         return mDtmfType;
139     }
140 
141     /**
142      * Sets the RTP payload type for dual-tone multi-frequency (DTMF) digits.
143      * The primary usage is to send digits to the remote gateway to perform
144      * certain tasks, such as second-stage dialing. According to RFC 2833, the
145      * RTP payload type for DTMF is assigned dynamically, so it must be in the
146      * range of 96 and 127. One can use {@code -1} to disable DTMF and free up
147      * the previous assigned type. This method cannot be called when the stream
148      * already joined an {@link AudioGroup}.
149      *
150      * @param type The RTP payload type to be used or {@code -1} to disable it.
151      * @throws IllegalArgumentException if the type is invalid or used by codec.
152      * @throws IllegalStateException if the stream is busy.
153      * @see AudioGroup#sendDtmf(int)
154      */
setDtmfType(int type)155     public void setDtmfType(int type) {
156         if (isBusy()) {
157             throw new IllegalStateException("Busy");
158         }
159         if (type != -1) {
160             if (type < 96 || type > 127) {
161                 throw new IllegalArgumentException("Invalid type");
162             }
163             if (mCodec != null && type == mCodec.type) {
164                 throw new IllegalArgumentException("The type is used by codec");
165             }
166         }
167         mDtmfType = type;
168     }
169 }
170