Methods Summary |
---|
private synchronized void | addPendingSession(android.net.sip.ISipSession session)
try {
cleanUpPendingSessions();
mPendingSessions.put(session.getCallId(), session);
if (DBG) log("#pending sess=" + mPendingSessions.size());
} catch (RemoteException e) {
// should not happen with a local call
loge("addPendingSession()", e);
}
|
private synchronized boolean | callingSelf(com.android.server.sip.SipService$SipSessionGroupExt ringingGroup, SipSessionGroup.SipSessionImpl ringingSession)
String callId = ringingSession.getCallId();
for (SipSessionGroupExt group : mSipGroups.values()) {
if ((group != ringingGroup) && group.containsSession(callId)) {
if (DBG) log("call self: "
+ ringingSession.getLocalProfile().getUriString()
+ " -> " + group.getLocalProfile().getUriString());
return true;
}
}
return false;
|
private void | cleanUpPendingSessions()
Map.Entry<String, ISipSession>[] entries =
mPendingSessions.entrySet().toArray(
new Map.Entry[mPendingSessions.size()]);
for (Map.Entry<String, ISipSession> entry : entries) {
if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) {
mPendingSessions.remove(entry.getKey());
}
}
|
public synchronized void | close(java.lang.String localProfileUri)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
SipSessionGroupExt group = mSipGroups.get(localProfileUri);
if (group == null) return;
if (!isCallerCreatorOrRadio(group)) {
if (DBG) log("only creator or radio can close this profile");
return;
}
group = mSipGroups.remove(localProfileUri);
notifyProfileRemoved(group.getLocalProfile());
group.close();
updateWakeLocks();
|
private com.android.server.sip.SipService$SipSessionGroupExt | createGroup(android.net.sip.SipProfile localProfile)
String key = localProfile.getUriString();
SipSessionGroupExt group = mSipGroups.get(key);
if (group == null) {
group = new SipSessionGroupExt(localProfile, null, null);
mSipGroups.put(key, group);
notifyProfileAdded(localProfile);
} else if (!isCallerCreator(group)) {
throw new SipException("only creator can access the profile");
}
return group;
|
private com.android.server.sip.SipService$SipSessionGroupExt | createGroup(android.net.sip.SipProfile localProfile, android.app.PendingIntent incomingCallPendingIntent, android.net.sip.ISipSessionListener listener)
String key = localProfile.getUriString();
SipSessionGroupExt group = mSipGroups.get(key);
if (group != null) {
if (!isCallerCreator(group)) {
throw new SipException("only creator can access the profile");
}
group.setIncomingCallPendingIntent(incomingCallPendingIntent);
group.setListener(listener);
} else {
group = new SipSessionGroupExt(localProfile,
incomingCallPendingIntent, listener);
mSipGroups.put(key, group);
notifyProfileAdded(localProfile);
}
return group;
|
private static android.os.Looper | createLooper()
HandlerThread thread = new HandlerThread("SipService.Executor");
thread.start();
return thread.getLooper();
|
public synchronized android.net.sip.ISipSession | createSession(android.net.sip.SipProfile localProfile, android.net.sip.ISipSessionListener listener)
if (DBG) log("createSession: profile" + localProfile);
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
localProfile.setCallingUid(Binder.getCallingUid());
if (mNetworkType == -1) {
if (DBG) log("createSession: mNetworkType==-1 ret=null");
return null;
}
try {
SipSessionGroupExt group = createGroup(localProfile);
return group.createSession(listener);
} catch (SipException e) {
if (DBG) loge("createSession;", e);
return null;
}
|
private java.lang.String | determineLocalIp()
try {
DatagramSocket s = new DatagramSocket();
s.connect(InetAddress.getByName("192.168.1.1"), 80);
return s.getLocalAddress().getHostAddress();
} catch (IOException e) {
if (DBG) loge("determineLocalIp()", e);
// dont do anything; there should be a connectivity change going
return null;
}
|
private int | getKeepAliveInterval()
return (mKeepAliveInterval < 0)
? mLastGoodKeepAliveInterval
: mKeepAliveInterval;
|
public synchronized android.net.sip.SipProfile[] | getListOfProfiles()
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
boolean isCallerRadio = isCallerRadio();
ArrayList<SipProfile> profiles = new ArrayList<SipProfile>();
for (SipSessionGroupExt group : mSipGroups.values()) {
if (isCallerRadio || isCallerCreator(group)) {
profiles.add(group.getLocalProfile());
}
}
return profiles.toArray(new SipProfile[profiles.size()]);
|
public synchronized android.net.sip.ISipSession | getPendingSession(java.lang.String callId)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
if (callId == null) return null;
return mPendingSessions.get(callId);
|
private boolean | isBehindNAT(java.lang.String address)
try {
// TODO: How is isBehindNAT used and why these constanst address:
// 10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x
byte[] d = InetAddress.getByName(address).getAddress();
if ((d[0] == 10) ||
(((0x000000FF & d[0]) == 172) &&
((0x000000F0 & d[1]) == 16)) ||
(((0x000000FF & d[0]) == 192) &&
((0x000000FF & d[1]) == 168))) {
return true;
}
} catch (UnknownHostException e) {
loge("isBehindAT()" + address, e);
}
return false;
|
private boolean | isCallerCreator(com.android.server.sip.SipService$SipSessionGroupExt group)
SipProfile profile = group.getLocalProfile();
return (profile.getCallingUid() == Binder.getCallingUid());
|
private boolean | isCallerCreatorOrRadio(com.android.server.sip.SipService$SipSessionGroupExt group)
return (isCallerRadio() || isCallerCreator(group));
|
private boolean | isCallerRadio()
return (Binder.getCallingUid() == Process.PHONE_UID);
|
public synchronized boolean | isOpened(java.lang.String localProfileUri)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
SipSessionGroupExt group = mSipGroups.get(localProfileUri);
if (group == null) return false;
if (isCallerCreatorOrRadio(group)) {
return true;
} else {
if (DBG) log("only creator or radio can query on the profile");
return false;
}
|
public synchronized boolean | isRegistered(java.lang.String localProfileUri)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
SipSessionGroupExt group = mSipGroups.get(localProfileUri);
if (group == null) return false;
if (isCallerCreatorOrRadio(group)) {
return group.isRegistered();
} else {
if (DBG) log("only creator or radio can query on the profile");
return false;
}
|
private void | log(java.lang.String s)
Rlog.d(TAG, s);
|
private void | loge(java.lang.String s, java.lang.Throwable e)
Rlog.e(TAG, s, e);
|
private void | notifyProfileAdded(android.net.sip.SipProfile localProfile)
if (DBG) log("notify: profile added: " + localProfile);
Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE);
intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
if (mSipGroups.size() == 1) {
registerReceivers();
}
|
private void | notifyProfileRemoved(android.net.sip.SipProfile localProfile)
if (DBG) log("notify: profile removed: " + localProfile);
Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
if (mSipGroups.size() == 0) {
unregisterReceivers();
}
|
private synchronized void | onConnectivityChanged(android.net.NetworkInfo info)
// We only care about the default network, and getActiveNetworkInfo()
// is the only way to distinguish them. However, as broadcasts are
// delivered asynchronously, we might miss DISCONNECTED events from
// getActiveNetworkInfo(), which is critical to our SIP stack. To
// solve this, if it is a DISCONNECTED event to our current network,
// respect it. Otherwise get a new one from getActiveNetworkInfo().
if (info == null || info.isConnected() || info.getType() != mNetworkType) {
ConnectivityManager cm = (ConnectivityManager)
mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
info = cm.getActiveNetworkInfo();
}
// Some devices limit SIP on Wi-Fi. In this case, if we are not on
// Wi-Fi, treat it as a DISCONNECTED event.
int networkType = (info != null && info.isConnected()) ? info.getType() : -1;
if (mSipOnWifiOnly && networkType != ConnectivityManager.TYPE_WIFI) {
networkType = -1;
}
// Ignore the event if the current active network is not changed.
if (mNetworkType == networkType) {
// TODO: Maybe we need to send seq/generation number
return;
}
if (DBG) {
log("onConnectivityChanged: " + mNetworkType +
" -> " + networkType);
}
try {
if (mNetworkType != -1) {
mLocalIp = null;
stopPortMappingMeasurement();
for (SipSessionGroupExt group : mSipGroups.values()) {
group.onConnectivityChanged(false);
}
}
mNetworkType = networkType;
if (mNetworkType != -1) {
mLocalIp = determineLocalIp();
mKeepAliveInterval = -1;
mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL;
for (SipSessionGroupExt group : mSipGroups.values()) {
group.onConnectivityChanged(true);
}
}
updateWakeLocks();
} catch (SipException e) {
loge("onConnectivityChanged()", e);
}
|
private synchronized void | onKeepAliveIntervalChanged()
for (SipSessionGroupExt group : mSipGroups.values()) {
group.onKeepAliveIntervalChanged();
}
|
public synchronized void | open(android.net.sip.SipProfile localProfile)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
localProfile.setCallingUid(Binder.getCallingUid());
try {
createGroup(localProfile);
} catch (SipException e) {
loge("openToMakeCalls()", e);
// TODO: how to send the exception back
}
|
public synchronized void | open3(android.net.sip.SipProfile localProfile, android.app.PendingIntent incomingCallPendingIntent, android.net.sip.ISipSessionListener listener)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
localProfile.setCallingUid(Binder.getCallingUid());
if (incomingCallPendingIntent == null) {
if (DBG) log("open3: incomingCallPendingIntent cannot be null; "
+ "the profile is not opened");
return;
}
if (DBG) log("open3: " + localProfile.getUriString() + ": "
+ incomingCallPendingIntent + ": " + listener);
try {
SipSessionGroupExt group = createGroup(localProfile,
incomingCallPendingIntent, listener);
if (localProfile.getAutoRegistration()) {
group.openToReceiveCalls();
updateWakeLocks();
}
} catch (SipException e) {
loge("open3:", e);
// TODO: how to send the exception back
}
|
private void | registerReceivers()
mContext.registerReceiver(mConnectivityReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
if (DBG) log("registerReceivers:");
|
private void | restartPortMappingLifetimeMeasurement(android.net.sip.SipProfile localProfile, int maxInterval)
stopPortMappingMeasurement();
mKeepAliveInterval = -1;
startPortMappingLifetimeMeasurement(localProfile, maxInterval);
|
public synchronized void | setRegistrationListener(java.lang.String localProfileUri, android.net.sip.ISipSessionListener listener)
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.USE_SIP, null);
SipSessionGroupExt group = mSipGroups.get(localProfileUri);
if (group == null) return;
if (isCallerCreator(group)) {
group.setListener(listener);
} else {
if (DBG) log("only creator can set listener on the profile");
}
|
private static void | slog(java.lang.String s)
Rlog.d(TAG, s);
|
public static void | start(android.content.Context context)Starts the SIP service. Do nothing if the SIP API is not supported on the
device.
if (SipManager.isApiSupported(context)) {
ServiceManager.addService("sip", new SipService(context));
context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP));
if (DBG) slog("start:");
}
|
private void | startPortMappingLifetimeMeasurement(android.net.sip.SipProfile localProfile)
startPortMappingLifetimeMeasurement(localProfile,
DEFAULT_MAX_KEEPALIVE_INTERVAL);
|
private void | startPortMappingLifetimeMeasurement(android.net.sip.SipProfile localProfile, int maxInterval)
if ((mSipKeepAliveProcessCallback == null)
&& (mKeepAliveInterval == -1)
&& isBehindNAT(mLocalIp)) {
if (DBG) log("startPortMappingLifetimeMeasurement: profile="
+ localProfile.getUriString());
int minInterval = mLastGoodKeepAliveInterval;
if (minInterval >= maxInterval) {
// If mLastGoodKeepAliveInterval also does not work, reset it
// to the default min
minInterval = mLastGoodKeepAliveInterval
= DEFAULT_KEEPALIVE_INTERVAL;
log(" reset min interval to " + minInterval);
}
mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback(
localProfile, minInterval, maxInterval);
mSipKeepAliveProcessCallback.start();
}
|
private void | stopPortMappingMeasurement()
if (mSipKeepAliveProcessCallback != null) {
mSipKeepAliveProcessCallback.stop();
mSipKeepAliveProcessCallback = null;
}
|
private void | unregisterReceivers()
mContext.unregisterReceiver(mConnectivityReceiver);
if (DBG) log("unregisterReceivers:");
// Reset variables maintained by ConnectivityReceiver.
mWifiLock.release();
mNetworkType = -1;
|
private void | updateWakeLocks()
for (SipSessionGroupExt group : mSipGroups.values()) {
if (group.isOpenedToReceiveCalls()) {
// Also grab the WifiLock when we are disconnected, so the
// system will keep trying to reconnect. It will be released
// when the system eventually connects to something else.
if (mNetworkType == ConnectivityManager.TYPE_WIFI || mNetworkType == -1) {
mWifiLock.acquire();
} else {
mWifiLock.release();
}
return;
}
}
mWifiLock.release();
mMyWakeLock.reset(); // in case there's a leak
|