ISipService: add new open(), open3(), getListOfProfiles()
replacing old openToReceiveCalls(), and broadcast intents when profiles are
added and removed during those calls.
Change-Id: I507327e7a043de3aa3256b88d74199a83a7b1438
diff --git a/demo/com/android/sip/demo/SipCallSetup.java b/demo/com/android/sip/demo/SipCallSetup.java
index 0585b61..a4058ab 100644
--- a/demo/com/android/sip/demo/SipCallSetup.java
+++ b/demo/com/android/sip/demo/SipCallSetup.java
@@ -244,8 +244,8 @@
mSipManager.register(myself.mProfile, 3600,
createRegistrationListener());
} else {
- mSipManager.openToReceiveCalls(myself.mProfile,
- INCOMING_CALL_ACTION, createRegistrationListener());
+ mSipManager.open(myself.mProfile, INCOMING_CALL_ACTION,
+ createRegistrationListener());
}
} catch (Exception e) {
Log.e(TAG, "register()", e);
diff --git a/settings/com/android/settings/sip/SipAutoRegistration.java b/settings/com/android/settings/sip/SipAutoRegistration.java
index 4230150..39c7b83 100644
--- a/settings/com/android/settings/sip/SipAutoRegistration.java
+++ b/settings/com/android/settings/sip/SipAutoRegistration.java
@@ -60,7 +60,7 @@
+ SipSettings.PROFILES_DIR);
for (SipProfile profile : sipProfileList) {
try {
- sipManager.openToReceiveCalls(profile,
+ sipManager.open(profile,
SipSettings.INCOMING_CALL_ACTION, null);
} catch (SipException e) {
Log.e(TAG, "failed" + profile.getProfileName(), e);
diff --git a/settings/com/android/settings/sip/SipSettings.java b/settings/com/android/settings/sip/SipSettings.java
index 679c55f..b7c26ba 100644
--- a/settings/com/android/settings/sip/SipSettings.java
+++ b/settings/com/android/settings/sip/SipSettings.java
@@ -298,7 +298,7 @@
private void registerProfile(SipProfile profile) {
if (profile != null) {
try {
- mSipManager.openToReceiveCalls(profile, INCOMING_CALL_ACTION,
+ mSipManager.open(profile, INCOMING_CALL_ACTION,
createRegistrationListener());
} catch (Exception e) {
Log.e(TAG, "register failed", e);
diff --git a/src/android/net/sip/ISipService.aidl b/src/android/net/sip/ISipService.aidl
index 99af890..6c68213 100644
--- a/src/android/net/sip/ISipService.aidl
+++ b/src/android/net/sip/ISipService.aidl
@@ -24,7 +24,8 @@
* {@hide}
*/
interface ISipService {
- void openToReceiveCalls(in SipProfile localProfile,
+ void open(in SipProfile localProfile);
+ void open3(in SipProfile localProfile,
String incomingCallBroadcastAction,
in ISipSessionListener listener);
void close(in String localProfileUri);
@@ -36,4 +37,6 @@
ISipSession createSession(in SipProfile localProfile,
in ISipSessionListener listener);
ISipSession getPendingSession(String callId);
+
+ SipProfile[] getListOfProfiles();
}
diff --git a/src/android/net/sip/SipManager.java b/src/android/net/sip/SipManager.java
index 2971c0f..6d48e65 100644
--- a/src/android/net/sip/SipManager.java
+++ b/src/android/net/sip/SipManager.java
@@ -23,6 +23,7 @@
import android.os.Looper;
import android.os.RemoteException;
+import java.text.ParseException;
import javax.sip.SipException;
/**
@@ -31,10 +32,10 @@
* <ul>
* <li>register a {@link SipProfile} to have the background SIP service listen
* to incoming calls and broadcast them with registered command string. See
- * {@link #openToReceiveCalls(SipProfile, String, SipRegistrationListener)},
- * {@link #close(String)}, {@link #isOpened(String)} and
- * {@link isRegistered(String)}. It also facilitates handling of the
- * incoming call broadcast intent. See
+ * {@link #open(SipProfile, String, SipRegistrationListener)},
+ * {@link #open(SipProfile)}, {@link #close(String)},
+ * {@link #isOpened(String)} and {@link isRegistered(String)}. It also
+ * facilitates handling of the incoming call broadcast intent. See
* {@link #isIncomingCallIntent(Intent)}, {@link #getCallId(Intent)},
* {@link #getOfferSessionDescription(Intent)} and
* {@link #takeAudioCall(Context, Intent, SipAudioCall.Listener)}.</li>
@@ -50,6 +51,18 @@
* @hide
*/
public class SipManager {
+ /** @hide */
+ public static final String SIP_INCOMING_CALL_ACTION =
+ "com.android.phone.SIP_INCOMING_CALL";
+ /** @hide */
+ public static final String SIP_ADD_PHONE_ACTION =
+ "com.android.phone.SIP_ADD_PHONE";
+ /** @hide */
+ public static final String SIP_REMOVE_PHONE_ACTION =
+ "com.android.phone.SIP_REMOVE_PHONE";
+ /** @hide */
+ public static final String LOCAL_URI_KEY = "LOCAL SIPURI";
+
private static final String CALL_ID_KEY = "CallID";
private static final String OFFER_SD_KEY = "OfferSD";
@@ -94,9 +107,34 @@
}
/**
- * Enables to receive incoming calls for the specified SIP profile. When
- * enabled, the SIP service will register the profile to the corresponding
- * server periodically in order to receive calls from the server.
+ * Opens the profile for making calls and/or receiving calls. Subsequent
+ * SIP calls can be made through the default phone UI. The caller may also
+ * make subsequent calls through
+ * {@link #makeAudioCall(Context, String, String, SipAudioCall.Listener)}.
+ * If the receiving-call option is enabled in the profile, the SIP service
+ * will register the profile to the corresponding server periodically in
+ * order to receive calls from the server.
+ *
+ * @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 calls. Subsequent
+ * SIP calls can be made through the default phone UI. The caller may also
+ * make subsequent calls through
+ * {@link #makeAudioCall(Context, String, String, SipAudioCall.Listener)}.
+ * If the receiving-call option is enabled in the profile, the SIP service
+ * will register the profile to the corresponding server periodically in
+ * order to receive calls from the server.
*
* @param localProfile the SIP profile to receive incoming calls for
* @param incomingCallBroadcastAction the action to be broadcast when an
@@ -105,21 +143,22 @@
* @throws SipException if the profile contains incorrect settings or
* calling the SIP service results in an error
*/
- public void openToReceiveCalls(SipProfile localProfile,
+ public void open(SipProfile localProfile,
String incomingCallBroadcastAction,
SipRegistrationListener listener) throws SipException {
try {
- mSipService.openToReceiveCalls(localProfile,
- incomingCallBroadcastAction, createRelay(listener));
+ mSipService.open3(localProfile, incomingCallBroadcastAction,
+ createRelay(listener));
} catch (RemoteException e) {
- throw new SipException("openToReceiveCalls()", 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 #openToReceiveCalls(SipProfile, String, SipRegistrationListener)}).
+ * (see {@link #open(SipProfile, String, SipRegistrationListener)} and
+ * {@link #open(SipProfile)}).
*
* @param localProfileUri the URI of the profile
* @param listener to listen to registration events; can be null
@@ -136,7 +175,7 @@
}
/**
- * Closes to not receive calls for the specified profile. All the resources
+ * 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
@@ -202,6 +241,30 @@
}
/**
+ * Creates a {@link SipAudioCall} to make a call. To use this method, one
+ * must call {@link #open(SipProfile)} first.
+ *
+ * @param context context to create a {@link SipAudioCall} object
+ * @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
+ * @return a {@link SipAudioCall} object
+ * @throws SipException if calling the SIP service results in an error
+ */
+ public SipAudioCall makeAudioCall(Context context, String localProfileUri,
+ String peerProfileUri, SipAudioCall.Listener listener)
+ throws SipException {
+ try {
+ return makeAudioCall(context,
+ new SipProfile.Builder(localProfileUri).build(),
+ new SipProfile.Builder(peerProfileUri).build(), listener);
+ } catch (ParseException e) {
+ throw new SipException("build SipProfile", e);
+ }
+ }
+
+ /**
* The method calls {@code takeAudioCall(context, incomingCallIntent,
* listener, true}.
*
@@ -312,9 +375,9 @@
/**
* Registers the profile to the corresponding server for receiving calls.
- * {@link #openToReceiveCalls(SipProfile, String, SipRegistrationListener)}
- * is still needed to be called at least once in order for the SIP service
- * to broadcast an intent when an incoming call is received.
+ * {@link #open(SipProfile, String, SipRegistrationListener)} is still
+ * needed to be called at least once in order for the SIP service to
+ * broadcast an intent when an incoming call is received.
*
* @param localProfile the SIP profile to register with
* @param expiryTime registration expiration time (in second)
@@ -333,13 +396,10 @@
}
/**
- * Registers the profile to the corresponding server for receiving calls.
- * {@link #openToReceiveCalls(SipProfile, String, SipRegistrationListener)}
- * is still needed to be called at least once in order for the SIP service
- * to broadcast an intent when an incoming call is received.
+ * Unregisters the profile from the corresponding server for not receiving
+ * further calls.
*
* @param localProfile the SIP profile to register with
- * @param expiryTime registration expiration time (in second)
* @param listener to listen to the registration events
* @throws SipException if calling the SIP service results in an error
*/
@@ -396,6 +456,19 @@
}
}
+ /**
+ * 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 null;
+ }
+ }
+
private static class ListenerRelay extends SipSessionAdapter {
private SipRegistrationListener mListener;
diff --git a/src/com/android/sip/SipServiceImpl.java b/src/com/android/sip/SipServiceImpl.java
index 18c5af7..c878da5 100644
--- a/src/com/android/sip/SipServiceImpl.java
+++ b/src/com/android/sip/SipServiceImpl.java
@@ -33,6 +33,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
@@ -80,16 +81,69 @@
mTimer = new WakeupTimer(context);
}
- public synchronized void openToReceiveCalls(SipProfile localProfile,
- String incomingCallBroadcastAction,
- ISipSessionListener listener) {
- FLog.d(TAG, "openToReceiveCalls: " + localProfile.getUriString() + ": "
+ public synchronized SipProfile[] getListOfProfiles() {
+ SipProfile[] profiles = new SipProfile[mSipGroups.size()];
+ int i = 0;
+ for (SipSessionGroupExt group : mSipGroups.values()) {
+ profiles[i++] = duplicate(group.getLocalProfile());
+ }
+ return profiles;
+ }
+
+ private SipProfile duplicate(SipProfile p) {
+ try {
+ return new SipProfile.Builder(p.getUserName(), p.getSipDomain())
+ .setProfileName(p.getProfileName())
+ .setPassword("*")
+ .setPort(p.getPort())
+ .setProtocol(p.getProtocol())
+ .setOutboundProxy(p.getProxyAddress())
+ .setSendKeepAlive(p.getSendKeepAlive())
+ .setAutoRegistration(p.getAutoRegistration())
+ .setDisplayName("*")
+ .build();
+ } catch (Exception e) {
+ Log.wtf(TAG, "duplicate()", e);
+ return null;
+ }
+ }
+
+ public void open(SipProfile localProfile) {
+ if (localProfile.getAutoRegistration()) {
+ openToReceiveCalls(localProfile);
+ } else {
+ openToMakeCalls(localProfile);
+ }
+ }
+
+ private void openToMakeCalls(SipProfile localProfile) {
+ try {
+ createGroup(localProfile);
+ } catch (SipException e) {
+ FLog.e(TAG, "openToMakeCalls()", e);
+ // TODO: how to send the exception back
+ }
+ }
+
+ private void openToReceiveCalls(SipProfile localProfile) {
+ open3(localProfile, SipManager.SIP_INCOMING_CALL_ACTION, null);
+ }
+
+ public synchronized void open3(SipProfile localProfile,
+ String incomingCallBroadcastAction, ISipSessionListener listener) {
+ if (TextUtils.isEmpty(incomingCallBroadcastAction)) {
+ throw new RuntimeException(
+ "empty broadcast action for incoming call");
+ }
+ FLog.d(TAG, "open3: " + localProfile.getUriString() + ": "
+ incomingCallBroadcastAction + ": " + listener);
try {
SipSessionGroupExt group = createGroup(localProfile,
incomingCallBroadcastAction, listener);
- group.openToReceiveCalls();
- if (isWifiOn()) grabWifiLock();
+ if (localProfile.getAutoRegistration()) {
+ group.openToReceiveCalls();
+ if (isWifiOn()) grabWifiLock();
+ }
} catch (SipException e) {
FLog.e(TAG, "openToReceiveCalls()", e);
// TODO: how to send the exception back
@@ -99,6 +153,7 @@
public synchronized void close(String localProfileUri) {
SipSessionGroupExt group = mSipGroups.remove(localProfileUri);
if (group != null) {
+ notifyProfileRemoved(group.getLocalProfile());
group.closeToNotReceiveCalls();
if (isWifiOn() && !anyOpened()) releaseWifiLock();
}
@@ -156,6 +211,7 @@
if (group == null) {
group = new SipSessionGroupExt(localProfile, null, null);
mSipGroups.put(key, group);
+ notifyProfileAdded(localProfile);
}
return group;
}
@@ -173,10 +229,25 @@
group = new SipSessionGroupExt(localProfile,
incomingCallBroadcastAction, listener);
mSipGroups.put(key, group);
+ notifyProfileAdded(localProfile);
}
return group;
}
+ private void notifyProfileAdded(SipProfile localProfile) {
+ Log.d(TAG, "notify: profile added: " + localProfile);
+ Intent intent = new Intent(SipManager.SIP_ADD_PHONE_ACTION);
+ intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ mContext.sendBroadcast(intent);
+ }
+
+ private void notifyProfileRemoved(SipProfile localProfile) {
+ Log.d(TAG, "notify: profile removed: " + localProfile);
+ Intent intent = new Intent(SipManager.SIP_REMOVE_PHONE_ACTION);
+ intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ mContext.sendBroadcast(intent);
+ }
+
private boolean anyOpened() {
for (SipSessionGroupExt group : mSipGroups.values()) {
if (group.isOpened()) return true;
@@ -275,6 +346,10 @@
mAutoRegistration.setListener(listener);
}
+ public SipProfile getLocalProfile() {
+ return mSipGroup.getLocalProfile();
+ }
+
// network connectivity is tricky because network can be disconnected
// at any instant so need to deal with exceptions carefully even when
// you think you are connected