am bd57eeaf
: SipService: add wake lock for multiple components.
Merge commit 'bd57eeafe034cf850225db403700b5dc5db5ebcc' into gingerbread-plus-aosp * commit 'bd57eeafe034cf850225db403700b5dc5db5ebcc': SipService: add wake lock for multiple components.
This commit is contained in:
@ -39,6 +39,7 @@ import android.os.Handler;
|
|||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.PowerManager;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
@ -54,6 +55,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
@ -93,6 +95,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
|
|
||||||
private ConnectivityReceiver mConnectivityReceiver;
|
private ConnectivityReceiver mConnectivityReceiver;
|
||||||
private boolean mWifiEnabled;
|
private boolean mWifiEnabled;
|
||||||
|
private MyWakeLock mMyWakeLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the SIP service. Do nothing if the SIP API is not supported on the
|
* Starts the SIP service. Do nothing if the SIP API is not supported on the
|
||||||
@ -114,6 +117,8 @@ public final class SipService extends ISipService.Stub {
|
|||||||
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||||
context.registerReceiver(mWifiStateReceiver,
|
context.registerReceiver(mWifiStateReceiver,
|
||||||
new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
|
new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
|
||||||
|
mMyWakeLock = new MyWakeLock((PowerManager)
|
||||||
|
context.getSystemService(Context.POWER_SERVICE));
|
||||||
|
|
||||||
mTimer = new WakeupTimer(context);
|
mTimer = new WakeupTimer(context);
|
||||||
mWifiOnly = SipManager.isSipWifiOnly(context);
|
mWifiOnly = SipManager.isSipWifiOnly(context);
|
||||||
@ -225,7 +230,11 @@ public final class SipService extends ISipService.Stub {
|
|||||||
group = mSipGroups.remove(localProfileUri);
|
group = mSipGroups.remove(localProfileUri);
|
||||||
notifyProfileRemoved(group.getLocalProfile());
|
notifyProfileRemoved(group.getLocalProfile());
|
||||||
group.close();
|
group.close();
|
||||||
if (!anyOpened()) releaseWifiLock();
|
|
||||||
|
if (!anyOpened()) {
|
||||||
|
releaseWifiLock();
|
||||||
|
mMyWakeLock.reset(); // in case there's leak
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean isOpened(String localProfileUri) {
|
public synchronized boolean isOpened(String localProfileUri) {
|
||||||
@ -405,6 +414,8 @@ public final class SipService extends ISipService.Stub {
|
|||||||
for (SipSessionGroupExt group : mSipGroups.values()) {
|
for (SipSessionGroupExt group : mSipGroups.values()) {
|
||||||
group.onConnectivityChanged(true);
|
group.onConnectivityChanged(true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
mMyWakeLock.reset(); // in case there's a leak
|
||||||
}
|
}
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
Log.e(TAG, "onConnectivityChanged()", e);
|
Log.e(TAG, "onConnectivityChanged()", e);
|
||||||
@ -581,7 +592,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// KeepAliveProcess is controlled by AutoRegistrationProcess.
|
// KeepAliveProcess is controlled by AutoRegistrationProcess.
|
||||||
// All methods will be invoked in sync with SipService.this except realRun()
|
// All methods will be invoked in sync with SipService.this.
|
||||||
private class KeepAliveProcess implements Runnable {
|
private class KeepAliveProcess implements Runnable {
|
||||||
private static final String TAG = "\\KEEPALIVE/";
|
private static final String TAG = "\\KEEPALIVE/";
|
||||||
private static final int INTERVAL = 10;
|
private static final int INTERVAL = 10;
|
||||||
@ -600,43 +611,33 @@ public final class SipService extends ISipService.Stub {
|
|||||||
|
|
||||||
// timeout handler
|
// timeout handler
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!mRunning) return;
|
|
||||||
final SipSessionGroup.SipSessionImpl session = mSession;
|
|
||||||
|
|
||||||
// delegate to mExecutor
|
|
||||||
getExecutor().addTask(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
realRun(session);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// real timeout handler
|
|
||||||
private void realRun(SipSessionGroup.SipSessionImpl session) {
|
|
||||||
synchronized (SipService.this) {
|
synchronized (SipService.this) {
|
||||||
if (notCurrentSession(session)) return;
|
if (!mRunning) return;
|
||||||
|
|
||||||
session = session.duplicate();
|
if (DEBUGV) Log.v(TAG, "~~~ keepalive: "
|
||||||
if (DEBUGV) Log.v(TAG, "~~~ keepalive");
|
+ mSession.getLocalProfile().getUriString());
|
||||||
mTimer.cancel(this);
|
SipSessionGroup.SipSessionImpl session = mSession.duplicate();
|
||||||
session.sendKeepAlive();
|
try {
|
||||||
if (session.isReRegisterRequired()) {
|
session.sendKeepAlive();
|
||||||
mSession.register(EXPIRY_TIME);
|
if (session.isReRegisterRequired()) {
|
||||||
} else {
|
// Acquire wake lock for the registration process. The
|
||||||
mTimer.set(INTERVAL * 1000, this);
|
// lock will be released when registration is complete.
|
||||||
|
mMyWakeLock.acquire(mSession);
|
||||||
|
mSession.register(EXPIRY_TIME);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.w(TAG, "keepalive error: " + t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
|
if (DEBUGV && (mSession != null)) Log.v(TAG, "stop keepalive:"
|
||||||
|
+ mSession.getLocalProfile().getUriString());
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
mSession = null;
|
mSession = null;
|
||||||
mTimer.cancel(this);
|
mTimer.cancel(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean notCurrentSession(ISipSession session) {
|
|
||||||
return (session != mSession) || !mRunning;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AutoRegistrationProcess extends SipSessionAdapter
|
private class AutoRegistrationProcess extends SipSessionAdapter
|
||||||
@ -667,6 +668,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
// start unregistration to clear up old registration at server
|
// start unregistration to clear up old registration at server
|
||||||
// TODO: when rfc5626 is deployed, use reg-id and sip.instance
|
// TODO: when rfc5626 is deployed, use reg-id and sip.instance
|
||||||
// in registration to avoid adding duplicate entries to server
|
// in registration to avoid adding duplicate entries to server
|
||||||
|
mMyWakeLock.acquire(mSession);
|
||||||
mSession.unregister();
|
mSession.unregister();
|
||||||
if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for "
|
if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for "
|
||||||
+ mSession.getLocalProfile().getUriString());
|
+ mSession.getLocalProfile().getUriString());
|
||||||
@ -676,8 +678,11 @@ public final class SipService extends ISipService.Stub {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
if (!mRunning) return;
|
if (!mRunning) return;
|
||||||
mRunning = false;
|
mRunning = false;
|
||||||
mSession.setListener(null);
|
mMyWakeLock.release(mSession);
|
||||||
if (mConnected && mRegistered) mSession.unregister();
|
if (mSession != null) {
|
||||||
|
mSession.setListener(null);
|
||||||
|
if (mConnected && mRegistered) mSession.unregister();
|
||||||
|
}
|
||||||
|
|
||||||
mTimer.cancel(this);
|
mTimer.cancel(this);
|
||||||
if (mKeepAliveProcess != null) {
|
if (mKeepAliveProcess != null) {
|
||||||
@ -734,29 +739,18 @@ public final class SipService extends ISipService.Stub {
|
|||||||
return mRegistered;
|
return mRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeout handler
|
// timeout handler: re-register
|
||||||
public void run() {
|
public void run() {
|
||||||
synchronized (SipService.this) {
|
synchronized (SipService.this) {
|
||||||
if (!mRunning) return;
|
if (!mRunning) return;
|
||||||
final SipSessionGroup.SipSessionImpl session = mSession;
|
|
||||||
|
|
||||||
// delegate to mExecutor
|
|
||||||
getExecutor().addTask(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
realRun(session);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// real timeout handler
|
|
||||||
private void realRun(SipSessionGroup.SipSessionImpl session) {
|
|
||||||
synchronized (SipService.this) {
|
|
||||||
if (notCurrentSession(session)) return;
|
|
||||||
mErrorCode = SipErrorCode.NO_ERROR;
|
mErrorCode = SipErrorCode.NO_ERROR;
|
||||||
mErrorMessage = null;
|
mErrorMessage = null;
|
||||||
if (DEBUG) Log.d(TAG, "~~~ registering");
|
if (DEBUG) Log.d(TAG, "~~~ registering");
|
||||||
if (mConnected) session.register(EXPIRY_TIME);
|
if (mConnected) {
|
||||||
|
mMyWakeLock.acquire(mSession);
|
||||||
|
mSession.register(EXPIRY_TIME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -806,6 +800,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
private boolean notCurrentSession(ISipSession session) {
|
private boolean notCurrentSession(ISipSession session) {
|
||||||
if (session != mSession) {
|
if (session != mSession) {
|
||||||
((SipSessionGroup.SipSessionImpl) session).setListener(null);
|
((SipSessionGroup.SipSessionImpl) session).setListener(null);
|
||||||
|
mMyWakeLock.release(session);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return !mRunning;
|
return !mRunning;
|
||||||
@ -842,6 +837,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
mKeepAliveProcess.start();
|
mKeepAliveProcess.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mMyWakeLock.release(session);
|
||||||
} else {
|
} else {
|
||||||
mRegistered = false;
|
mRegistered = false;
|
||||||
mExpiryTime = -1L;
|
mExpiryTime = -1L;
|
||||||
@ -872,6 +868,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
mErrorCode = errorCode;
|
mErrorCode = errorCode;
|
||||||
mErrorMessage = message;
|
mErrorMessage = message;
|
||||||
mProxy.onRegistrationFailed(session, errorCode, message);
|
mProxy.onRegistrationFailed(session, errorCode, message);
|
||||||
|
mMyWakeLock.release(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,6 +881,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
mErrorCode = SipErrorCode.TIME_OUT;
|
mErrorCode = SipErrorCode.TIME_OUT;
|
||||||
mProxy.onRegistrationTimeout(session);
|
mProxy.onRegistrationTimeout(session);
|
||||||
restartLater();
|
restartLater();
|
||||||
|
mMyWakeLock.release(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -902,7 +900,16 @@ public final class SipService extends ISipService.Stub {
|
|||||||
private MyTimerTask mTask;
|
private MyTimerTask mTask;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
|
// Run the handler in MyExecutor to be protected by wake lock
|
||||||
|
getExecutor().execute(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
onReceiveInternal(context, intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onReceiveInternal(Context context, Intent intent) {
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
||||||
Bundle b = intent.getExtras();
|
Bundle b = intent.getExtras();
|
||||||
@ -970,11 +977,13 @@ public final class SipService extends ISipService.Stub {
|
|||||||
if (mTask != null) mTask.cancel();
|
if (mTask != null) mTask.cancel();
|
||||||
mTask = new MyTimerTask(type, connected);
|
mTask = new MyTimerTask(type, connected);
|
||||||
mTimer.schedule(mTask, 2 * 1000L);
|
mTimer.schedule(mTask, 2 * 1000L);
|
||||||
// TODO: hold wakup lock so that we can finish change before
|
// hold wakup lock so that we can finish changes before the
|
||||||
// the device goes to sleep
|
// device goes to sleep
|
||||||
|
mMyWakeLock.acquire(mTask);
|
||||||
} else {
|
} else {
|
||||||
if ((mTask != null) && mTask.mNetworkType.equals(type)) {
|
if ((mTask != null) && mTask.mNetworkType.equals(type)) {
|
||||||
mTask.cancel();
|
mTask.cancel();
|
||||||
|
mMyWakeLock.release(mTask);
|
||||||
}
|
}
|
||||||
onConnectivityChanged(type, false);
|
onConnectivityChanged(type, false);
|
||||||
}
|
}
|
||||||
@ -994,7 +1003,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// delegate to mExecutor
|
// delegate to mExecutor
|
||||||
getExecutor().addTask(new Runnable() {
|
getExecutor().execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
realRun();
|
realRun();
|
||||||
}
|
}
|
||||||
@ -1012,6 +1021,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType
|
if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType
|
||||||
+ (mConnected ? " CONNECTED" : "DISCONNECTED"));
|
+ (mConnected ? " CONNECTED" : "DISCONNECTED"));
|
||||||
onConnectivityChanged(mNetworkType, mConnected);
|
onConnectivityChanged(mNetworkType, mConnected);
|
||||||
|
mMyWakeLock.release(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1019,7 +1029,6 @@ public final class SipService extends ISipService.Stub {
|
|||||||
|
|
||||||
// TODO: clean up pending SipSession(s) periodically
|
// TODO: clean up pending SipSession(s) periodically
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timer that can schedule events to occur even when the device is in sleep.
|
* Timer that can schedule events to occur even when the device is in sleep.
|
||||||
* Only used internally in this package.
|
* Only used internally in this package.
|
||||||
@ -1209,7 +1218,8 @@ public final class SipService extends ISipService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
// This callback is already protected by AlarmManager's wake lock.
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (getAction().equals(action)
|
if (getAction().equals(action)
|
||||||
&& intent.getExtras().containsKey(TRIGGER_TIME)) {
|
&& intent.getExtras().containsKey(TRIGGER_TIME)) {
|
||||||
@ -1236,7 +1246,7 @@ public final class SipService extends ISipService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void execute(long triggerTime) {
|
private synchronized void execute(long triggerTime) {
|
||||||
if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
|
if (DEBUG_TIMER) Log.d(TAG, "time's up, triggerTime = "
|
||||||
+ showTime(triggerTime) + ": " + mEventQueue.size());
|
+ showTime(triggerTime) + ": " + mEventQueue.size());
|
||||||
if (stopped() || mEventQueue.isEmpty()) return;
|
if (stopped() || mEventQueue.isEmpty()) return;
|
||||||
@ -1248,9 +1258,8 @@ public final class SipService extends ISipService.Stub {
|
|||||||
event.mLastTriggerTime = event.mTriggerTime;
|
event.mLastTriggerTime = event.mTriggerTime;
|
||||||
event.mTriggerTime += event.mPeriod;
|
event.mTriggerTime += event.mPeriod;
|
||||||
|
|
||||||
// run the callback in a new thread to prevent deadlock
|
// run the callback in the handler thread to prevent deadlock
|
||||||
new Thread(event.mCallback, "SipServiceTimerCallbackThread")
|
getExecutor().execute(event.mCallback);
|
||||||
.start();
|
|
||||||
}
|
}
|
||||||
if (DEBUG_TIMER) {
|
if (DEBUG_TIMER) {
|
||||||
Log.d(TAG, "after timeout execution");
|
Log.d(TAG, "after timeout execution");
|
||||||
@ -1314,29 +1323,78 @@ public final class SipService extends ISipService.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single-threaded executor
|
private static Looper createLooper() {
|
||||||
private static class MyExecutor extends Handler {
|
HandlerThread thread = new HandlerThread("SipService.Executor");
|
||||||
|
thread.start();
|
||||||
|
return thread.getLooper();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes immediate tasks in a single thread.
|
||||||
|
// Hold/release wake lock for running tasks
|
||||||
|
private class MyExecutor extends Handler {
|
||||||
MyExecutor() {
|
MyExecutor() {
|
||||||
super(createLooper());
|
super(createLooper());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Looper createLooper() {
|
void execute(Runnable task) {
|
||||||
HandlerThread thread = new HandlerThread("SipService");
|
mMyWakeLock.acquire(task);
|
||||||
thread.start();
|
|
||||||
return thread.getLooper();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTask(Runnable task) {
|
|
||||||
Message.obtain(this, 0/* don't care */, task).sendToTarget();
|
Message.obtain(this, 0/* don't care */, task).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (msg.obj instanceof Runnable) {
|
if (msg.obj instanceof Runnable) {
|
||||||
((Runnable) msg.obj).run();
|
executeInternal((Runnable) msg.obj);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "can't handle msg: " + msg);
|
Log.w(TAG, "can't handle msg: " + msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void executeInternal(Runnable task) {
|
||||||
|
try {
|
||||||
|
task.run();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.e(TAG, "run task: " + task, t);
|
||||||
|
} finally {
|
||||||
|
mMyWakeLock.release(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MyWakeLock {
|
||||||
|
private PowerManager mPowerManager;
|
||||||
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
private HashSet<Object> mHolders = new HashSet<Object>();
|
||||||
|
|
||||||
|
MyWakeLock(PowerManager powerManager) {
|
||||||
|
mPowerManager = powerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void reset() {
|
||||||
|
mHolders.clear();
|
||||||
|
release(null);
|
||||||
|
if (DEBUGV) Log.v(TAG, "~~~ hard reset wakelock");
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void acquire(Object holder) {
|
||||||
|
mHolders.add(holder);
|
||||||
|
if (mWakeLock == null) {
|
||||||
|
mWakeLock = mPowerManager.newWakeLock(
|
||||||
|
PowerManager.PARTIAL_WAKE_LOCK, "SipWakeLock");
|
||||||
|
}
|
||||||
|
if (!mWakeLock.isHeld()) mWakeLock.acquire();
|
||||||
|
if (DEBUGV) Log.v(TAG, "acquire wakelock: holder count="
|
||||||
|
+ mHolders.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void release(Object holder) {
|
||||||
|
mHolders.remove(holder);
|
||||||
|
if ((mWakeLock != null) && mHolders.isEmpty()
|
||||||
|
&& mWakeLock.isHeld()) {
|
||||||
|
mWakeLock.release();
|
||||||
|
}
|
||||||
|
if (DEBUGV) Log.v(TAG, "release wakelock: holder count="
|
||||||
|
+ mHolders.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,8 +547,14 @@ class SipSessionGroup implements SipListener {
|
|||||||
mState = SipSession.State.PINGING;
|
mState = SipSession.State.PINGING;
|
||||||
try {
|
try {
|
||||||
processCommand(new OptionsCommand());
|
processCommand(new OptionsCommand());
|
||||||
while (SipSession.State.PINGING == mState) {
|
for (int i = 0; i < 15; i++) {
|
||||||
Thread.sleep(1000);
|
if (SipSession.State.PINGING != mState) break;
|
||||||
|
Thread.sleep(200);
|
||||||
|
}
|
||||||
|
if (SipSession.State.PINGING == mState) {
|
||||||
|
// FIXME: what to do if server doesn't respond
|
||||||
|
reset();
|
||||||
|
if (DEBUG) Log.w(TAG, "no response from ping");
|
||||||
}
|
}
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
Log.e(TAG, "sendKeepAlive failed", e);
|
Log.e(TAG, "sendKeepAlive failed", e);
|
||||||
|
Reference in New Issue
Block a user