diff options
author | Wink Saville <wink@google.com> | 2013-01-28 15:27:47 -0800 |
---|---|---|
committer | Wink Saville <wink@google.com> | 2013-01-28 15:27:47 -0800 |
commit | cbb2a2a207796a68eff26be001af2797594d3b3c (patch) | |
tree | ae7d166136064ba408035fa741bb944441fddb47 /voip/java/android/net/sip | |
parent | 29e4aa7abe6b0c62f31fb23b8572cd5b91f08f5c (diff) | |
download | frameworks_base-cbb2a2a207796a68eff26be001af2797594d3b3c.zip frameworks_base-cbb2a2a207796a68eff26be001af2797594d3b3c.tar.gz frameworks_base-cbb2a2a207796a68eff26be001af2797594d3b3c.tar.bz2 |
Delete frameworks/base/voip use voip-common from frameworks/opt/net/voip
Change-Id: Ieaba759a0f69b45c4b8839cbed1fe757cdf190c5
Diffstat (limited to 'voip/java/android/net/sip')
-rw-r--r-- | voip/java/android/net/sip/ISipService.aidl | 43 | ||||
-rw-r--r-- | voip/java/android/net/sip/ISipSession.aidl | 148 | ||||
-rw-r--r-- | voip/java/android/net/sip/ISipSessionListener.aidl | 133 | ||||
-rw-r--r-- | voip/java/android/net/sip/SimpleSessionDescription.java | 613 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipAudioCall.java | 1143 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipErrorCode.java | 101 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipException.java | 37 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipManager.java | 622 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipProfile.aidl | 19 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipProfile.java | 502 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipRegistrationListener.java | 48 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipSession.java | 574 | ||||
-rw-r--r-- | voip/java/android/net/sip/SipSessionAdapter.java | 68 | ||||
-rw-r--r-- | voip/java/android/net/sip/package.html | 45 |
14 files changed, 0 insertions, 4096 deletions
diff --git a/voip/java/android/net/sip/ISipService.aidl b/voip/java/android/net/sip/ISipService.aidl deleted file mode 100644 index 3250bf9..0000000 --- a/voip/java/android/net/sip/ISipService.aidl +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.app.PendingIntent; -import android.net.sip.ISipSession; -import android.net.sip.ISipSessionListener; -import android.net.sip.SipProfile; - -/** - * {@hide} - */ -interface ISipService { - void open(in SipProfile localProfile); - void open3(in SipProfile localProfile, - in PendingIntent incomingCallPendingIntent, - in ISipSessionListener listener); - void close(in String localProfileUri); - boolean isOpened(String localProfileUri); - boolean isRegistered(String localProfileUri); - void setRegistrationListener(String localProfileUri, - ISipSessionListener listener); - - ISipSession createSession(in SipProfile localProfile, - in ISipSessionListener listener); - ISipSession getPendingSession(String callId); - - SipProfile[] getListOfProfiles(); -} diff --git a/voip/java/android/net/sip/ISipSession.aidl b/voip/java/android/net/sip/ISipSession.aidl deleted file mode 100644 index 2d515db..0000000 --- a/voip/java/android/net/sip/ISipSession.aidl +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.net.sip.ISipSessionListener; -import android.net.sip.SipProfile; - -/** - * A SIP session that is associated with a SIP dialog or a transaction that is - * not within a dialog. - * @hide - */ -interface ISipSession { - /** - * Gets the IP address of the local host on which this SIP session runs. - * - * @return the IP address of the local host - */ - String getLocalIp(); - - /** - * Gets the SIP profile that this session is associated with. - * - * @return the SIP profile that this session is associated with - */ - SipProfile getLocalProfile(); - - /** - * Gets the SIP profile that this session is connected to. Only available - * when the session is associated with a SIP dialog. - * - * @return the SIP profile that this session is connected to - */ - SipProfile getPeerProfile(); - - /** - * Gets the session state. The value returned must be one of the states in - * {@link SipSessionState}. - * - * @return the session state - */ - int getState(); - - /** - * Checks if the session is in a call. - * - * @return true if the session is in a call - */ - boolean isInCall(); - - /** - * Gets the call ID of the session. - * - * @return the call ID - */ - String getCallId(); - - - /** - * Sets the listener to listen to the session events. A {@link ISipSession} - * can only hold one listener at a time. Subsequent calls to this method - * override the previous listener. - * - * @param listener to listen to the session events of this object - */ - void setListener(in ISipSessionListener listener); - - - /** - * Performs registration to the server specified by the associated local - * profile. The session listener is called back upon success or failure of - * registration. The method is only valid to call when the session state is - * in {@link SipSessionState#READY_TO_CALL}. - * - * @param duration duration in second before the registration expires - * @see ISipSessionListener - */ - void register(int duration); - - /** - * Performs unregistration to the server specified by the associated local - * profile. Unregistration is technically the same as registration with zero - * expiration duration. The session listener is called back upon success or - * failure of unregistration. The method is only valid to call when the - * session state is in {@link SipSessionState#READY_TO_CALL}. - * - * @see ISipSessionListener - */ - void unregister(); - - /** - * Initiates a call to the specified profile. The session listener is called - * back upon defined session events. The method is only valid to call when - * the session state is in {@link SipSessionState#READY_TO_CALL}. - * - * @param callee the SIP profile to make the call to - * @param sessionDescription the session description of this call - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds - * @see ISipSessionListener - */ - void makeCall(in SipProfile callee, String sessionDescription, int timeout); - - /** - * Answers an incoming call with the specified session description. The - * method is only valid to call when the session state is in - * {@link SipSessionState#INCOMING_CALL}. - * - * @param sessionDescription the session description to answer this call - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds - */ - void answerCall(String sessionDescription, int timeout); - - /** - * Ends an established call, terminates an outgoing call or rejects an - * incoming call. The method is only valid to call when the session state is - * in {@link SipSessionState#IN_CALL}, - * {@link SipSessionState#INCOMING_CALL}, - * {@link SipSessionState#OUTGOING_CALL} or - * {@link SipSessionState#OUTGOING_CALL_RING_BACK}. - */ - void endCall(); - - /** - * Changes the session description during a call. The method is only valid - * to call when the session state is in {@link SipSessionState#IN_CALL}. - * - * @param sessionDescription the new session description - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds - */ - void changeCall(String sessionDescription, int timeout); -} diff --git a/voip/java/android/net/sip/ISipSessionListener.aidl b/voip/java/android/net/sip/ISipSessionListener.aidl deleted file mode 100644 index 690700c..0000000 --- a/voip/java/android/net/sip/ISipSessionListener.aidl +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.net.sip.ISipSession; -import android.net.sip.SipProfile; - -/** - * Listener class to listen to SIP session events. - * @hide - */ -interface ISipSessionListener { - /** - * Called when an INVITE request is sent to initiate a new call. - * - * @param session the session object that carries out the transaction - */ - void onCalling(in ISipSession session); - - /** - * Called when an INVITE request is received. - * - * @param session the session object that carries out the transaction - * @param caller the SIP profile of the caller - * @param sessionDescription the caller's session description - */ - void onRinging(in ISipSession session, in SipProfile caller, - String sessionDescription); - - /** - * Called when a RINGING response is received for the INVITE request sent - * - * @param session the session object that carries out the transaction - */ - void onRingingBack(in ISipSession session); - - /** - * Called when the session is established. - * - * @param session the session object that is associated with the dialog - * @param sessionDescription the peer's session description - */ - void onCallEstablished(in ISipSession session, - String sessionDescription); - - /** - * Called when the session is terminated. - * - * @param session the session object that is associated with the dialog - */ - void onCallEnded(in ISipSession session); - - /** - * Called when the peer is busy during session initialization. - * - * @param session the session object that carries out the transaction - */ - void onCallBusy(in ISipSession session); - - /** - * Called when the call is being transferred to a new one. - * - * @param newSession the new session that the call will be transferred to - * @param sessionDescription the new peer's session description - */ - void onCallTransferring(in ISipSession newSession, String sessionDescription); - - /** - * Called when an error occurs during session initialization and - * termination. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - void onError(in ISipSession session, int errorCode, String errorMessage); - - /** - * Called when an error occurs during session modification negotiation. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - void onCallChangeFailed(in ISipSession session, int errorCode, - String errorMessage); - - /** - * Called when a registration request is sent. - * - * @param session the session object that carries out the transaction - */ - void onRegistering(in ISipSession session); - - /** - * Called when registration is successfully done. - * - * @param session the session object that carries out the transaction - * @param duration duration in second before the registration expires - */ - void onRegistrationDone(in ISipSession session, int duration); - - /** - * Called when the registration fails. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - void onRegistrationFailed(in ISipSession session, int errorCode, - String errorMessage); - - /** - * Called when the registration gets timed out. - * - * @param session the session object that carries out the transaction - */ - void onRegistrationTimeout(in ISipSession session); -} diff --git a/voip/java/android/net/sip/SimpleSessionDescription.java b/voip/java/android/net/sip/SimpleSessionDescription.java deleted file mode 100644 index 9fcd21d..0000000 --- a/voip/java/android/net/sip/SimpleSessionDescription.java +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; - -/** - * An object used to manipulate messages of Session Description Protocol (SDP). - * It is mainly designed for the uses of Session Initiation Protocol (SIP). - * Therefore, it only handles connection addresses ("c="), bandwidth limits, - * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this - * implementation does not support multicast sessions. - * - * <p>Here is an example code to create a session description.</p> - * <pre> - * SimpleSessionDescription description = new SimpleSessionDescription( - * System.currentTimeMillis(), "1.2.3.4"); - * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP"); - * media.setRtpPayload(0, "PCMU/8000", null); - * media.setRtpPayload(8, "PCMA/8000", null); - * media.setRtpPayload(127, "telephone-event/8000", "0-15"); - * media.setAttribute("sendrecv", ""); - * </pre> - * <p>Invoking <code>description.encode()</code> will produce a result like the - * one below.</p> - * <pre> - * v=0 - * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4 - * s=- - * c=IN IP4 1.2.3.4 - * t=0 0 - * m=audio 56789 RTP/AVP 0 8 127 - * a=rtpmap:0 PCMU/8000 - * a=rtpmap:8 PCMA/8000 - * a=rtpmap:127 telephone-event/8000 - * a=fmtp:127 0-15 - * a=sendrecv - * </pre> - * @hide - */ -public class SimpleSessionDescription { - private final Fields mFields = new Fields("voscbtka"); - private final ArrayList<Media> mMedia = new ArrayList<Media>(); - - /** - * Creates a minimal session description from the given session ID and - * unicast address. The address is used in the origin field ("o=") and the - * connection field ("c="). See {@link SimpleSessionDescription} for an - * example of its usage. - */ - public SimpleSessionDescription(long sessionId, String address) { - address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address; - mFields.parse("v=0"); - mFields.parse(String.format(Locale.US, "o=- %d %d %s", sessionId, - System.currentTimeMillis(), address)); - mFields.parse("s=-"); - mFields.parse("t=0 0"); - mFields.parse("c=" + address); - } - - /** - * Creates a session description from the given message. - * - * @throws IllegalArgumentException if message is invalid. - */ - public SimpleSessionDescription(String message) { - String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+"); - Fields fields = mFields; - - for (String line : lines) { - try { - if (line.charAt(1) != '=') { - throw new IllegalArgumentException(); - } - if (line.charAt(0) == 'm') { - String[] parts = line.substring(2).split(" ", 4); - String[] ports = parts[1].split("/", 2); - Media media = newMedia(parts[0], Integer.parseInt(ports[0]), - (ports.length < 2) ? 1 : Integer.parseInt(ports[1]), - parts[2]); - for (String format : parts[3].split(" ")) { - media.setFormat(format, null); - } - fields = media; - } else { - fields.parse(line); - } - } catch (Exception e) { - throw new IllegalArgumentException("Invalid SDP: " + line); - } - } - } - - /** - * Creates a new media description in this session description. - * - * @param type The media type, e.g. {@code "audio"}. - * @param port The first transport port used by this media. - * @param portCount The number of contiguous ports used by this media. - * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}. - */ - public Media newMedia(String type, int port, int portCount, - String protocol) { - Media media = new Media(type, port, portCount, protocol); - mMedia.add(media); - return media; - } - - /** - * Returns all the media descriptions in this session description. - */ - public Media[] getMedia() { - return mMedia.toArray(new Media[mMedia.size()]); - } - - /** - * Encodes the session description and all its media descriptions in a - * string. Note that the result might be incomplete if a required field - * has never been added before. - */ - public String encode() { - StringBuilder buffer = new StringBuilder(); - mFields.write(buffer); - for (Media media : mMedia) { - media.write(buffer); - } - return buffer.toString(); - } - - /** - * Returns the connection address or {@code null} if it is not present. - */ - public String getAddress() { - return mFields.getAddress(); - } - - /** - * Sets the connection address. The field will be removed if the address - * is {@code null}. - */ - public void setAddress(String address) { - mFields.setAddress(address); - } - - /** - * Returns the encryption method or {@code null} if it is not present. - */ - public String getEncryptionMethod() { - return mFields.getEncryptionMethod(); - } - - /** - * Returns the encryption key or {@code null} if it is not present. - */ - public String getEncryptionKey() { - return mFields.getEncryptionKey(); - } - - /** - * Sets the encryption method and the encryption key. The field will be - * removed if the method is {@code null}. - */ - public void setEncryption(String method, String key) { - mFields.setEncryption(method, key); - } - - /** - * Returns the types of the bandwidth limits. - */ - public String[] getBandwidthTypes() { - return mFields.getBandwidthTypes(); - } - - /** - * Returns the bandwidth limit of the given type or {@code -1} if it is not - * present. - */ - public int getBandwidth(String type) { - return mFields.getBandwidth(type); - } - - /** - * Sets the bandwith limit for the given type. The field will be removed if - * the value is negative. - */ - public void setBandwidth(String type, int value) { - mFields.setBandwidth(type, value); - } - - /** - * Returns the names of all the attributes. - */ - public String[] getAttributeNames() { - return mFields.getAttributeNames(); - } - - /** - * Returns the attribute of the given name or {@code null} if it is not - * present. - */ - public String getAttribute(String name) { - return mFields.getAttribute(name); - } - - /** - * Sets the attribute for the given name. The field will be removed if - * the value is {@code null}. To set a binary attribute, use an empty - * string as the value. - */ - public void setAttribute(String name, String value) { - mFields.setAttribute(name, value); - } - - /** - * This class represents a media description of a session description. It - * can only be created by {@link SimpleSessionDescription#newMedia}. Since - * the syntax is more restricted for RTP based protocols, two sets of access - * methods are implemented. See {@link SimpleSessionDescription} for an - * example of its usage. - */ - public static class Media extends Fields { - private final String mType; - private final int mPort; - private final int mPortCount; - private final String mProtocol; - private ArrayList<String> mFormats = new ArrayList<String>(); - - private Media(String type, int port, int portCount, String protocol) { - super("icbka"); - mType = type; - mPort = port; - mPortCount = portCount; - mProtocol = protocol; - } - - /** - * Returns the media type. - */ - public String getType() { - return mType; - } - - /** - * Returns the first transport port used by this media. - */ - public int getPort() { - return mPort; - } - - /** - * Returns the number of contiguous ports used by this media. - */ - public int getPortCount() { - return mPortCount; - } - - /** - * Returns the transport protocol. - */ - public String getProtocol() { - return mProtocol; - } - - /** - * Returns the media formats. - */ - public String[] getFormats() { - return mFormats.toArray(new String[mFormats.size()]); - } - - /** - * Returns the {@code fmtp} attribute of the given format or - * {@code null} if it is not present. - */ - public String getFmtp(String format) { - return super.get("a=fmtp:" + format, ' '); - } - - /** - * Sets a format and its {@code fmtp} attribute. If the attribute is - * {@code null}, the corresponding field will be removed. - */ - public void setFormat(String format, String fmtp) { - mFormats.remove(format); - mFormats.add(format); - super.set("a=rtpmap:" + format, ' ', null); - super.set("a=fmtp:" + format, ' ', fmtp); - } - - /** - * Removes a format and its {@code fmtp} attribute. - */ - public void removeFormat(String format) { - mFormats.remove(format); - super.set("a=rtpmap:" + format, ' ', null); - super.set("a=fmtp:" + format, ' ', null); - } - - /** - * Returns the RTP payload types. - */ - public int[] getRtpPayloadTypes() { - int[] types = new int[mFormats.size()]; - int length = 0; - for (String format : mFormats) { - try { - types[length] = Integer.parseInt(format); - ++length; - } catch (NumberFormatException e) { } - } - return Arrays.copyOf(types, length); - } - - /** - * Returns the {@code rtpmap} attribute of the given RTP payload type - * or {@code null} if it is not present. - */ - public String getRtpmap(int type) { - return super.get("a=rtpmap:" + type, ' '); - } - - /** - * Returns the {@code fmtp} attribute of the given RTP payload type or - * {@code null} if it is not present. - */ - public String getFmtp(int type) { - return super.get("a=fmtp:" + type, ' '); - } - - /** - * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp} - * attributes. If any of the attributes is {@code null}, the - * corresponding field will be removed. See - * {@link SimpleSessionDescription} for an example of its usage. - */ - public void setRtpPayload(int type, String rtpmap, String fmtp) { - String format = String.valueOf(type); - mFormats.remove(format); - mFormats.add(format); - super.set("a=rtpmap:" + format, ' ', rtpmap); - super.set("a=fmtp:" + format, ' ', fmtp); - } - - /** - * Removes a RTP payload and its {@code rtpmap} and {@code fmtp} - * attributes. - */ - public void removeRtpPayload(int type) { - removeFormat(String.valueOf(type)); - } - - private void write(StringBuilder buffer) { - buffer.append("m=").append(mType).append(' ').append(mPort); - if (mPortCount != 1) { - buffer.append('/').append(mPortCount); - } - buffer.append(' ').append(mProtocol); - for (String format : mFormats) { - buffer.append(' ').append(format); - } - buffer.append("\r\n"); - super.write(buffer); - } - } - - /** - * This class acts as a set of fields, and the size of the set is expected - * to be small. Therefore, it uses a simple list instead of maps. Each field - * has three parts: a key, a delimiter, and a value. Delimiters are special - * because they are not included in binary attributes. As a result, the - * private methods, which are the building blocks of this class, all take - * the delimiter as an argument. - */ - private static class Fields { - private final String mOrder; - private final ArrayList<String> mLines = new ArrayList<String>(); - - Fields(String order) { - mOrder = order; - } - - /** - * Returns the connection address or {@code null} if it is not present. - */ - public String getAddress() { - String address = get("c", '='); - if (address == null) { - return null; - } - String[] parts = address.split(" "); - if (parts.length != 3) { - return null; - } - int slash = parts[2].indexOf('/'); - return (slash < 0) ? parts[2] : parts[2].substring(0, slash); - } - - /** - * Sets the connection address. The field will be removed if the address - * is {@code null}. - */ - public void setAddress(String address) { - if (address != null) { - address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + - address; - } - set("c", '=', address); - } - - /** - * Returns the encryption method or {@code null} if it is not present. - */ - public String getEncryptionMethod() { - String encryption = get("k", '='); - if (encryption == null) { - return null; - } - int colon = encryption.indexOf(':'); - return (colon == -1) ? encryption : encryption.substring(0, colon); - } - - /** - * Returns the encryption key or {@code null} if it is not present. - */ - public String getEncryptionKey() { - String encryption = get("k", '='); - if (encryption == null) { - return null; - } - int colon = encryption.indexOf(':'); - return (colon == -1) ? null : encryption.substring(0, colon + 1); - } - - /** - * Sets the encryption method and the encryption key. The field will be - * removed if the method is {@code null}. - */ - public void setEncryption(String method, String key) { - set("k", '=', (method == null || key == null) ? - method : method + ':' + key); - } - - /** - * Returns the types of the bandwidth limits. - */ - public String[] getBandwidthTypes() { - return cut("b=", ':'); - } - - /** - * Returns the bandwidth limit of the given type or {@code -1} if it is - * not present. - */ - public int getBandwidth(String type) { - String value = get("b=" + type, ':'); - if (value != null) { - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { } - setBandwidth(type, -1); - } - return -1; - } - - /** - * Sets the bandwith limit for the given type. The field will be removed - * if the value is negative. - */ - public void setBandwidth(String type, int value) { - set("b=" + type, ':', (value < 0) ? null : String.valueOf(value)); - } - - /** - * Returns the names of all the attributes. - */ - public String[] getAttributeNames() { - return cut("a=", ':'); - } - - /** - * Returns the attribute of the given name or {@code null} if it is not - * present. - */ - public String getAttribute(String name) { - return get("a=" + name, ':'); - } - - /** - * Sets the attribute for the given name. The field will be removed if - * the value is {@code null}. To set a binary attribute, use an empty - * string as the value. - */ - public void setAttribute(String name, String value) { - set("a=" + name, ':', value); - } - - private void write(StringBuilder buffer) { - for (int i = 0; i < mOrder.length(); ++i) { - char type = mOrder.charAt(i); - for (String line : mLines) { - if (line.charAt(0) == type) { - buffer.append(line).append("\r\n"); - } - } - } - } - - /** - * Invokes {@link #set} after splitting the line into three parts. - */ - private void parse(String line) { - char type = line.charAt(0); - if (mOrder.indexOf(type) == -1) { - return; - } - char delimiter = '='; - if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) { - delimiter = ' '; - } else if (type == 'b' || type == 'a') { - delimiter = ':'; - } - int i = line.indexOf(delimiter); - if (i == -1) { - set(line, delimiter, ""); - } else { - set(line.substring(0, i), delimiter, line.substring(i + 1)); - } - } - - /** - * Finds the key with the given prefix and returns its suffix. - */ - private String[] cut(String prefix, char delimiter) { - String[] names = new String[mLines.size()]; - int length = 0; - for (String line : mLines) { - if (line.startsWith(prefix)) { - int i = line.indexOf(delimiter); - if (i == -1) { - i = line.length(); - } - names[length] = line.substring(prefix.length(), i); - ++length; - } - } - return Arrays.copyOf(names, length); - } - - /** - * Returns the index of the key. - */ - private int find(String key, char delimiter) { - int length = key.length(); - for (int i = mLines.size() - 1; i >= 0; --i) { - String line = mLines.get(i); - if (line.startsWith(key) && (line.length() == length || - line.charAt(length) == delimiter)) { - return i; - } - } - return -1; - } - - /** - * Sets the key with the value or removes the key if the value is - * {@code null}. - */ - private void set(String key, char delimiter, String value) { - int index = find(key, delimiter); - if (value != null) { - if (value.length() != 0) { - key = key + delimiter + value; - } - if (index == -1) { - mLines.add(key); - } else { - mLines.set(index, key); - } - } else if (index != -1) { - mLines.remove(index); - } - } - - /** - * Returns the value of the key. - */ - private String get(String key, char delimiter) { - int index = find(key, delimiter); - if (index == -1) { - return null; - } - String line = mLines.get(index); - int length = key.length(); - return (line.length() == length) ? "" : line.substring(length + 1); - } - } -} diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java deleted file mode 100644 index ea943e9..0000000 --- a/voip/java/android/net/sip/SipAudioCall.java +++ /dev/null @@ -1,1143 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -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.net.sip.SimpleSessionDescription.Media; -import android.net.wifi.WifiManager; -import android.os.Message; -import android.telephony.Rlog; -import android.text.TextUtils; -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * Handles an Internet audio call over SIP. You can instantiate this class with {@link SipManager}, - * using {@link SipManager#makeAudioCall makeAudioCall()} and {@link SipManager#takeAudioCall - * takeAudioCall()}. - * - * <p class="note"><strong>Note:</strong> Using this class require the - * {@link android.Manifest.permission#INTERNET} and - * {@link android.Manifest.permission#USE_SIP} permissions. In addition, {@link - * #startAudio} requires the - * {@link android.Manifest.permission#RECORD_AUDIO}, - * {@link android.Manifest.permission#ACCESS_WIFI_STATE}, and - * {@link android.Manifest.permission#WAKE_LOCK} permissions; and {@link #setSpeakerMode - * setSpeakerMode()} requires the - * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} permission.</p> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For more information about using SIP, read the - * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> - * developer guide.</p> - * </div> - */ -public class SipAudioCall { - private static final String LOG_TAG = SipAudioCall.class.getSimpleName(); - private static final boolean DBG = true; - private static final boolean RELEASE_SOCKET = true; - private static final boolean DONT_RELEASE_SOCKET = false; - private static final int SESSION_TIMEOUT = 5; // in seconds - private static final int TRANSFER_TIMEOUT = 15; // in seconds - - /** Listener for events relating to a SIP call, such as when a call is being - * recieved ("on ringing") or a call is outgoing ("on calling"). - * <p>Many of these events are also received by {@link SipSession.Listener}.</p> - */ - public static class Listener { - /** - * Called when the call object is ready to make another call. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that is ready to make another call - */ - public void onReadyToCall(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when a request is sent out to initiate a new call. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onCalling(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when a new call comes in. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - * @param caller the SIP profile of the caller - */ - public void onRinging(SipAudioCall call, SipProfile caller) { - onChanged(call); - } - - /** - * Called when a RINGING response is received for the INVITE request - * sent. The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onRingingBack(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when the session is established. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onCallEstablished(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when the session is terminated. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onCallEnded(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when the peer is busy during session initialization. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onCallBusy(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when the call is on hold. - * The default implementation calls {@link #onChanged}. - * - * @param call the call object that carries out the audio call - */ - public void onCallHeld(SipAudioCall call) { - onChanged(call); - } - - /** - * Called when an error occurs. The default implementation is no op. - * - * @param call the call object that carries out the audio call - * @param errorCode error code of this error - * @param errorMessage error message - * @see SipErrorCode - */ - public void onError(SipAudioCall call, int errorCode, - String errorMessage) { - // no-op - } - - /** - * Called when an event occurs and the corresponding callback is not - * overridden. The default implementation is no op. Error events are - * not re-directed to this callback and are handled in {@link #onError}. - */ - public void onChanged(SipAudioCall call) { - // no-op - } - } - - private Context mContext; - private SipProfile mLocalProfile; - private SipAudioCall.Listener mListener; - private SipSession mSipSession; - private SipSession mTransferringSession; - - private long mSessionId = System.currentTimeMillis(); - private String mPeerSd; - - private AudioStream mAudioStream; - private AudioGroup mAudioGroup; - - private boolean mInCall = false; - private boolean mMuted = false; - private boolean mHold = false; - - private WifiManager mWm; - private WifiManager.WifiLock mWifiHighPerfLock; - - private int mErrorCode = SipErrorCode.NO_ERROR; - private String mErrorMessage; - - /** - * Creates a call object with the local SIP profile. - * @param context the context for accessing system services such as - * ringtone, audio, WIFI etc - */ - public SipAudioCall(Context context, SipProfile localProfile) { - mContext = context; - mLocalProfile = localProfile; - mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - } - - /** - * Sets the listener to listen to the audio call events. The method calls - * {@link #setListener setListener(listener, false)}. - * - * @param listener to listen to the audio call events of this object - * @see #setListener(Listener, boolean) - */ - public void setListener(SipAudioCall.Listener listener) { - setListener(listener, false); - } - - /** - * Sets the listener to listen to the audio call events. A - * {@link SipAudioCall} can only hold one listener at a time. Subsequent - * calls to this method override the previous listener. - * - * @param listener to listen to the audio call events of this object - * @param callbackImmediately set to true if the caller wants to be called - * back immediately on the current state - */ - public void setListener(SipAudioCall.Listener listener, - boolean callbackImmediately) { - mListener = listener; - try { - if ((listener == null) || !callbackImmediately) { - // do nothing - } else if (mErrorCode != SipErrorCode.NO_ERROR) { - listener.onError(this, mErrorCode, mErrorMessage); - } else if (mInCall) { - if (mHold) { - listener.onCallHeld(this); - } else { - listener.onCallEstablished(this); - } - } else { - int state = getState(); - switch (state) { - case SipSession.State.READY_TO_CALL: - listener.onReadyToCall(this); - break; - case SipSession.State.INCOMING_CALL: - listener.onRinging(this, getPeerProfile()); - break; - case SipSession.State.OUTGOING_CALL: - listener.onCalling(this); - break; - case SipSession.State.OUTGOING_CALL_RING_BACK: - listener.onRingingBack(this); - break; - } - } - } catch (Throwable t) { - loge("setListener()", t); - } - } - - /** - * Checks if the call is established. - * - * @return true if the call is established - */ - public boolean isInCall() { - synchronized (this) { - return mInCall; - } - } - - /** - * Checks if the call is on hold. - * - * @return true if the call is on hold - */ - public boolean isOnHold() { - synchronized (this) { - return mHold; - } - } - - /** - * Closes this object. This object is not usable after being closed. - */ - public void close() { - close(true); - } - - private synchronized void close(boolean closeRtp) { - if (closeRtp) stopCall(RELEASE_SOCKET); - - mInCall = false; - mHold = false; - mSessionId = System.currentTimeMillis(); - mErrorCode = SipErrorCode.NO_ERROR; - mErrorMessage = null; - - if (mSipSession != null) { - mSipSession.setListener(null); - mSipSession = null; - } - } - - /** - * Gets the local SIP profile. - * - * @return the local SIP profile - */ - public SipProfile getLocalProfile() { - synchronized (this) { - return mLocalProfile; - } - } - - /** - * Gets the peer's SIP profile. - * - * @return the peer's SIP profile - */ - public SipProfile getPeerProfile() { - synchronized (this) { - return (mSipSession == null) ? null : mSipSession.getPeerProfile(); - } - } - - /** - * Gets the state of the {@link SipSession} that carries this call. - * The value returned must be one of the states in {@link SipSession.State}. - * - * @return the session state - */ - public int getState() { - synchronized (this) { - if (mSipSession == null) return SipSession.State.READY_TO_CALL; - return mSipSession.getState(); - } - } - - - /** - * Gets the {@link SipSession} that carries this call. - * - * @return the session object that carries this call - * @hide - */ - public SipSession getSipSession() { - synchronized (this) { - return mSipSession; - } - } - - private synchronized void transferToNewSession() { - if (mTransferringSession == null) return; - SipSession origin = mSipSession; - mSipSession = mTransferringSession; - mTransferringSession = null; - - // stop the replaced call. - if (mAudioStream != null) { - mAudioStream.join(null); - } else { - try { - mAudioStream = new AudioStream(InetAddress.getByName( - getLocalIp())); - } catch (Throwable t) { - loge("transferToNewSession():", t); - } - } - if (origin != null) origin.endCall(); - startAudio(); - } - - private SipSession.Listener createListener() { - return new SipSession.Listener() { - @Override - public void onCalling(SipSession session) { - if (DBG) log("onCalling: session=" + session); - Listener listener = mListener; - if (listener != null) { - try { - listener.onCalling(SipAudioCall.this); - } catch (Throwable t) { - loge("onCalling():", t); - } - } - } - - @Override - public void onRingingBack(SipSession session) { - if (DBG) log("onRingingBackk: " + session); - Listener listener = mListener; - if (listener != null) { - try { - listener.onRingingBack(SipAudioCall.this); - } catch (Throwable t) { - loge("onRingingBack():", t); - } - } - } - - @Override - public void onRinging(SipSession session, - SipProfile peerProfile, String sessionDescription) { - // this callback is triggered only for reinvite. - synchronized (SipAudioCall.this) { - if ((mSipSession == null) || !mInCall - || !session.getCallId().equals( - mSipSession.getCallId())) { - // should not happen - session.endCall(); - return; - } - - // session changing request - try { - String answer = createAnswer(sessionDescription).encode(); - mSipSession.answerCall(answer, SESSION_TIMEOUT); - } catch (Throwable e) { - loge("onRinging():", e); - session.endCall(); - } - } - } - - @Override - public void onCallEstablished(SipSession session, - String sessionDescription) { - mPeerSd = sessionDescription; - if (DBG) log("onCallEstablished(): " + mPeerSd); - - // TODO: how to notify the UI that the remote party is changed - if ((mTransferringSession != null) - && (session == mTransferringSession)) { - transferToNewSession(); - return; - } - - Listener listener = mListener; - if (listener != null) { - try { - if (mHold) { - listener.onCallHeld(SipAudioCall.this); - } else { - listener.onCallEstablished(SipAudioCall.this); - } - } catch (Throwable t) { - loge("onCallEstablished(): ", t); - } - } - } - - @Override - public void onCallEnded(SipSession session) { - if (DBG) log("onCallEnded: " + session + " mSipSession:" + mSipSession); - // reset the trasnferring session if it is the one. - if (session == mTransferringSession) { - mTransferringSession = null; - return; - } - // or ignore the event if the original session is being - // transferred to the new one. - if ((mTransferringSession != null) || - (session != mSipSession)) return; - - Listener listener = mListener; - if (listener != null) { - try { - listener.onCallEnded(SipAudioCall.this); - } catch (Throwable t) { - loge("onCallEnded(): ", t); - } - } - close(); - } - - @Override - public void onCallBusy(SipSession session) { - if (DBG) log("onCallBusy: " + session); - Listener listener = mListener; - if (listener != null) { - try { - listener.onCallBusy(SipAudioCall.this); - } catch (Throwable t) { - loge("onCallBusy(): ", t); - } - } - close(false); - } - - @Override - public void onCallChangeFailed(SipSession session, int errorCode, - String message) { - if (DBG) log("onCallChangedFailed: " + message); - mErrorCode = errorCode; - mErrorMessage = message; - Listener listener = mListener; - if (listener != null) { - try { - listener.onError(SipAudioCall.this, mErrorCode, - message); - } catch (Throwable t) { - loge("onCallBusy():", t); - } - } - } - - @Override - public void onError(SipSession session, int errorCode, - String message) { - SipAudioCall.this.onError(errorCode, message); - } - - @Override - public void onRegistering(SipSession session) { - // irrelevant - } - - @Override - public void onRegistrationTimeout(SipSession session) { - // irrelevant - } - - @Override - public void onRegistrationFailed(SipSession session, int errorCode, - String message) { - // irrelevant - } - - @Override - public void onRegistrationDone(SipSession session, int duration) { - // irrelevant - } - - @Override - public void onCallTransferring(SipSession newSession, - String sessionDescription) { - if (DBG) log("onCallTransferring: mSipSession=" - + mSipSession + " newSession=" + newSession); - mTransferringSession = newSession; - try { - if (sessionDescription == null) { - newSession.makeCall(newSession.getPeerProfile(), - createOffer().encode(), TRANSFER_TIMEOUT); - } else { - String answer = createAnswer(sessionDescription).encode(); - newSession.answerCall(answer, SESSION_TIMEOUT); - } - } catch (Throwable e) { - loge("onCallTransferring()", e); - newSession.endCall(); - } - } - }; - } - - private void onError(int errorCode, String message) { - if (DBG) log("onError: " - + SipErrorCode.toString(errorCode) + ": " + message); - mErrorCode = errorCode; - mErrorMessage = message; - Listener listener = mListener; - if (listener != null) { - try { - listener.onError(this, errorCode, message); - } catch (Throwable t) { - loge("onError():", t); - } - } - synchronized (this) { - if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST) - || !isInCall()) { - close(true); - } - } - } - - /** - * Attaches an incoming call to this call object. - * - * @param session the session that receives the incoming call - * @param sessionDescription the session description of the incoming call - * @throws SipException if the SIP service fails to attach this object to - * the session or VOIP API is not supported by the device - * @see SipManager#isVoipSupported - */ - public void attachCall(SipSession session, String sessionDescription) - throws SipException { - if (!SipManager.isVoipSupported(mContext)) { - throw new SipException("VOIP API is not supported"); - } - - synchronized (this) { - mSipSession = session; - mPeerSd = sessionDescription; - if (DBG) log("attachCall(): " + mPeerSd); - try { - session.setListener(createListener()); - } catch (Throwable e) { - loge("attachCall()", e); - throwSipException(e); - } - } - } - - /** - * Initiates an audio call to the specified profile. The attempt will be - * timed out if the call is not established within {@code timeout} seconds - * and {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param peerProfile the SIP profile to make the call to - * @param sipSession the {@link SipSession} for carrying out the call - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @see Listener#onError - * @throws SipException if the SIP service fails to create a session for the - * call or VOIP API is not supported by the device - * @see SipManager#isVoipSupported - */ - public void makeCall(SipProfile peerProfile, SipSession sipSession, - int timeout) throws SipException { - if (DBG) log("makeCall: " + peerProfile + " session=" + sipSession + " timeout=" + timeout); - if (!SipManager.isVoipSupported(mContext)) { - throw new SipException("VOIP API is not supported"); - } - - synchronized (this) { - mSipSession = sipSession; - try { - mAudioStream = new AudioStream(InetAddress.getByName( - getLocalIp())); - sipSession.setListener(createListener()); - sipSession.makeCall(peerProfile, createOffer().encode(), - timeout); - } catch (IOException e) { - loge("makeCall:", e); - throw new SipException("makeCall()", e); - } - } - } - - /** - * Ends a call. - * @throws SipException if the SIP service fails to end the call - */ - public void endCall() throws SipException { - if (DBG) log("endCall: mSipSession" + mSipSession); - synchronized (this) { - stopCall(RELEASE_SOCKET); - mInCall = false; - - // perform the above local ops first and then network op - if (mSipSession != null) mSipSession.endCall(); - } - } - - /** - * Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is - * called. The attempt will be timed out if the call is not established - * within {@code timeout} seconds and - * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @see Listener#onError - * @throws SipException if the SIP service fails to hold the call - */ - public void holdCall(int timeout) throws SipException { - if (DBG) log("holdCall: mSipSession" + mSipSession + " timeout=" + timeout); - synchronized (this) { - if (mHold) return; - if (mSipSession == null) { - loge("holdCall:"); - throw new SipException("Not in a call to hold call"); - } - mSipSession.changeCall(createHoldOffer().encode(), timeout); - mHold = true; - setAudioGroupMode(); - } - } - - /** - * Answers a call. The attempt will be timed out if the call is not - * established within {@code timeout} seconds and - * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @see Listener#onError - * @throws SipException if the SIP service fails to answer the call - */ - public void answerCall(int timeout) throws SipException { - if (DBG) log("answerCall: mSipSession" + mSipSession + " timeout=" + timeout); - synchronized (this) { - if (mSipSession == null) { - throw new SipException("No call to answer"); - } - try { - mAudioStream = new AudioStream(InetAddress.getByName( - getLocalIp())); - mSipSession.answerCall(createAnswer(mPeerSd).encode(), timeout); - } catch (IOException e) { - loge("answerCall:", e); - throw new SipException("answerCall()", e); - } - } - } - - /** - * Continues a call that's on hold. When succeeds, - * {@link Listener#onCallEstablished} is called. The attempt will be timed - * out if the call is not established within {@code timeout} seconds and - * {@link Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @see Listener#onError - * @throws SipException if the SIP service fails to unhold the call - */ - public void continueCall(int timeout) throws SipException { - if (DBG) log("continueCall: mSipSession" + mSipSession + " timeout=" + timeout); - synchronized (this) { - if (!mHold) return; - mSipSession.changeCall(createContinueOffer().encode(), timeout); - mHold = false; - setAudioGroupMode(); - } - } - - private SimpleSessionDescription createOffer() { - SimpleSessionDescription offer = - new SimpleSessionDescription(mSessionId, getLocalIp()); - AudioCodec[] codecs = AudioCodec.getCodecs(); - Media media = offer.newMedia( - "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP"); - for (AudioCodec codec : AudioCodec.getCodecs()) { - media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp); - } - media.setRtpPayload(127, "telephone-event/8000", "0-15"); - if (DBG) log("createOffer: offer=" + offer); - return offer; - } - - private SimpleSessionDescription createAnswer(String offerSd) { - if (TextUtils.isEmpty(offerSd)) return createOffer(); - SimpleSessionDescription offer = - new SimpleSessionDescription(offerSd); - SimpleSessionDescription answer = - new SimpleSessionDescription(mSessionId, getLocalIp()); - AudioCodec codec = null; - for (Media media : offer.getMedia()) { - if ((codec == null) && (media.getPort() > 0) - && "audio".equals(media.getType()) - && "RTP/AVP".equals(media.getProtocol())) { - // Find the first audio codec we supported. - for (int type : media.getRtpPayloadTypes()) { - codec = AudioCodec.getCodec(type, media.getRtpmap(type), - media.getFmtp(type)); - if (codec != null) { - break; - } - } - if (codec != null) { - Media reply = answer.newMedia( - "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP"); - reply.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp); - - // Check if DTMF is supported in the same media. - for (int type : media.getRtpPayloadTypes()) { - String rtpmap = media.getRtpmap(type); - if ((type != codec.type) && (rtpmap != null) - && rtpmap.startsWith("telephone-event")) { - reply.setRtpPayload( - type, rtpmap, media.getFmtp(type)); - } - } - - // Handle recvonly and sendonly. - if (media.getAttribute("recvonly") != null) { - answer.setAttribute("sendonly", ""); - } else if(media.getAttribute("sendonly") != null) { - answer.setAttribute("recvonly", ""); - } else if(offer.getAttribute("recvonly") != null) { - answer.setAttribute("sendonly", ""); - } else if(offer.getAttribute("sendonly") != null) { - answer.setAttribute("recvonly", ""); - } - continue; - } - } - // Reject the media. - Media reply = answer.newMedia( - media.getType(), 0, 1, media.getProtocol()); - for (String format : media.getFormats()) { - reply.setFormat(format, null); - } - } - if (codec == null) { - loge("createAnswer: no suitable codes"); - throw new IllegalStateException("Reject SDP: no suitable codecs"); - } - if (DBG) log("createAnswer: answer=" + answer); - return answer; - } - - private SimpleSessionDescription createHoldOffer() { - SimpleSessionDescription offer = createContinueOffer(); - offer.setAttribute("sendonly", ""); - if (DBG) log("createHoldOffer: offer=" + offer); - return offer; - } - - private SimpleSessionDescription createContinueOffer() { - if (DBG) log("createContinueOffer"); - SimpleSessionDescription offer = - new SimpleSessionDescription(mSessionId, getLocalIp()); - Media media = offer.newMedia( - "audio", mAudioStream.getLocalPort(), 1, "RTP/AVP"); - AudioCodec codec = mAudioStream.getCodec(); - media.setRtpPayload(codec.type, codec.rtpmap, codec.fmtp); - int dtmfType = mAudioStream.getDtmfType(); - if (dtmfType != -1) { - media.setRtpPayload(dtmfType, "telephone-event/8000", "0-15"); - } - return offer; - } - - private void grabWifiHighPerfLock() { - if (mWifiHighPerfLock == null) { - if (DBG) log("grabWifiHighPerfLock:"); - mWifiHighPerfLock = ((WifiManager) - mContext.getSystemService(Context.WIFI_SERVICE)) - .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, LOG_TAG); - mWifiHighPerfLock.acquire(); - } - } - - private void releaseWifiHighPerfLock() { - if (mWifiHighPerfLock != null) { - if (DBG) log("releaseWifiHighPerfLock:"); - mWifiHighPerfLock.release(); - mWifiHighPerfLock = null; - } - } - - private boolean isWifiOn() { - return (mWm.getConnectionInfo().getBSSID() == null) ? false : true; - } - - /** Toggles mute. */ - public void toggleMute() { - synchronized (this) { - mMuted = !mMuted; - setAudioGroupMode(); - } - } - - /** - * Checks if the call is muted. - * - * @return true if the call is muted - */ - public boolean isMuted() { - synchronized (this) { - return mMuted; - } - } - - /** - * Puts the device to speaker mode. - * <p class="note"><strong>Note:</strong> Requires the - * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} permission.</p> - * - * @param speakerMode set true to enable speaker mode; false to disable - */ - public void setSpeakerMode(boolean speakerMode) { - synchronized (this) { - ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)) - .setSpeakerphoneOn(speakerMode); - setAudioGroupMode(); - } - } - - private boolean isSpeakerOn() { - return ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)) - .isSpeakerphoneOn(); - } - - /** - * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2883</a>, - * event 0--9 maps to decimal - * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event - * flash to 16. Currently, event flash is not supported. - * - * @param code the DTMF code to send. Value 0 to 15 (inclusive) are valid - * inputs. - */ - public void sendDtmf(int code) { - sendDtmf(code, null); - } - - /** - * Sends a DTMF code. According to <a href="http://tools.ietf.org/html/rfc2833">RFC 2883</a>, - * event 0--9 maps to decimal - * value 0--9, '*' to 10, '#' to 11, event 'A'--'D' to 12--15, and event - * flash to 16. Currently, event flash is not supported. - * - * @param code the DTMF code to send. Value 0 to 15 (inclusive) are valid - * inputs. - * @param result the result message to send when done - */ - public void sendDtmf(int code, Message result) { - synchronized (this) { - AudioGroup audioGroup = getAudioGroup(); - if ((audioGroup != null) && (mSipSession != null) - && (SipSession.State.IN_CALL == getState())) { - if (DBG) log("sendDtmf: code=" + code + " result=" + result); - audioGroup.sendDtmf(code); - } - if (result != null) result.sendToTarget(); - } - } - - /** - * Gets the {@link AudioStream} object used in this call. The object - * represents the RTP stream that carries the audio data to and from the - * peer. The object may not be created before the call is established. And - * it is undefined after the call ends or the {@link #close} method is - * called. - * - * @return the {@link AudioStream} object or null if the RTP stream has not - * yet been set up - * @hide - */ - public AudioStream getAudioStream() { - synchronized (this) { - return mAudioStream; - } - } - - /** - * Gets the {@link AudioGroup} object which the {@link AudioStream} object - * joins. The group object may not exist before the call is established. - * 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. 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 - * @see #getAudioStream - * @hide - */ - public AudioGroup getAudioGroup() { - synchronized (this) { - if (mAudioGroup != null) return mAudioGroup; - return ((mAudioStream == null) ? null : mAudioStream.getGroup()); - } - } - - /** - * 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. Note that the mode of the - * {@code AudioGroup} is not changed according to the audio settings (i.e., - * hold, mute, speaker phone) of this object. This is mainly used to merge - * multiple {@code SipAudioCall} objects to form a conference call. The - * settings of the first object (that merges others) override others'. - * - * @see #getAudioStream - * @hide - */ - public void setAudioGroup(AudioGroup group) { - synchronized (this) { - if (DBG) log("setAudioGroup: group=" + group); - if ((mAudioStream != null) && (mAudioStream.getGroup() != null)) { - mAudioStream.join(group); - } - mAudioGroup = group; - } - } - - /** - * Starts the audio for the established call. This method should be called - * after {@link Listener#onCallEstablished} is called. - * <p class="note"><strong>Note:</strong> Requires the - * {@link android.Manifest.permission#RECORD_AUDIO}, - * {@link android.Manifest.permission#ACCESS_WIFI_STATE} and - * {@link android.Manifest.permission#WAKE_LOCK} permissions.</p> - */ - public void startAudio() { - try { - startAudioInternal(); - } catch (UnknownHostException e) { - onError(SipErrorCode.PEER_NOT_REACHABLE, e.getMessage()); - } catch (Throwable e) { - onError(SipErrorCode.CLIENT_ERROR, e.getMessage()); - } - } - - private synchronized void startAudioInternal() throws UnknownHostException { - if (DBG) loge("startAudioInternal: mPeerSd=" + mPeerSd); - if (mPeerSd == null) { - throw new IllegalStateException("mPeerSd = null"); - } - - stopCall(DONT_RELEASE_SOCKET); - mInCall = true; - - // Run exact the same logic in createAnswer() to setup mAudioStream. - SimpleSessionDescription offer = - new SimpleSessionDescription(mPeerSd); - AudioStream stream = mAudioStream; - AudioCodec codec = null; - for (Media media : offer.getMedia()) { - if ((codec == null) && (media.getPort() > 0) - && "audio".equals(media.getType()) - && "RTP/AVP".equals(media.getProtocol())) { - // Find the first audio codec we supported. - for (int type : media.getRtpPayloadTypes()) { - codec = AudioCodec.getCodec( - type, media.getRtpmap(type), media.getFmtp(type)); - if (codec != null) { - break; - } - } - - if (codec != null) { - // Associate with the remote host. - String address = media.getAddress(); - if (address == null) { - address = offer.getAddress(); - } - stream.associate(InetAddress.getByName(address), - media.getPort()); - - stream.setDtmfType(-1); - stream.setCodec(codec); - // Check if DTMF is supported in the same media. - for (int type : media.getRtpPayloadTypes()) { - String rtpmap = media.getRtpmap(type); - if ((type != codec.type) && (rtpmap != null) - && rtpmap.startsWith("telephone-event")) { - stream.setDtmfType(type); - } - } - - // Handle recvonly and sendonly. - if (mHold) { - stream.setMode(RtpStream.MODE_NORMAL); - } else if (media.getAttribute("recvonly") != null) { - stream.setMode(RtpStream.MODE_SEND_ONLY); - } else if(media.getAttribute("sendonly") != null) { - stream.setMode(RtpStream.MODE_RECEIVE_ONLY); - } else if(offer.getAttribute("recvonly") != null) { - stream.setMode(RtpStream.MODE_SEND_ONLY); - } else if(offer.getAttribute("sendonly") != null) { - stream.setMode(RtpStream.MODE_RECEIVE_ONLY); - } else { - stream.setMode(RtpStream.MODE_NORMAL); - } - break; - } - } - } - if (codec == null) { - throw new IllegalStateException("Reject SDP: no suitable codecs"); - } - - if (isWifiOn()) grabWifiHighPerfLock(); - - // AudioGroup logic: - AudioGroup audioGroup = getAudioGroup(); - if (mHold) { - // 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(); - stream.join(audioGroup); - } - setAudioGroupMode(); - } - - // set audio group mode based on current audio configuration - private void setAudioGroupMode() { - AudioGroup audioGroup = getAudioGroup(); - if (DBG) log("setAudioGroupMode: audioGroup=" + audioGroup); - if (audioGroup != null) { - if (mHold) { - audioGroup.setMode(AudioGroup.MODE_ON_HOLD); - } else if (mMuted) { - audioGroup.setMode(AudioGroup.MODE_MUTED); - } else if (isSpeakerOn()) { - audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION); - } else { - audioGroup.setMode(AudioGroup.MODE_NORMAL); - } - } - } - - private void stopCall(boolean releaseSocket) { - if (DBG) log("stopCall: releaseSocket=" + releaseSocket); - releaseWifiHighPerfLock(); - if (mAudioStream != null) { - mAudioStream.join(null); - - if (releaseSocket) { - mAudioStream.release(); - mAudioStream = null; - } - } - } - - private String getLocalIp() { - return mSipSession.getLocalIp(); - } - - private void throwSipException(Throwable throwable) throws SipException { - if (throwable instanceof SipException) { - throw (SipException) throwable; - } else { - throw new SipException("", throwable); - } - } - - private void log(String s) { - Rlog.d(LOG_TAG, s); - } - - private void loge(String s) { - Rlog.e(LOG_TAG, s); - } - - private void loge(String s, Throwable t) { - Rlog.e(LOG_TAG, s, t); - } -} diff --git a/voip/java/android/net/sip/SipErrorCode.java b/voip/java/android/net/sip/SipErrorCode.java deleted file mode 100644 index 509728f..0000000 --- a/voip/java/android/net/sip/SipErrorCode.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -/** - * Defines error codes returned during SIP actions. For example, during - * {@link SipRegistrationListener#onRegistrationFailed onRegistrationFailed()}, - * {@link SipSession.Listener#onError onError()}, - * {@link SipSession.Listener#onCallChangeFailed onCallChangeFailed()} and - * {@link SipSession.Listener#onRegistrationFailed onRegistrationFailed()}. - */ -public class SipErrorCode { - /** Not an error. */ - public static final int NO_ERROR = 0; - - /** When some socket error occurs. */ - public static final int SOCKET_ERROR = -1; - - /** When server responds with an error. */ - public static final int SERVER_ERROR = -2; - - /** When transaction is terminated unexpectedly. */ - public static final int TRANSACTION_TERMINTED = -3; - - /** When some error occurs on the device, possibly due to a bug. */ - public static final int CLIENT_ERROR = -4; - - /** When the transaction gets timed out. */ - public static final int TIME_OUT = -5; - - /** When the remote URI is not valid. */ - public static final int INVALID_REMOTE_URI = -6; - - /** When the peer is not reachable. */ - public static final int PEER_NOT_REACHABLE = -7; - - /** When invalid credentials are provided. */ - public static final int INVALID_CREDENTIALS = -8; - - /** The client is in a transaction and cannot initiate a new one. */ - public static final int IN_PROGRESS = -9; - - /** When data connection is lost. */ - public static final int DATA_CONNECTION_LOST = -10; - - /** Cross-domain authentication required. */ - public static final int CROSS_DOMAIN_AUTHENTICATION = -11; - - /** When the server is not reachable. */ - public static final int SERVER_UNREACHABLE = -12; - - public static String toString(int errorCode) { - switch (errorCode) { - case NO_ERROR: - return "NO_ERROR"; - case SOCKET_ERROR: - return "SOCKET_ERROR"; - case SERVER_ERROR: - return "SERVER_ERROR"; - case TRANSACTION_TERMINTED: - return "TRANSACTION_TERMINTED"; - case CLIENT_ERROR: - return "CLIENT_ERROR"; - case TIME_OUT: - return "TIME_OUT"; - case INVALID_REMOTE_URI: - return "INVALID_REMOTE_URI"; - case PEER_NOT_REACHABLE: - return "PEER_NOT_REACHABLE"; - case INVALID_CREDENTIALS: - return "INVALID_CREDENTIALS"; - case IN_PROGRESS: - return "IN_PROGRESS"; - case DATA_CONNECTION_LOST: - return "DATA_CONNECTION_LOST"; - case CROSS_DOMAIN_AUTHENTICATION: - return "CROSS_DOMAIN_AUTHENTICATION"; - case SERVER_UNREACHABLE: - return "SERVER_UNREACHABLE"; - default: - return "UNKNOWN"; - } - } - - private SipErrorCode() { - } -} diff --git a/voip/java/android/net/sip/SipException.java b/voip/java/android/net/sip/SipException.java deleted file mode 100644 index 0339395..0000000 --- a/voip/java/android/net/sip/SipException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -/** - * Indicates a general SIP-related exception. - */ -public class SipException extends Exception { - public SipException() { - } - - public SipException(String message) { - super(message); - } - - public SipException(String message, Throwable cause) { - // we want to eliminate the dependency on javax.sip.SipException - super(message, ((cause instanceof javax.sip.SipException) - && (cause.getCause() != null)) - ? cause.getCause() - : cause); - } -} diff --git a/voip/java/android/net/sip/SipManager.java b/voip/java/android/net/sip/SipManager.java deleted file mode 100644 index a94232a..0000000 --- a/voip/java/android/net/sip/SipManager.java +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.telephony.Rlog; - -import java.text.ParseException; - -/** - * Provides APIs for SIP tasks, such as initiating SIP connections, and provides access to related - * SIP services. This class is the starting point for any SIP actions. You can acquire an instance - * of it with {@link #newInstance newInstance()}.</p> - * <p>The APIs in this class allows you to:</p> - * <ul> - * <li>Create a {@link SipSession} to get ready for making calls or listen for incoming calls. See - * {@link #createSipSession createSipSession()} and {@link #getSessionFor getSessionFor()}.</li> - * <li>Initiate and receive generic SIP calls or audio-only SIP calls. Generic SIP calls may - * be video, audio, or other, and are initiated with {@link #open open()}. Audio-only SIP calls - * should be handled with a {@link SipAudioCall}, which you can acquire with {@link - * #makeAudioCall makeAudioCall()} and {@link #takeAudioCall takeAudioCall()}.</li> - * <li>Register and unregister with a SIP service provider, with - * {@link #register register()} and {@link #unregister unregister()}.</li> - * <li>Verify session connectivity, with {@link #isOpened isOpened()} and - * {@link #isRegistered isRegistered()}.</li> - * </ul> - * <p class="note"><strong>Note:</strong> Not all Android-powered devices support VOIP calls using - * SIP. You should always call {@link android.net.sip.SipManager#isVoipSupported - * isVoipSupported()} to verify that the device supports VOIP calling and {@link - * android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports - * the SIP APIs. Your application must also request the {@link - * android.Manifest.permission#INTERNET} and {@link android.Manifest.permission#USE_SIP} - * permissions.</p> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For more information about using SIP, read the - * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> - * developer guide.</p> - * </div> - */ -public class SipManager { - /** - * The result code to be sent back with the incoming call - * {@link PendingIntent}. - * @see #open(SipProfile, PendingIntent, SipRegistrationListener) - */ - public static final int INCOMING_CALL_RESULT_CODE = 101; - - /** - * Key to retrieve the call ID from an incoming call intent. - * @see #open(SipProfile, PendingIntent, SipRegistrationListener) - */ - public static final String EXTRA_CALL_ID = "android:sipCallID"; - - /** - * Key to retrieve the offered session description from an incoming call - * intent. - * @see #open(SipProfile, PendingIntent, SipRegistrationListener) - */ - public static final String EXTRA_OFFER_SD = "android:sipOfferSD"; - - /** - * Action to broadcast when SipService is up. - * Internal use only. - * @hide - */ - public static final String ACTION_SIP_SERVICE_UP = - "android.net.sip.SIP_SERVICE_UP"; - /** - * Action string for the incoming call intent for the Phone app. - * Internal use only. - * @hide - */ - public static final String ACTION_SIP_INCOMING_CALL = - "com.android.phone.SIP_INCOMING_CALL"; - /** - * Action string for the add-phone intent. - * Internal use only. - * @hide - */ - public static final String ACTION_SIP_ADD_PHONE = - "com.android.phone.SIP_ADD_PHONE"; - /** - * Action string for the remove-phone intent. - * Internal use only. - * @hide - */ - public static final String ACTION_SIP_REMOVE_PHONE = - "com.android.phone.SIP_REMOVE_PHONE"; - /** - * Part of the ACTION_SIP_ADD_PHONE and ACTION_SIP_REMOVE_PHONE intents. - * Internal use only. - * @hide - */ - public static final String EXTRA_LOCAL_URI = "android:localSipUri"; - - private static final String TAG = "SipManager"; - - private ISipService mSipService; - private Context mContext; - - /** - * Creates a manager instance. Returns null if SIP API is not supported. - * - * @param context application context for creating the manager object - * @return the manager instance or null if SIP API is not supported - */ - public static SipManager newInstance(Context context) { - return (isApiSupported(context) ? new SipManager(context) : null); - } - - /** - * Returns true if the SIP API is supported by the system. - */ - public static boolean isApiSupported(Context context) { - return context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_SIP); - } - - /** - * Returns true if the system supports SIP-based VOIP API. - */ - public static boolean isVoipSupported(Context context) { - return context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_SIP_VOIP) && isApiSupported(context); - } - - /** - * Returns true if SIP is only available on WIFI. - */ - public static boolean isSipWifiOnly(Context context) { - return context.getResources().getBoolean( - com.android.internal.R.bool.config_sip_wifi_only); - } - - private SipManager(Context context) { - mContext = context; - createSipService(); - } - - private void createSipService() { - IBinder b = ServiceManager.getService(Context.SIP_SERVICE); - mSipService = ISipService.Stub.asInterface(b); - } - - /** - * Opens the profile for making generic SIP calls. The caller may make subsequent calls - * through {@link #makeAudioCall}. If one also wants to receive calls on the - * profile, use - * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} - * instead. - * - * @param localProfile the SIP profile to make calls from - * @throws SipException if the profile contains incorrect settings or - * calling the SIP service results in an error - */ - public void open(SipProfile localProfile) throws SipException { - try { - mSipService.open(localProfile); - } catch (RemoteException e) { - throw new SipException("open()", e); - } - } - - /** - * Opens the profile for making calls and/or receiving generic SIP calls. The caller may - * make subsequent calls through {@link #makeAudioCall}. If the - * auto-registration option is enabled in the profile, the SIP service - * will register the profile to the corresponding SIP provider periodically - * in order to receive calls from the provider. When the SIP service - * receives a new call, it will send out an intent with the provided action - * string. The intent contains a call ID extra and an offer session - * description string extra. Use {@link #getCallId} and - * {@link #getOfferSessionDescription} to retrieve those extras. - * - * @param localProfile the SIP profile to receive incoming calls for - * @param incomingCallPendingIntent When an incoming call is received, the - * SIP service will call - * {@link PendingIntent#send(Context, int, Intent)} to send back the - * intent to the caller with {@link #INCOMING_CALL_RESULT_CODE} as the - * result code and the intent to fill in the call ID and session - * description information. It cannot be null. - * @param listener to listen to registration events; can be null - * @see #getCallId - * @see #getOfferSessionDescription - * @see #takeAudioCall - * @throws NullPointerException if {@code incomingCallPendingIntent} is null - * @throws SipException if the profile contains incorrect settings or - * calling the SIP service results in an error - * @see #isIncomingCallIntent - * @see #getCallId - * @see #getOfferSessionDescription - */ - public void open(SipProfile localProfile, - PendingIntent incomingCallPendingIntent, - SipRegistrationListener listener) throws SipException { - if (incomingCallPendingIntent == null) { - throw new NullPointerException( - "incomingCallPendingIntent cannot be null"); - } - try { - mSipService.open3(localProfile, incomingCallPendingIntent, - createRelay(listener, localProfile.getUriString())); - } catch (RemoteException e) { - throw new SipException("open()", e); - } - } - - /** - * Sets the listener to listen to registration events. No effect if the - * profile has not been opened to receive calls (see - * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)}). - * - * @param localProfileUri the URI of the profile - * @param listener to listen to registration events; can be null - * @throws SipException if calling the SIP service results in an error - */ - public void setRegistrationListener(String localProfileUri, - SipRegistrationListener listener) throws SipException { - try { - mSipService.setRegistrationListener( - localProfileUri, createRelay(listener, localProfileUri)); - } catch (RemoteException e) { - throw new SipException("setRegistrationListener()", e); - } - } - - /** - * Closes the specified profile to not make/receive calls. All the resources - * that were allocated to the profile are also released. - * - * @param localProfileUri the URI of the profile to close - * @throws SipException if calling the SIP service results in an error - */ - public void close(String localProfileUri) throws SipException { - try { - mSipService.close(localProfileUri); - } catch (RemoteException e) { - throw new SipException("close()", e); - } - } - - /** - * Checks if the specified profile is opened in the SIP service for - * making and/or receiving calls. - * - * @param localProfileUri the URI of the profile in question - * @return true if the profile is enabled to receive calls - * @throws SipException if calling the SIP service results in an error - */ - public boolean isOpened(String localProfileUri) throws SipException { - try { - return mSipService.isOpened(localProfileUri); - } catch (RemoteException e) { - throw new SipException("isOpened()", e); - } - } - - /** - * Checks if the SIP service has successfully registered the profile to the - * SIP provider (specified in the profile) for receiving calls. Returning - * true from this method also implies the profile is opened - * ({@link #isOpened}). - * - * @param localProfileUri the URI of the profile in question - * @return true if the profile is registered to the SIP provider; false if - * the profile has not been opened in the SIP service or the SIP - * service has not yet successfully registered the profile to the SIP - * provider - * @throws SipException if calling the SIP service results in an error - */ - public boolean isRegistered(String localProfileUri) throws SipException { - try { - return mSipService.isRegistered(localProfileUri); - } catch (RemoteException e) { - throw new SipException("isRegistered()", e); - } - } - - /** - * Creates a {@link SipAudioCall} to make a call. The attempt will be timed - * out if the call is not established within {@code timeout} seconds and - * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param localProfile the SIP profile to make the call from - * @param peerProfile the SIP profile to make the call to - * @param listener to listen to the call events from {@link SipAudioCall}; - * can be null - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @return a {@link SipAudioCall} object - * @throws SipException if calling the SIP service results in an error or - * VOIP API is not supported by the device - * @see SipAudioCall.Listener#onError - * @see #isVoipSupported - */ - public SipAudioCall makeAudioCall(SipProfile localProfile, - SipProfile peerProfile, SipAudioCall.Listener listener, int timeout) - throws SipException { - if (!isVoipSupported(mContext)) { - throw new SipException("VOIP API is not supported"); - } - SipAudioCall call = new SipAudioCall(mContext, localProfile); - call.setListener(listener); - SipSession s = createSipSession(localProfile, null); - call.makeCall(peerProfile, s, timeout); - return call; - } - - /** - * Creates a {@link SipAudioCall} to make an audio call. The attempt will be - * timed out if the call is not established within {@code timeout} seconds - * and - * {@link SipAudioCall.Listener#onError onError(SipAudioCall, SipErrorCode.TIME_OUT, String)} - * will be called. - * - * @param localProfileUri URI of the SIP profile to make the call from - * @param peerProfileUri URI of the SIP profile to make the call to - * @param listener to listen to the call events from {@link SipAudioCall}; - * can be null - * @param timeout the timeout value in seconds. Default value (defined by - * SIP protocol) is used if {@code timeout} is zero or negative. - * @return a {@link SipAudioCall} object - * @throws SipException if calling the SIP service results in an error or - * VOIP API is not supported by the device - * @see SipAudioCall.Listener#onError - * @see #isVoipSupported - */ - public SipAudioCall makeAudioCall(String localProfileUri, - String peerProfileUri, SipAudioCall.Listener listener, int timeout) - throws SipException { - if (!isVoipSupported(mContext)) { - throw new SipException("VOIP API is not supported"); - } - try { - return makeAudioCall( - new SipProfile.Builder(localProfileUri).build(), - new SipProfile.Builder(peerProfileUri).build(), listener, - timeout); - } catch (ParseException e) { - throw new SipException("build SipProfile", e); - } - } - - /** - * Creates a {@link SipAudioCall} to take an incoming call. Before the call - * is returned, the listener will receive a - * {@link SipAudioCall.Listener#onRinging} - * callback. - * - * @param incomingCallIntent the incoming call broadcast intent - * @param listener to listen to the call events from {@link SipAudioCall}; - * can be null - * @return a {@link SipAudioCall} object - * @throws SipException if calling the SIP service results in an error - */ - public SipAudioCall takeAudioCall(Intent incomingCallIntent, - SipAudioCall.Listener listener) throws SipException { - if (incomingCallIntent == null) { - throw new SipException("Cannot retrieve session with null intent"); - } - - String callId = getCallId(incomingCallIntent); - if (callId == null) { - throw new SipException("Call ID missing in incoming call intent"); - } - - String offerSd = getOfferSessionDescription(incomingCallIntent); - if (offerSd == null) { - throw new SipException("Session description missing in incoming " - + "call intent"); - } - - try { - ISipSession session = mSipService.getPendingSession(callId); - if (session == null) { - throw new SipException("No pending session for the call"); - } - SipAudioCall call = new SipAudioCall( - mContext, session.getLocalProfile()); - call.attachCall(new SipSession(session), offerSd); - call.setListener(listener); - return call; - } catch (Throwable t) { - throw new SipException("takeAudioCall()", t); - } - } - - /** - * Checks if the intent is an incoming call broadcast intent. - * - * @param intent the intent in question - * @return true if the intent is an incoming call broadcast intent - */ - public static boolean isIncomingCallIntent(Intent intent) { - if (intent == null) return false; - String callId = getCallId(intent); - String offerSd = getOfferSessionDescription(intent); - return ((callId != null) && (offerSd != null)); - } - - /** - * Gets the call ID from the specified incoming call broadcast intent. - * - * @param incomingCallIntent the incoming call broadcast intent - * @return the call ID or null if the intent does not contain it - */ - public static String getCallId(Intent incomingCallIntent) { - return incomingCallIntent.getStringExtra(EXTRA_CALL_ID); - } - - /** - * Gets the offer session description from the specified incoming call - * broadcast intent. - * - * @param incomingCallIntent the incoming call broadcast intent - * @return the offer session description or null if the intent does not - * have it - */ - public static String getOfferSessionDescription(Intent incomingCallIntent) { - return incomingCallIntent.getStringExtra(EXTRA_OFFER_SD); - } - - /** - * Creates an incoming call broadcast intent. - * - * @param callId the call ID of the incoming call - * @param sessionDescription the session description of the incoming call - * @return the incoming call intent - * @hide - */ - public static Intent createIncomingCallBroadcast(String callId, - String sessionDescription) { - Intent intent = new Intent(); - intent.putExtra(EXTRA_CALL_ID, callId); - intent.putExtra(EXTRA_OFFER_SD, sessionDescription); - return intent; - } - - /** - * Manually registers the profile to the corresponding SIP provider for - * receiving calls. - * {@link #open(SipProfile, PendingIntent, SipRegistrationListener)} is - * still needed to be called at least once in order for the SIP service to - * notify the caller with the {@link android.app.PendingIntent} when an incoming call is - * received. - * - * @param localProfile the SIP profile to register with - * @param expiryTime registration expiration time (in seconds) - * @param listener to listen to the registration events - * @throws SipException if calling the SIP service results in an error - */ - public void register(SipProfile localProfile, int expiryTime, - SipRegistrationListener listener) throws SipException { - try { - ISipSession session = mSipService.createSession(localProfile, - createRelay(listener, localProfile.getUriString())); - if (session == null) { - throw new SipException( - "SipService.createSession() returns null"); - } - session.register(expiryTime); - } catch (RemoteException e) { - throw new SipException("register()", e); - } - } - - /** - * Manually unregisters the profile from the corresponding SIP provider for - * stop receiving further calls. This may interference with the auto - * registration process in the SIP service if the auto-registration option - * in the profile is enabled. - * - * @param localProfile the SIP profile to register with - * @param listener to listen to the registration events - * @throws SipException if calling the SIP service results in an error - */ - public void unregister(SipProfile localProfile, - SipRegistrationListener listener) throws SipException { - try { - ISipSession session = mSipService.createSession(localProfile, - createRelay(listener, localProfile.getUriString())); - if (session == null) { - throw new SipException( - "SipService.createSession() returns null"); - } - session.unregister(); - } catch (RemoteException e) { - throw new SipException("unregister()", e); - } - } - - /** - * Gets the {@link SipSession} that handles the incoming call. For audio - * calls, consider to use {@link SipAudioCall} to handle the incoming call. - * See {@link #takeAudioCall}. Note that the method may be called only once - * for the same intent. For subsequent calls on the same intent, the method - * returns null. - * - * @param incomingCallIntent the incoming call broadcast intent - * @return the session object that handles the incoming call - */ - public SipSession getSessionFor(Intent incomingCallIntent) - throws SipException { - try { - String callId = getCallId(incomingCallIntent); - ISipSession s = mSipService.getPendingSession(callId); - return ((s == null) ? null : new SipSession(s)); - } catch (RemoteException e) { - throw new SipException("getSessionFor()", e); - } - } - - private static ISipSessionListener createRelay( - SipRegistrationListener listener, String uri) { - return ((listener == null) ? null : new ListenerRelay(listener, uri)); - } - - /** - * Creates a {@link SipSession} with the specified profile. Use other - * methods, if applicable, instead of interacting with {@link SipSession} - * directly. - * - * @param localProfile the SIP profile the session is associated with - * @param listener to listen to SIP session events - */ - public SipSession createSipSession(SipProfile localProfile, - SipSession.Listener listener) throws SipException { - try { - ISipSession s = mSipService.createSession(localProfile, null); - if (s == null) { - throw new SipException( - "Failed to create SipSession; network unavailable?"); - } - return new SipSession(s, listener); - } catch (RemoteException e) { - throw new SipException("createSipSession()", e); - } - } - - /** - * Gets the list of profiles hosted by the SIP service. The user information - * (username, password and display name) are crossed out. - * @hide - */ - public SipProfile[] getListOfProfiles() { - try { - return mSipService.getListOfProfiles(); - } catch (RemoteException e) { - return new SipProfile[0]; - } - } - - private static class ListenerRelay extends SipSessionAdapter { - private SipRegistrationListener mListener; - private String mUri; - - // listener must not be null - public ListenerRelay(SipRegistrationListener listener, String uri) { - mListener = listener; - mUri = uri; - } - - private String getUri(ISipSession session) { - try { - return ((session == null) - ? mUri - : session.getLocalProfile().getUriString()); - } catch (Throwable e) { - // SipService died? SIP stack died? - Rlog.e(TAG, "getUri(): ", e); - return null; - } - } - - @Override - public void onRegistering(ISipSession session) { - mListener.onRegistering(getUri(session)); - } - - @Override - public void onRegistrationDone(ISipSession session, int duration) { - long expiryTime = duration; - if (duration > 0) expiryTime += System.currentTimeMillis(); - mListener.onRegistrationDone(getUri(session), expiryTime); - } - - @Override - public void onRegistrationFailed(ISipSession session, int errorCode, - String message) { - mListener.onRegistrationFailed(getUri(session), errorCode, message); - } - - @Override - public void onRegistrationTimeout(ISipSession session) { - mListener.onRegistrationFailed(getUri(session), - SipErrorCode.TIME_OUT, "registration timed out"); - } - } -} diff --git a/voip/java/android/net/sip/SipProfile.aidl b/voip/java/android/net/sip/SipProfile.aidl deleted file mode 100644 index 3b6f68f..0000000 --- a/voip/java/android/net/sip/SipProfile.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2010, 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.sip; - -parcelable SipProfile; diff --git a/voip/java/android/net/sip/SipProfile.java b/voip/java/android/net/sip/SipProfile.java deleted file mode 100644 index 0ef754c..0000000 --- a/voip/java/android/net/sip/SipProfile.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import java.io.ObjectStreamException; -import java.io.Serializable; -import java.text.ParseException; -import javax.sip.InvalidArgumentException; -import javax.sip.ListeningPoint; -import javax.sip.PeerUnavailableException; -import javax.sip.SipFactory; -import javax.sip.address.Address; -import javax.sip.address.AddressFactory; -import javax.sip.address.SipURI; -import javax.sip.address.URI; - -/** - * Defines a SIP profile, including a SIP account, domain and server information. - * <p>You can create a {@link SipProfile} using {@link - * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link - * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p> - * - * <div class="special reference"> - * <h3>Developer Guides</h3> - * <p>For more information about using SIP, read the - * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a> - * developer guide.</p> - * </div> - */ -public class SipProfile implements Parcelable, Serializable, Cloneable { - private static final long serialVersionUID = 1L; - private static final int DEFAULT_PORT = 5060; - private static final String TCP = "TCP"; - private static final String UDP = "UDP"; - private Address mAddress; - private String mProxyAddress; - private String mPassword; - private String mDomain; - private String mProtocol = UDP; - private String mProfileName; - private String mAuthUserName; - private int mPort = DEFAULT_PORT; - private boolean mSendKeepAlive = false; - private boolean mAutoRegistration = true; - private transient int mCallingUid = 0; - - public static final Parcelable.Creator<SipProfile> CREATOR = - new Parcelable.Creator<SipProfile>() { - public SipProfile createFromParcel(Parcel in) { - return new SipProfile(in); - } - - public SipProfile[] newArray(int size) { - return new SipProfile[size]; - } - }; - - /** - * Helper class for creating a {@link SipProfile}. - */ - public static class Builder { - private AddressFactory mAddressFactory; - private SipProfile mProfile = new SipProfile(); - private SipURI mUri; - private String mDisplayName; - private String mProxyAddress; - - { - try { - mAddressFactory = - SipFactory.getInstance().createAddressFactory(); - } catch (PeerUnavailableException e) { - throw new RuntimeException(e); - } - } - - /** - * Creates a builder based on the given profile. - */ - public Builder(SipProfile profile) { - if (profile == null) throw new NullPointerException(); - try { - mProfile = (SipProfile) profile.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("should not occur", e); - } - mProfile.mAddress = null; - mUri = profile.getUri(); - mUri.setUserPassword(profile.getPassword()); - mDisplayName = profile.getDisplayName(); - mProxyAddress = profile.getProxyAddress(); - mProfile.mPort = profile.getPort(); - } - - /** - * Constructor. - * - * @param uriString the URI string as "sip:<user_name>@<domain>" - * @throws ParseException if the string is not a valid URI - */ - public Builder(String uriString) throws ParseException { - if (uriString == null) { - throw new NullPointerException("uriString cannot be null"); - } - URI uri = mAddressFactory.createURI(fix(uriString)); - if (uri instanceof SipURI) { - mUri = (SipURI) uri; - } else { - throw new ParseException(uriString + " is not a SIP URI", 0); - } - mProfile.mDomain = mUri.getHost(); - } - - /** - * Constructor. - * - * @param username username of the SIP account - * @param serverDomain the SIP server domain; if the network address - * is different from the domain, use {@link #setOutboundProxy} to - * set server address - * @throws ParseException if the parameters are not valid - */ - public Builder(String username, String serverDomain) - throws ParseException { - if ((username == null) || (serverDomain == null)) { - throw new NullPointerException( - "username and serverDomain cannot be null"); - } - mUri = mAddressFactory.createSipURI(username, serverDomain); - mProfile.mDomain = serverDomain; - } - - private String fix(String uriString) { - return (uriString.trim().toLowerCase().startsWith("sip:") - ? uriString - : "sip:" + uriString); - } - - /** - * Sets the username used for authentication. - * - * @param name authentication username of the profile - * @return this builder object - */ - public Builder setAuthUserName(String name) { - mProfile.mAuthUserName = name; - return this; - } - - /** - * Sets the name of the profile. This name is given by user. - * - * @param name name of the profile - * @return this builder object - */ - public Builder setProfileName(String name) { - mProfile.mProfileName = name; - return this; - } - - /** - * Sets the password of the SIP account - * - * @param password password of the SIP account - * @return this builder object - */ - public Builder setPassword(String password) { - mUri.setUserPassword(password); - return this; - } - - /** - * Sets the port number of the server. By default, it is 5060. - * - * @param port port number of the server - * @return this builder object - * @throws IllegalArgumentException if the port number is out of range - */ - public Builder setPort(int port) throws IllegalArgumentException { - if ((port > 65535) || (port < 1000)) { - throw new IllegalArgumentException("incorrect port arugment: " + port); - } - mProfile.mPort = port; - return this; - } - - /** - * Sets the protocol used to connect to the SIP server. Currently, - * only "UDP" and "TCP" are supported. - * - * @param protocol the protocol string - * @return this builder object - * @throws IllegalArgumentException if the protocol is not recognized - */ - public Builder setProtocol(String protocol) - throws IllegalArgumentException { - if (protocol == null) { - throw new NullPointerException("protocol cannot be null"); - } - protocol = protocol.toUpperCase(); - if (!protocol.equals(UDP) && !protocol.equals(TCP)) { - throw new IllegalArgumentException( - "unsupported protocol: " + protocol); - } - mProfile.mProtocol = protocol; - return this; - } - - /** - * Sets the outbound proxy of the SIP server. - * - * @param outboundProxy the network address of the outbound proxy - * @return this builder object - */ - public Builder setOutboundProxy(String outboundProxy) { - mProxyAddress = outboundProxy; - return this; - } - - /** - * Sets the display name of the user. - * - * @param displayName display name of the user - * @return this builder object - */ - public Builder setDisplayName(String displayName) { - mDisplayName = displayName; - return this; - } - - /** - * Sets the send keep-alive flag. - * - * @param flag true if sending keep-alive message is required, - * false otherwise - * @return this builder object - */ - public Builder setSendKeepAlive(boolean flag) { - mProfile.mSendKeepAlive = flag; - return this; - } - - - /** - * Sets the auto. registration flag. - * - * @param flag true if the profile will be registered automatically, - * false otherwise - * @return this builder object - */ - public Builder setAutoRegistration(boolean flag) { - mProfile.mAutoRegistration = flag; - return this; - } - - /** - * Builds and returns the SIP profile object. - * - * @return the profile object created - */ - public SipProfile build() { - // remove password from URI - mProfile.mPassword = mUri.getUserPassword(); - mUri.setUserPassword(null); - try { - if (!TextUtils.isEmpty(mProxyAddress)) { - SipURI uri = (SipURI) - mAddressFactory.createURI(fix(mProxyAddress)); - mProfile.mProxyAddress = uri.getHost(); - } else { - if (!mProfile.mProtocol.equals(UDP)) { - mUri.setTransportParam(mProfile.mProtocol); - } - if (mProfile.mPort != DEFAULT_PORT) { - mUri.setPort(mProfile.mPort); - } - } - mProfile.mAddress = mAddressFactory.createAddress( - mDisplayName, mUri); - } catch (InvalidArgumentException e) { - throw new RuntimeException(e); - } catch (ParseException e) { - // must not occur - throw new RuntimeException(e); - } - return mProfile; - } - } - - private SipProfile() { - } - - private SipProfile(Parcel in) { - mAddress = (Address) in.readSerializable(); - mProxyAddress = in.readString(); - mPassword = in.readString(); - mDomain = in.readString(); - mProtocol = in.readString(); - mProfileName = in.readString(); - mSendKeepAlive = (in.readInt() == 0) ? false : true; - mAutoRegistration = (in.readInt() == 0) ? false : true; - mCallingUid = in.readInt(); - mPort = in.readInt(); - mAuthUserName = in.readString(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeSerializable(mAddress); - out.writeString(mProxyAddress); - out.writeString(mPassword); - out.writeString(mDomain); - out.writeString(mProtocol); - out.writeString(mProfileName); - out.writeInt(mSendKeepAlive ? 1 : 0); - out.writeInt(mAutoRegistration ? 1 : 0); - out.writeInt(mCallingUid); - out.writeInt(mPort); - out.writeString(mAuthUserName); - } - - @Override - public int describeContents() { - return 0; - } - - /** - * Gets the SIP URI of this profile. - * - * @return the SIP URI of this profile - * @hide - */ - public SipURI getUri() { - return (SipURI) mAddress.getURI(); - } - - /** - * Gets the SIP URI string of this profile. - * - * @return the SIP URI string of this profile - */ - public String getUriString() { - // We need to return the sip uri domain instead of - // the SIP URI with transport, port information if - // the outbound proxy address exists. - if (!TextUtils.isEmpty(mProxyAddress)) { - return "sip:" + getUserName() + "@" + mDomain; - } - return getUri().toString(); - } - - /** - * Gets the SIP address of this profile. - * - * @return the SIP address of this profile - * @hide - */ - public Address getSipAddress() { - return mAddress; - } - - /** - * Gets the display name of the user. - * - * @return the display name of the user - */ - public String getDisplayName() { - return mAddress.getDisplayName(); - } - - /** - * Gets the username. - * - * @return the username - */ - public String getUserName() { - return getUri().getUser(); - } - - /** - * Gets the username for authentication. If it is null, then the username - * is used in authentication instead. - * - * @return the authentication username - * @see #getUserName - */ - public String getAuthUserName() { - return mAuthUserName; - } - - /** - * Gets the password. - * - * @return the password - */ - public String getPassword() { - return mPassword; - } - - /** - * Gets the SIP domain. - * - * @return the SIP domain - */ - public String getSipDomain() { - return mDomain; - } - - /** - * Gets the port number of the SIP server. - * - * @return the port number of the SIP server - */ - public int getPort() { - return mPort; - } - - /** - * Gets the protocol used to connect to the server. - * - * @return the protocol - */ - public String getProtocol() { - return mProtocol; - } - - /** - * Gets the network address of the server outbound proxy. - * - * @return the network address of the server outbound proxy - */ - public String getProxyAddress() { - return mProxyAddress; - } - - /** - * Gets the (user-defined) name of the profile. - * - * @return name of the profile - */ - public String getProfileName() { - return mProfileName; - } - - /** - * Gets the flag of 'Sending keep-alive'. - * - * @return the flag of sending SIP keep-alive messages. - */ - public boolean getSendKeepAlive() { - return mSendKeepAlive; - } - - /** - * Gets the flag of 'Auto Registration'. - * - * @return the flag of registering the profile automatically. - */ - public boolean getAutoRegistration() { - return mAutoRegistration; - } - - /** - * Sets the calling process's Uid in the sip service. - * @hide - */ - public void setCallingUid(int uid) { - mCallingUid = uid; - } - - /** - * Gets the calling process's Uid in the sip settings. - * @hide - */ - public int getCallingUid() { - return mCallingUid; - } - - private Object readResolve() throws ObjectStreamException { - // For compatibility. - if (mPort == 0) mPort = DEFAULT_PORT; - return this; - } -} diff --git a/voip/java/android/net/sip/SipRegistrationListener.java b/voip/java/android/net/sip/SipRegistrationListener.java deleted file mode 100644 index 9968cc7..0000000 --- a/voip/java/android/net/sip/SipRegistrationListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -/** - * Listener for SIP registration events. - */ -public interface SipRegistrationListener { - /** - * Called when a registration request is sent. - * - * @param localProfileUri the URI string of the SIP profile to register with - */ - void onRegistering(String localProfileUri); - - /** - * Called when the registration succeeded. - * - * @param localProfileUri the URI string of the SIP profile to register with - * @param expiryTime duration in seconds before the registration expires - */ - void onRegistrationDone(String localProfileUri, long expiryTime); - - /** - * Called when the registration failed. - * - * @param localProfileUri the URI string of the SIP profile to register with - * @param errorCode error code of this error - * @param errorMessage error message - * @see SipErrorCode - */ - void onRegistrationFailed(String localProfileUri, int errorCode, - String errorMessage); -} diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java deleted file mode 100644 index edbc66f..0000000 --- a/voip/java/android/net/sip/SipSession.java +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -import android.os.RemoteException; -import android.telephony.Rlog; - -/** - * Represents a SIP session that is associated with a SIP dialog or a standalone - * transaction not within a dialog. - * <p>You can get a {@link SipSession} from {@link SipManager} with {@link - * SipManager#createSipSession createSipSession()} (when initiating calls) or {@link - * SipManager#getSessionFor getSessionFor()} (when receiving calls).</p> - */ -public final class SipSession { - private static final String TAG = "SipSession"; - - /** - * Defines SIP session states, such as "registering", "outgoing call", and "in call". - */ - public static class State { - /** When session is ready to initiate a call or transaction. */ - public static final int READY_TO_CALL = 0; - - /** When the registration request is sent out. */ - public static final int REGISTERING = 1; - - /** When the unregistration request is sent out. */ - public static final int DEREGISTERING = 2; - - /** When an INVITE request is received. */ - public static final int INCOMING_CALL = 3; - - /** When an OK response is sent for the INVITE request received. */ - public static final int INCOMING_CALL_ANSWERING = 4; - - /** When an INVITE request is sent. */ - public static final int OUTGOING_CALL = 5; - - /** When a RINGING response is received for the INVITE request sent. */ - public static final int OUTGOING_CALL_RING_BACK = 6; - - /** When a CANCEL request is sent for the INVITE request sent. */ - public static final int OUTGOING_CALL_CANCELING = 7; - - /** When a call is established. */ - public static final int IN_CALL = 8; - - /** When an OPTIONS request is sent. */ - public static final int PINGING = 9; - - /** When ending a call. @hide */ - public static final int ENDING_CALL = 10; - - /** Not defined. */ - public static final int NOT_DEFINED = 101; - - /** - * Converts the state to string. - */ - public static String toString(int state) { - switch (state) { - case READY_TO_CALL: - return "READY_TO_CALL"; - case REGISTERING: - return "REGISTERING"; - case DEREGISTERING: - return "DEREGISTERING"; - case INCOMING_CALL: - return "INCOMING_CALL"; - case INCOMING_CALL_ANSWERING: - return "INCOMING_CALL_ANSWERING"; - case OUTGOING_CALL: - return "OUTGOING_CALL"; - case OUTGOING_CALL_RING_BACK: - return "OUTGOING_CALL_RING_BACK"; - case OUTGOING_CALL_CANCELING: - return "OUTGOING_CALL_CANCELING"; - case IN_CALL: - return "IN_CALL"; - case PINGING: - return "PINGING"; - default: - return "NOT_DEFINED"; - } - } - - private State() { - } - } - - /** - * Listener for events relating to a SIP session, such as when a session is being registered - * ("on registering") or a call is outgoing ("on calling"). - * <p>Many of these events are also received by {@link SipAudioCall.Listener}.</p> - */ - public static class Listener { - /** - * Called when an INVITE request is sent to initiate a new call. - * - * @param session the session object that carries out the transaction - */ - public void onCalling(SipSession session) { - } - - /** - * Called when an INVITE request is received. - * - * @param session the session object that carries out the transaction - * @param caller the SIP profile of the caller - * @param sessionDescription the caller's session description - */ - public void onRinging(SipSession session, SipProfile caller, - String sessionDescription) { - } - - /** - * Called when a RINGING response is received for the INVITE request sent - * - * @param session the session object that carries out the transaction - */ - public void onRingingBack(SipSession session) { - } - - /** - * Called when the session is established. - * - * @param session the session object that is associated with the dialog - * @param sessionDescription the peer's session description - */ - public void onCallEstablished(SipSession session, - String sessionDescription) { - } - - /** - * Called when the session is terminated. - * - * @param session the session object that is associated with the dialog - */ - public void onCallEnded(SipSession session) { - } - - /** - * Called when the peer is busy during session initialization. - * - * @param session the session object that carries out the transaction - */ - public void onCallBusy(SipSession session) { - } - - /** - * Called when the call is being transferred to a new one. - * - * @hide - * @param newSession the new session that the call will be transferred to - * @param sessionDescription the new peer's session description - */ - public void onCallTransferring(SipSession newSession, - String sessionDescription) { - } - - /** - * Called when an error occurs during session initialization and - * termination. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - public void onError(SipSession session, int errorCode, - String errorMessage) { - } - - /** - * Called when an error occurs during session modification negotiation. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - public void onCallChangeFailed(SipSession session, int errorCode, - String errorMessage) { - } - - /** - * Called when a registration request is sent. - * - * @param session the session object that carries out the transaction - */ - public void onRegistering(SipSession session) { - } - - /** - * Called when registration is successfully done. - * - * @param session the session object that carries out the transaction - * @param duration duration in second before the registration expires - */ - public void onRegistrationDone(SipSession session, int duration) { - } - - /** - * Called when the registration fails. - * - * @param session the session object that carries out the transaction - * @param errorCode error code defined in {@link SipErrorCode} - * @param errorMessage error message - */ - public void onRegistrationFailed(SipSession session, int errorCode, - String errorMessage) { - } - - /** - * Called when the registration gets timed out. - * - * @param session the session object that carries out the transaction - */ - public void onRegistrationTimeout(SipSession session) { - } - } - - private final ISipSession mSession; - private Listener mListener; - - SipSession(ISipSession realSession) { - mSession = realSession; - if (realSession != null) { - try { - realSession.setListener(createListener()); - } catch (RemoteException e) { - loge("SipSession.setListener:", e); - } - } - } - - SipSession(ISipSession realSession, Listener listener) { - this(realSession); - setListener(listener); - } - - /** - * Gets the IP address of the local host on which this SIP session runs. - * - * @return the IP address of the local host - */ - public String getLocalIp() { - try { - return mSession.getLocalIp(); - } catch (RemoteException e) { - loge("getLocalIp:", e); - return "127.0.0.1"; - } - } - - /** - * Gets the SIP profile that this session is associated with. - * - * @return the SIP profile that this session is associated with - */ - public SipProfile getLocalProfile() { - try { - return mSession.getLocalProfile(); - } catch (RemoteException e) { - loge("getLocalProfile:", e); - return null; - } - } - - /** - * Gets the SIP profile that this session is connected to. Only available - * when the session is associated with a SIP dialog. - * - * @return the SIP profile that this session is connected to - */ - public SipProfile getPeerProfile() { - try { - return mSession.getPeerProfile(); - } catch (RemoteException e) { - loge("getPeerProfile:", e); - return null; - } - } - - /** - * Gets the session state. The value returned must be one of the states in - * {@link State}. - * - * @return the session state - */ - public int getState() { - try { - return mSession.getState(); - } catch (RemoteException e) { - loge("getState:", e); - return State.NOT_DEFINED; - } - } - - /** - * Checks if the session is in a call. - * - * @return true if the session is in a call - */ - public boolean isInCall() { - try { - return mSession.isInCall(); - } catch (RemoteException e) { - loge("isInCall:", e); - return false; - } - } - - /** - * Gets the call ID of the session. - * - * @return the call ID - */ - public String getCallId() { - try { - return mSession.getCallId(); - } catch (RemoteException e) { - loge("getCallId:", e); - return null; - } - } - - - /** - * Sets the listener to listen to the session events. A {@code SipSession} - * can only hold one listener at a time. Subsequent calls to this method - * override the previous listener. - * - * @param listener to listen to the session events of this object - */ - public void setListener(Listener listener) { - mListener = listener; - } - - - /** - * Performs registration to the server specified by the associated local - * profile. The session listener is called back upon success or failure of - * registration. The method is only valid to call when the session state is - * in {@link State#READY_TO_CALL}. - * - * @param duration duration in second before the registration expires - * @see Listener - */ - public void register(int duration) { - try { - mSession.register(duration); - } catch (RemoteException e) { - loge("register:", e); - } - } - - /** - * Performs unregistration to the server specified by the associated local - * profile. Unregistration is technically the same as registration with zero - * expiration duration. The session listener is called back upon success or - * failure of unregistration. The method is only valid to call when the - * session state is in {@link State#READY_TO_CALL}. - * - * @see Listener - */ - public void unregister() { - try { - mSession.unregister(); - } catch (RemoteException e) { - loge("unregister:", e); - } - } - - /** - * Initiates a call to the specified profile. The session listener is called - * back upon defined session events. The method is only valid to call when - * the session state is in {@link State#READY_TO_CALL}. - * - * @param callee the SIP profile to make the call to - * @param sessionDescription the session description of this call - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds. Default value (defined - * by SIP protocol) is used if {@code timeout} is zero or negative. - * @see Listener - */ - public void makeCall(SipProfile callee, String sessionDescription, - int timeout) { - try { - mSession.makeCall(callee, sessionDescription, timeout); - } catch (RemoteException e) { - loge("makeCall:", e); - } - } - - /** - * Answers an incoming call with the specified session description. The - * method is only valid to call when the session state is in - * {@link State#INCOMING_CALL}. - * - * @param sessionDescription the session description to answer this call - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds. Default value (defined - * by SIP protocol) is used if {@code timeout} is zero or negative. - */ - public void answerCall(String sessionDescription, int timeout) { - try { - mSession.answerCall(sessionDescription, timeout); - } catch (RemoteException e) { - loge("answerCall:", e); - } - } - - /** - * Ends an established call, terminates an outgoing call or rejects an - * incoming call. The method is only valid to call when the session state is - * in {@link State#IN_CALL}, - * {@link State#INCOMING_CALL}, - * {@link State#OUTGOING_CALL} or - * {@link State#OUTGOING_CALL_RING_BACK}. - */ - public void endCall() { - try { - mSession.endCall(); - } catch (RemoteException e) { - loge("endCall:", e); - } - } - - /** - * Changes the session description during a call. The method is only valid - * to call when the session state is in {@link State#IN_CALL}. - * - * @param sessionDescription the new session description - * @param timeout the session will be timed out if the call is not - * established within {@code timeout} seconds. Default value (defined - * by SIP protocol) is used if {@code timeout} is zero or negative. - */ - public void changeCall(String sessionDescription, int timeout) { - try { - mSession.changeCall(sessionDescription, timeout); - } catch (RemoteException e) { - loge("changeCall:", e); - } - } - - ISipSession getRealSession() { - return mSession; - } - - private ISipSessionListener createListener() { - return new ISipSessionListener.Stub() { - @Override - public void onCalling(ISipSession session) { - if (mListener != null) { - mListener.onCalling(SipSession.this); - } - } - - @Override - public void onRinging(ISipSession session, SipProfile caller, - String sessionDescription) { - if (mListener != null) { - mListener.onRinging(SipSession.this, caller, - sessionDescription); - } - } - - @Override - public void onRingingBack(ISipSession session) { - if (mListener != null) { - mListener.onRingingBack(SipSession.this); - } - } - - @Override - public void onCallEstablished(ISipSession session, - String sessionDescription) { - if (mListener != null) { - mListener.onCallEstablished(SipSession.this, - sessionDescription); - } - } - - @Override - public void onCallEnded(ISipSession session) { - if (mListener != null) { - mListener.onCallEnded(SipSession.this); - } - } - - @Override - public void onCallBusy(ISipSession session) { - if (mListener != null) { - mListener.onCallBusy(SipSession.this); - } - } - - @Override - public void onCallTransferring(ISipSession session, - String sessionDescription) { - if (mListener != null) { - mListener.onCallTransferring( - new SipSession(session, SipSession.this.mListener), - sessionDescription); - - } - } - - @Override - public void onCallChangeFailed(ISipSession session, int errorCode, - String message) { - if (mListener != null) { - mListener.onCallChangeFailed(SipSession.this, errorCode, - message); - } - } - - @Override - public void onError(ISipSession session, int errorCode, String message) { - if (mListener != null) { - mListener.onError(SipSession.this, errorCode, message); - } - } - - @Override - public void onRegistering(ISipSession session) { - if (mListener != null) { - mListener.onRegistering(SipSession.this); - } - } - - @Override - public void onRegistrationDone(ISipSession session, int duration) { - if (mListener != null) { - mListener.onRegistrationDone(SipSession.this, duration); - } - } - - @Override - public void onRegistrationFailed(ISipSession session, int errorCode, - String message) { - if (mListener != null) { - mListener.onRegistrationFailed(SipSession.this, errorCode, - message); - } - } - - @Override - public void onRegistrationTimeout(ISipSession session) { - if (mListener != null) { - mListener.onRegistrationTimeout(SipSession.this); - } - } - }; - } - - private void loge(String s, Throwable t) { - Rlog.e(TAG, s, t); - } -} diff --git a/voip/java/android/net/sip/SipSessionAdapter.java b/voip/java/android/net/sip/SipSessionAdapter.java deleted file mode 100644 index f538983..0000000 --- a/voip/java/android/net/sip/SipSessionAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2010 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.sip; - -/** - * Adapter class for {@link ISipSessionListener}. Default implementation of all - * callback methods is no-op. - * @hide - */ -public class SipSessionAdapter extends ISipSessionListener.Stub { - public void onCalling(ISipSession session) { - } - - public void onRinging(ISipSession session, SipProfile caller, - String sessionDescription) { - } - - public void onRingingBack(ISipSession session) { - } - - public void onCallEstablished(ISipSession session, - String sessionDescription) { - } - - public void onCallEnded(ISipSession session) { - } - - public void onCallBusy(ISipSession session) { - } - - public void onCallTransferring(ISipSession session, - String sessionDescription) { - } - - public void onCallChangeFailed(ISipSession session, int errorCode, - String message) { - } - - public void onError(ISipSession session, int errorCode, String message) { - } - - public void onRegistering(ISipSession session) { - } - - public void onRegistrationDone(ISipSession session, int duration) { - } - - public void onRegistrationFailed(ISipSession session, int errorCode, - String message) { - } - - public void onRegistrationTimeout(ISipSession session) { - } -} diff --git a/voip/java/android/net/sip/package.html b/voip/java/android/net/sip/package.html deleted file mode 100644 index 3c4cc23..0000000 --- a/voip/java/android/net/sip/package.html +++ /dev/null @@ -1,45 +0,0 @@ -<HTML> -<BODY> -<p>Provides access to Session Initiation Protocol (SIP) functionality, such as -making and answering VOIP calls using SIP.</p> - -<p>For more information, see the -<a href="{@docRoot}guide/topics/connectivity/sip.html">Session Initiation Protocol</a> -developer guide.</p> -{@more} - -<p>To get started, you need to get an instance of the {@link android.net.sip.SipManager} by -calling {@link android.net.sip.SipManager#newInstance newInstance()}.</p> - -<p>With the {@link android.net.sip.SipManager}, you can initiate SIP audio calls with {@link -android.net.sip.SipManager#makeAudioCall makeAudioCall()} and {@link -android.net.sip.SipManager#takeAudioCall takeAudioCall()}. Both methods require -a {@link android.net.sip.SipAudioCall.Listener} that receives callbacks when the state of the -call changes, such as when the call is ringing, established, or ended.</p> - -<p>Both {@link android.net.sip.SipManager#makeAudioCall makeAudioCall()} also requires two -{@link android.net.sip.SipProfile} objects, representing the local device and the peer -device. You can create a {@link android.net.sip.SipProfile} using the {@link -android.net.sip.SipProfile.Builder} subclass.</p> - -<p>Once you have a {@link android.net.sip.SipAudioCall}, you can perform SIP audio call actions with -the instance, such as make a call, answer a call, mute a call, turn on speaker mode, send DTMF -tones, and more.</p> - -<p>If you want to create generic SIP connections (such as for video calls or other), you can -create a SIP connection from the {@link android.net.sip.SipManager}, using {@link -android.net.sip.SipManager#open open()}. If you only want to create audio SIP calls, though, you -should use the {@link android.net.sip.SipAudioCall} class, as described above.</p> - -<p class="note"><strong>Note:</strong> -Not all Android-powered devices support VOIP functionality with SIP. Before performing any SIP -activity, you should call {@link android.net.sip.SipManager#isVoipSupported isVoipSupported()} -to verify that the device supports VOIP calling and {@link -android.net.sip.SipManager#isApiSupported isApiSupported()} to verify that the device supports the -SIP APIs. -Your application must also request the {@link android.Manifest.permission#INTERNET} and {@link -android.Manifest.permission#USE_SIP} permissions in order to use the SIP APIs. -</p> - -</BODY> -</HTML>
\ No newline at end of file |