summaryrefslogtreecommitdiffstats
path: root/voip/java/android/net/sip
diff options
context:
space:
mode:
authorWink Saville <wink@google.com>2013-01-28 15:27:47 -0800
committerWink Saville <wink@google.com>2013-01-28 15:27:47 -0800
commitcbb2a2a207796a68eff26be001af2797594d3b3c (patch)
treeae7d166136064ba408035fa741bb944441fddb47 /voip/java/android/net/sip
parent29e4aa7abe6b0c62f31fb23b8572cd5b91f08f5c (diff)
downloadframeworks_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.aidl43
-rw-r--r--voip/java/android/net/sip/ISipSession.aidl148
-rw-r--r--voip/java/android/net/sip/ISipSessionListener.aidl133
-rw-r--r--voip/java/android/net/sip/SimpleSessionDescription.java613
-rw-r--r--voip/java/android/net/sip/SipAudioCall.java1143
-rw-r--r--voip/java/android/net/sip/SipErrorCode.java101
-rw-r--r--voip/java/android/net/sip/SipException.java37
-rw-r--r--voip/java/android/net/sip/SipManager.java622
-rw-r--r--voip/java/android/net/sip/SipProfile.aidl19
-rw-r--r--voip/java/android/net/sip/SipProfile.java502
-rw-r--r--voip/java/android/net/sip/SipRegistrationListener.java48
-rw-r--r--voip/java/android/net/sip/SipSession.java574
-rw-r--r--voip/java/android/net/sip/SipSessionAdapter.java68
-rw-r--r--voip/java/android/net/sip/package.html45
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