19c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/* 29c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Copyright (C) 2010, The Android Open Source Project 39c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 49c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License"); 59c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * you may not use this file except in compliance with the License. 69c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * You may obtain a copy of the License at 79c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 89c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * http://www.apache.org/licenses/LICENSE-2.0 99c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Unless required by applicable law or agreed to in writing, software 119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS, 129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * See the License for the specific language governing permissions and 149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * limitations under the License. 159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpackage com.android.server.sip; 189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.app.PendingIntent; 209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.BroadcastReceiver; 219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.Context; 229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.Intent; 239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.IntentFilter; 249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.ConnectivityManager; 259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.NetworkInfo; 269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipService; 279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipSession; 289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipSessionListener; 299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipErrorCode; 309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipManager; 319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipProfile; 329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipSession; 339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipSessionAdapter; 349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.wifi.WifiManager; 359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Binder; 369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Bundle; 379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Handler; 389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.HandlerThread; 399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Looper; 409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Message; 41257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyanimport android.os.PowerManager; 42a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyanimport android.os.Process; 439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.RemoteException; 449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.ServiceManager; 459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.SystemClock; 469329db04f13480ccdff013dcc00cdb96f12a921cWink Savilleimport android.telephony.Rlog; 479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.io.IOException; 499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.DatagramSocket; 509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.InetAddress; 519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.UnknownHostException; 52a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyanimport java.util.ArrayList; 539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.HashMap; 549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Map; 554cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyanimport java.util.concurrent.Executor; 569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException; 579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/** 599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * @hide 609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic final class SipService extends ISipService.Stub { 62acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan static final String TAG = "SipService"; 639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville static final boolean DBG = true; 649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int EXPIRY_TIME = 3600; 659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int SHORT_EXPIRY_TIME = 10; 669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int MIN_EXPIRY_TIME = 60; 678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds 68cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private static final int DEFAULT_MAX_KEEPALIVE_INTERVAL = 120; // in seconds 699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Context mContext; 719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mLocalIp; 727d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private int mNetworkType = -1; 734cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer; 749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private WifiManager.WifiLock mWifiLock; 7579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private boolean mSipOnWifiOnly; 76987b505b1c190ff0e5a05d2cc20c9b08d2b99b18Hung-ying Tyan 779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipKeepAliveProcessCallback mSipKeepAliveProcessCallback; 789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 794cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private MyExecutor mExecutor = new MyExecutor(); 809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // SipProfile URI --> group 829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, SipSessionGroupExt> mSipGroups = 839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, SipSessionGroupExt>(); 849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // session ID --> session 869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, ISipSession> mPendingSessions = 879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, ISipSession>(); 889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private ConnectivityReceiver mConnectivityReceiver; 90acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan private SipWakeLock mMyWakeLock; 91469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mKeepAliveInterval; 92cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan /** 959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Starts the SIP service. Do nothing if the SIP API is not supported on the 969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * device. 979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public static void start(Context context) { 999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (SipManager.isApiSupported(context)) { 1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ServiceManager.addService("sip", new SipService(context)); 10122523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP)); 1029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) slog("start:"); 1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipService(Context context) { 1079329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("SipService: started!"); 1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext = context; 1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnectivityReceiver = new ConnectivityReceiver(); 11079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 11179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock = ((WifiManager) 11279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh context.getSystemService(Context.WIFI_SERVICE)) 11379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 11479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.setReferenceCounted(false); 11579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mSipOnWifiOnly = SipManager.isSipWifiOnly(context); 11679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 117acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock = new SipWakeLock((PowerManager) 118257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan context.getSystemService(Context.POWER_SERVICE)); 1199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1204cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mTimer = new SipWakeupTimer(context, mExecutor); 121dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 122dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 1239329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized SipProfile[] getListOfProfiles() { 1258127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1268127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 127a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan boolean isCallerRadio = isCallerRadio(); 128a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan ArrayList<SipProfile> profiles = new ArrayList<SipProfile>(); 1299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 130a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerRadio || isCallerCreator(group)) { 131a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan profiles.add(group.getLocalProfile()); 132a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 1339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 134a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return profiles.toArray(new SipProfile[profiles.size()]); 1359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1379329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 138dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan public synchronized void open(SipProfile localProfile) { 1398127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1408127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 1429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan createGroup(localProfile); 1449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("openToMakeCalls()", e); 1469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 1519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void open3(SipProfile localProfile, 152845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 153845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) { 1548127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1558127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 157845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 1589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("open3: incomingCallPendingIntent cannot be null; " 159845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + "the profile is not opened"); 160a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 1619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("open3: " + localProfile.getUriString() + ": " 163845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + incomingCallPendingIntent + ": " + listener); 1649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile, 166845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localProfile.getAutoRegistration()) { 1689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.openToReceiveCalls(); 1697d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 1709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1729329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("open3:", e); 1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 177a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreator(SipSessionGroupExt group) { 178a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipProfile profile = group.getLocalProfile(); 179a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (profile.getCallingUid() == Binder.getCallingUid()); 180a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 181a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 182a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreatorOrRadio(SipSessionGroupExt group) { 183a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (isCallerRadio() || isCallerCreator(group)); 184a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 185a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 186a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerRadio() { 187a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (Binder.getCallingUid() == Process.PHONE_UID); 188a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 189a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 1909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 1919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void close(String localProfileUri) { 1928127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1938127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 194a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 195a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 196a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreatorOrRadio(group)) { 1979329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can close this profile"); 198a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 1999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 200a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 201a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group = mSipGroups.remove(localProfileUri); 202a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan notifyProfileRemoved(group.getLocalProfile()); 203a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.close(); 204257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 2057d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 2069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2089329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isOpened(String localProfileUri) { 2108127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2118127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 213a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 214a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 215617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return true; 216a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2179329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 218a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 219a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isRegistered(String localProfileUri) { 2248127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2258127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 227a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 228a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 229a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return group.isRegistered(); 230a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2319329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 232a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 233a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void setRegistrationListener(String localProfileUri, 2389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2398127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2408127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 242a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 243a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreator(group)) { 244a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.setListener(listener); 245a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2469329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator can set listener on the profile"); 247a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession createSession(SipProfile localProfile, 2529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: profile" + localProfile); 2548127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2558127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 2579329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mNetworkType == -1) { 2589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: mNetworkType==-1 ret=null"); 2599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville return null; 2609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 2619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile); 2639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group.createSession(listener); 2649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 2659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("createSession;", e); 2669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 2679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession getPendingSession(String callId) { 2728127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2738127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (callId == null) return null; 2759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mPendingSessions.get(callId); 2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String determineLocalIp() { 2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan DatagramSocket s = new DatagramSocket(); 2819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan s.connect(InetAddress.getByName("192.168.1.1"), 80); 2829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return s.getLocalAddress().getHostAddress(); 2839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 2849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("determineLocalIp()", e); 2859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // dont do anything; there should be a connectivity change going 2869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 2879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile) 2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 2929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 2939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 2949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group == null) { 2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, null, null); 2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 298a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else if (!isCallerCreator(group)) { 299a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile, 305845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 306845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) throws SipException { 3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group != null) { 310a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreator(group)) { 311a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 312a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 313845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan group.setIncomingCallPendingIntent(incomingCallPendingIntent); 3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.setListener(listener); 3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, 317845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 3189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 3209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileAdded(SipProfile localProfile) { 3259329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile added: " + localProfile); 3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE); 3279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3297d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 1) { 3307d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh registerReceivers(); 3317d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileRemoved(SipProfile localProfile) { 3359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile removed: " + localProfile); 3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE); 3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3397d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 0) { 3407d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh unregisterReceivers(); 3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 344469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void stopPortMappingMeasurement() { 3459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mSipKeepAliveProcessCallback != null) { 3469329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.stop(); 3479329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = null; 348469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 349469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 350469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 3518a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 3528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile) { 353cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, 354cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan DEFAULT_MAX_KEEPALIVE_INTERVAL); 35544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 35644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 35744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 35844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 3599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if ((mSipKeepAliveProcessCallback == null) 3608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && (mKeepAliveInterval == -1) 3618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && isBehindNAT(mLocalIp)) { 3629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("startPortMappingLifetimeMeasurement: profile=" 3638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + localProfile.getUriString()); 3648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 365cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval = mLastGoodKeepAliveInterval; 366cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (minInterval >= maxInterval) { 367cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If mLastGoodKeepAliveInterval also does not work, reset it 368cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // to the default min 369cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan minInterval = mLastGoodKeepAliveInterval 370cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan = DEFAULT_KEEPALIVE_INTERVAL; 3719329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log(" reset min interval to " + minInterval); 372cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 3739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback( 374cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan localProfile, minInterval, maxInterval); 3759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.start(); 3768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 377469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 378469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 37944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void restartPortMappingLifetimeMeasurement( 38044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 38144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan stopPortMappingMeasurement(); 38244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mKeepAliveInterval = -1; 38344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, maxInterval); 38444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 38544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 3869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void addPendingSession(ISipSession session) { 3879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 3883f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan cleanUpPendingSessions(); 3899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mPendingSessions.put(session.getCallId(), session); 3909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("#pending sess=" + mPendingSessions.size()); 3919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (RemoteException e) { 3929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // should not happen with a local call 3939329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("addPendingSession()", e); 3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3973f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan private void cleanUpPendingSessions() throws RemoteException { 3983f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan Map.Entry<String, ISipSession>[] entries = 3993f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.entrySet().toArray( 4003f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan new Map.Entry[mPendingSessions.size()]); 4013f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan for (Map.Entry<String, ISipSession> entry : entries) { 4023f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) { 4033f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.remove(entry.getKey()); 4043f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4053f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4063f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4073f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan 408ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup, 409ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan SipSessionGroup.SipSessionImpl ringingSession) { 410ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan String callId = ringingSession.getCallId(); 411ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 412ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if ((group != ringingGroup) && group.containsSession(callId)) { 4139329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("call self: " 414ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + ringingSession.getLocalProfile().getUriString() 415ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + " -> " + group.getLocalProfile().getUriString()); 416ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return true; 417ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 418ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 419ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return false; 420ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 421ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 4228a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private synchronized void onKeepAliveIntervalChanged() { 4238a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4248a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan group.onKeepAliveIntervalChanged(); 4258a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4278a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4288a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private int getKeepAliveInterval() { 4298a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return (mKeepAliveInterval < 0) 430cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan ? mLastGoodKeepAliveInterval 4318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan : mKeepAliveInterval; 4328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private boolean isBehindNAT(String address) { 4358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 4369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: How is isBehindNAT used and why these constanst address: 4379329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // 10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x 4388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan byte[] d = InetAddress.getByName(address).getAddress(); 4398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((d[0] == 10) || 4409329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 172) && 4419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000F0 & d[1]) == 16)) || 4429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 192) && 4439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000FF & d[1]) == 168))) { 4448a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return true; 4458a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4468a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (UnknownHostException e) { 4479329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("isBehindAT()" + address, e); 4488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4498a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return false; 4508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 451ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 4529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class SipSessionGroupExt extends SipSessionAdapter { 4539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SSGE_TAG = "SipSessionGroupExt"; 4549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SSGE_DBG = true; 4559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup mSipGroup; 456845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan private PendingIntent mIncomingCallPendingIntent; 457617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean mOpenedToReceiveCalls; 4589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipAutoReg mAutoRegistration = 4609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville new SipAutoReg(); 4619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipSessionGroupExt(SipProfile localProfile, 463845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 4649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) throws SipException { 4659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("SipSessionGroupExt: profile=" + localProfile); 4661b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup = new SipSessionGroup(duplicate(localProfile), 4671b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh localProfile.getPassword(), mTimer, mMyWakeLock); 468845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = incomingCallPendingIntent; 4699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 4709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipProfile getLocalProfile() { 4739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfile(); 4749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 476ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan public boolean containsSession(String callId) { 477ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return mSipGroup.containsSession(callId); 478ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 479ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 4808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 4818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mAutoRegistration.onKeepAliveIntervalChanged(); 4828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // TODO: remove this method once SipWakeupTimer can better handle variety 4858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // of timeout values 4868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan void setWakeupTimer(SipWakeupTimer timer) { 4878a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSipGroup.setWakeupTimer(timer); 4888a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4898a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipProfile duplicate(SipProfile p) { 4919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return new SipProfile.Builder(p).setPassword("*").build(); 4939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Exception e) { 4949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("duplicate()", e); 4959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("duplicate profile", e); 4969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 5009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 503845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void setIncomingCallPendingIntent(PendingIntent pIntent) { 504845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = pIntent; 5059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void openToReceiveCalls() throws SipException { 508617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = true; 5097d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 5109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.openToReceiveCalls(this); 5119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.start(mSipGroup); 5129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5139329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("openToReceiveCalls: " + getUri() + ": " 514845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 5159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onConnectivityChanged(boolean connected) 5189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 5199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) { 5209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: connected=" + connected + " uri=" 5219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + getUri() + ": " + mIncomingCallPendingIntent); 5229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 5239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.onConnectivityChanged(); 5249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 5251b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup.reset(); 526617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (mOpenedToReceiveCalls) openToReceiveCalls(); 5279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 5289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void close() { 534617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = false; 5359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5379329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("close: " + getUri() + ": " + mIncomingCallPendingIntent); 5389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public ISipSession createSession(ISipSessionListener listener) { 5419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("createSession"); 5429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.createSession(listener); 5439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 546845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void onRinging(ISipSession s, SipProfile caller, 5479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String sessionDescription) { 548845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipSessionGroup.SipSessionImpl session = 549845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan (SipSessionGroup.SipSessionImpl) s; 5509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 5519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 552ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (!isRegistered() || callingSelf(this, session)) { 5539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: end notReg or self"); 5549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan session.endCall(); 5559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 5569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // send out incoming call broadcast 5599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan addPendingSession(session); 5609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = SipManager.createIncomingCallBroadcast( 561845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.getCallId(), sessionDescription); 5629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: uri=" + getUri() + ": " 5639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + caller.getUri() + ": " + session.getCallId() 564845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + " " + mIncomingCallPendingIntent); 565845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent.send(mContext, 566845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipManager.INCOMING_CALL_RESULT_CODE, intent); 567845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } catch (PendingIntent.CanceledException e) { 5689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onRinging: pendingIntent is canceled, drop incoming call", e); 569845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.endCall(); 5709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 5759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onError(ISipSession session, int errorCode, 5769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 5779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onError: errorCode=" + errorCode + " desc=" 5789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 5799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 581617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan public boolean isOpenedToReceiveCalls() { 582617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return mOpenedToReceiveCalls; 5839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 5869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mAutoRegistration.isRegistered(); 5879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getUri() { 5909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfileUri(); 5919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5929329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 5939329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 5949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SSGE_TAG, s); 5959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 5969329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 5979329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 5989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SSGE_TAG, s, t); 5999329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 6009329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6039329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipKeepAliveProcessCallback implements Runnable, 6048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipSessionGroup.KeepAliveProcessCallback { 6059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SKAI_TAG = "SipKeepAliveProcessCallback"; 6069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SKAI_DBG = true; 6077d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_INTERVAL = 5; // in seconds 6088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int PASS_THRESHOLD = 10; 6097d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds 61037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private SipProfile mLocalProfile; 611469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroupExt mGroup; 612469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroup.SipSessionImpl mSession; 613cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mMinInterval; 61444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mMaxInterval; 61544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mInterval; 61637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private int mPassCount; 61744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 6189329db04f13480ccdff013dcc00cdb96f12a921cWink Saville public SipKeepAliveProcessCallback(SipProfile localProfile, 619cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval, int maxInterval) { 620cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMaxInterval = maxInterval; 621cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMinInterval = minInterval; 62237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mLocalProfile = localProfile; 623469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 624469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 625469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void start() { 6268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 62737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mSession != null) { 62837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 6297d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 63037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 63137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mInterval = (mMaxInterval + mMinInterval) / 2; 63237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mPassCount = 0; 63337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 63437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // Don't start measurement if the interval is too small 63537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mInterval < DEFAULT_KEEPALIVE_INTERVAL || checkTermination()) { 6369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: measurement aborted; interval=[" + 63737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mMinInterval + "," + mMaxInterval + "]"); 63837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 63937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 64037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 6418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 6429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: interval=" + mInterval); 64337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 64437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = new SipSessionGroupExt(mLocalProfile, null, null); 64537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // TODO: remove this line once SipWakeupTimer can better handle 64637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // variety of timeout values 64737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor)); 64837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 64937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mSession = (SipSessionGroup.SipSessionImpl) 65037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.createSession(null); 6518a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 65237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } catch (Throwable t) { 65337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh onError(SipErrorCode.CLIENT_ERROR, t.toString()); 6548a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 6558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 656469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 657469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 658469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void stop() { 6598a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 6607d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession != null) { 6617d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.stopKeepAliveProcess(); 6627d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession = null; 6637d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 66437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mGroup != null) { 66537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.close(); 66637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = null; 66737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 6687d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 6699329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("stop"); 670469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 671469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 672469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 6738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void restart() { 674469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 6757d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // Return immediately if the measurement process is stopped 6767d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession == null) return; 6777d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 6789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("restart: interval=" + mInterval); 679469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 6808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.stopKeepAliveProcess(); 6817d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mPassCount = 0; 6828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 6838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 6849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("restart", e); 685469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 686469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 687469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 688469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 689cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private boolean checkTermination() { 690cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan return ((mMaxInterval - mMinInterval) < MIN_INTERVAL); 691cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 692cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan 6938a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 6948a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 6958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 6969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 6978a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!portChanged) { 69844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (++mPassCount != PASS_THRESHOLD) return; 6998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update the interval, since the current interval is good to 7008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // keep the port mapping. 701cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (mKeepAliveInterval > 0) { 702cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mLastGoodKeepAliveInterval = mKeepAliveInterval; 703cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 7048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval = mInterval; 7059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: portChanged=" + portChanged + " mKeepAliveInterval=" 7078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 708257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 7098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan onKeepAliveIntervalChanged(); 7108a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7118a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Since the rport is changed, shorten the interval. 7128a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMaxInterval = mInterval; 7138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 714cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (checkTermination()) { 7158a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update mKeepAliveInterval and stop measurement. 7168a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan stop(); 717cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If all the measurements failed, we still set it to 718cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // mMinInterval; If mMinInterval still doesn't work, a new 719cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL 720cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // will be conducted. 7218a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval; 7229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7239329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: checkTermination mKeepAliveInterval=" 7248a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 725469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 7268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7278a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // calculate the new interval and continue. 7288a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mInterval = (mMaxInterval + mMinInterval) / 2; 7299329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: mKeepAliveInterval=" + mKeepAliveInterval 7319329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + ", new mInterval=" + mInterval); 7328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan restart(); 7349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 7398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 7408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 7419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) loge("onError: errorCode=" + errorCode + " desc=" + description); 7427d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartLater(); 7437d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7447d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7457d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // timeout handler 7467d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan @Override 7477d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan public void run() { 7487d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7497d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restart(); 7507d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7517d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7527d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void restartLater() { 7538a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 7547d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = NAT_MEASUREMENT_RETRY_INTERVAL; 7557d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7567d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.set(interval * 1000, this); 7578a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 7619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 7659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7669329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7679329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 7699329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s, t); 7709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipAutoReg extends SipSessionAdapter 7748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan implements Runnable, SipSessionGroup.KeepAliveProcessCallback { 7759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private String SAR_TAG; 7769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SAR_DBG = true; 7777d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10; 7787d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 7808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private SipSessionGroup.SipSessionImpl mKeepAliveSession; 7819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionListenerProxy mProxy = new SipSessionListenerProxy(); 7829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mBackoff = 1; 7839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mRegistered; 7849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private long mExpiryTime; 7859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mErrorCode; 7869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mErrorMessage; 787d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 7889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7897d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private int mKeepAliveSuccessCount = 0; 7907d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start(SipSessionGroup group) { 792d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) { 793d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 7949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff = 1; 7959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = (SipSessionGroup.SipSessionImpl) 7969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.createSession(this); 7979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // return right away if no active network connection. 7989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mSession == null) return; 7999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // start unregistration to clear up old registration at server 8019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: when rfc5626 is deployed, use reg-id and sip.instance 8029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // in registration to avoid adding duplicate entries to server 803257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 8049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.unregister(); 8059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville SAR_TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString(); 8069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("start: group=" + group); 8079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8107d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void startKeepAliveProcess(int interval) { 8119329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("startKeepAliveProcess: interval=" + interval); 8127d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession == null) { 8137d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = mSession.duplicate(); 8147d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8157d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8167d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8177d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan try { 8187d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.startKeepAliveProcess(interval, this); 8197d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } catch (SipException e) { 8209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("startKeepAliveProcess: interval=" + interval, e); 8217d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8227d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8237d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8247d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void stopKeepAliveProcess() { 8257d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession != null) { 8267d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8277d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = null; 8287d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8297d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8307d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8317d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 8358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 83644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (portChanged) { 8377d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = getKeepAliveInterval(); 8387d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) { 8399329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8409329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: keepalive doesn't work with interval " 8419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + interval + ", past success count=" 8429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + mKeepAliveSuccessCount); 8439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 8447d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (interval > DEFAULT_KEEPALIVE_INTERVAL) { 8457d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartPortMappingLifetimeMeasurement( 8467d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.getLocalProfile(), interval); 8477d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8487d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8497d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("keep keepalive going with interval " 85285caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + interval + ", past success count=" 85385caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + mKeepAliveSuccessCount); 85485caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 8557d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount /= 2; 8567d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 85744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } else { 85844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // Start keep-alive interval measurement on the first 85944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // successfully kept-alive SipSessionGroup 86044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement( 86144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mSession.getLocalProfile()); 8627d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount++; 86344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 8648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!mRunning || !portChanged) return; 8669dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8679dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // The keep alive process is stopped when port is changed; 8689dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // Nullify the session so that the process can be restarted 8699dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // again when the re-registration is done 8709dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan mKeepAliveSession = null; 8719dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Acquire wake lock for the registration process. The 8738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // lock will be released when registration is complete. 8748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMyWakeLock.acquire(mSession); 8758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.register(EXPIRY_TIME); 8768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 8829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onError: errorCode=" + errorCode + " desc=" + description); 88485caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 88544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan onResponse(true); // re-register immediately 8868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8878a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 889d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 890d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 891257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mSession); 892257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mSession != null) { 893257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.setListener(null); 8947d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1 && mRegistered) mSession.unregister(); 895257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 896d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 8979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 8987d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan stopKeepAliveProcess(); 8999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 900d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRegistered = false; 901d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan setListener(mProxy.getListener()); 9029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 9058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (mKeepAliveSession != null) { 9068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan int newInterval = getKeepAliveInterval(); 9079329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 9089329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onKeepAliveIntervalChanged: interval=" + newInterval); 9098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9107d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 9117d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(newInterval); 9128a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9148a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 9169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 9179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.setListener(listener); 9189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int state = (mSession == null) 9219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? SipSession.State.READY_TO_CALL 9229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan : mSession.getState(); 9239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == SipSession.State.REGISTERING) 9249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan || (state == SipSession.State.DEREGISTERING)) { 9259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(mSession); 9269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mRegistered) { 9279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = (int) 9289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (mExpiryTime - SystemClock.elapsedRealtime()); 9299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(mSession, duration); 9309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mErrorCode != SipErrorCode.NO_ERROR) { 9319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mErrorCode == SipErrorCode.TIME_OUT) { 9329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(mSession); 9339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationFailed(mSession, mErrorCode, 9359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorMessage); 9369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9377d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else if (mNetworkType == -1) { 938d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 939d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.DATA_CONNECTION_LOST, 940d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "no data connection"); 941d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mRunning) { 942d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 943d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.CLIENT_ERROR, 944d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "registration not running"); 945d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else { 946d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 947d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.IN_PROGRESS, 948d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan String.valueOf(state)); 9499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Throwable t) { 9519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("setListener: ", t); 9529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 9579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mRegistered; 9589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 960257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // timeout handler: re-register 9618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 963d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan synchronized (SipService.this) { 964d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 965d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 966d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = SipErrorCode.NO_ERROR; 967d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = null; 9689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("run: registering"); 9697d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 970257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 971257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 972257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 9739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void restart(int duration) { 9779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("restart: duration=" + duration + "s later."); 9789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(duration * 1000, this); 9809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int backoffDuration() { 9839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = SHORT_EXPIRY_TIME * mBackoff; 9849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 3600) { 9859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = 3600; 9869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff *= 2; 9889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return duration; 9909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 9939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistering(ISipSession session) { 9949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistering: " + session); 9959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 996d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 997d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 9989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 9999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(session); 10009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1003d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean notCurrentSession(ISipSession session) { 1004d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (session != mSession) { 1005d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan ((SipSessionGroup.SipSessionImpl) session).setListener(null); 1006257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 1007d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return true; 1008d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1009d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return !mRunning; 1010d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1011d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationDone(ISipSession session, int duration) { 10149329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationDone: " + session); 10159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1016d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(session, duration); 10199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 0) { 10219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = SystemClock.elapsedRealtime() 10229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (duration * 1000); 10239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mRegistered) { 10259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = true; 10269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // allow some overlap to avoid call drop during renew 10279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration -= MIN_EXPIRY_TIME; 10289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration < MIN_EXPIRY_TIME) { 10299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = MIN_EXPIRY_TIME; 10309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(duration); 10329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile = mSession.getLocalProfile(); 10348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp) 10358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan || localProfile.getSendKeepAlive())) { 10367d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(getKeepAliveInterval()); 10379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1039257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = -1L; 10439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("Refresh registration immediately"); 10449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan run(); 10459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 10519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 10529329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationFailed: " + session + ": " 10539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 10549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1055d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1057fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan switch (errorCode) { 1058fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.INVALID_CREDENTIALS: 1059fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.SERVER_UNREACHABLE: 10609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log(" pause auto-registration"); 1061fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan stop(); 10620b88a073712b1510db7c636f89c4e19f0131449aHung-ying Tyan break; 1063fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan default: 1064fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 10659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1066d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 1067d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = errorCode; 1068d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = message; 1069d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(session, errorCode, message); 1070257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationTimeout(ISipSession session) { 10769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationTimeout: " + session); 10779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1078d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1079d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorCode = SipErrorCode.TIME_OUT; 10819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(session); 1082fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 1083257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1087fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan private void restartLater() { 10889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) loge("restartLater"); 10899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(backoffDuration()); 10919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10929329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 10939329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 10949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SAR_TAG, s); 10959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 10969329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 10979329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 10989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s); 10999329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11009329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11019329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 11029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s, e); 11039329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class ConnectivityReceiver extends BroadcastReceiver { 11079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 110879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void onReceive(Context context, Intent intent) { 110979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh Bundle bundle = intent.getExtras(); 111079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh if (bundle != null) { 111179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh final NetworkInfo info = (NetworkInfo) 111279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh bundle.get(ConnectivityManager.EXTRA_NETWORK_INFO); 11139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 111479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Run the handler in MyExecutor to be protected by wake lock 111579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mExecutor.execute(new Runnable() { 11169329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 111779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void run() { 111879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh onConnectivityChanged(info); 11199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 112079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh }); 11219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 112379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 112479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 112579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void registerReceivers() { 112679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.registerReceiver(mConnectivityReceiver, 112779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 11289329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("registerReceivers:"); 112979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 113179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void unregisterReceivers() { 113279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.unregisterReceiver(mConnectivityReceiver); 11339329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("unregisterReceivers:"); 113479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 113579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Reset variables maintained by ConnectivityReceiver. 113679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.release(); 11377d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mNetworkType = -1; 11387d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11397d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh 11407d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private void updateWakeLocks() { 11417d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 11427d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (group.isOpenedToReceiveCalls()) { 11437d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // Also grab the WifiLock when we are disconnected, so the 11447d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // system will keep trying to reconnect. It will be released 11457d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // when the system eventually connects to something else. 11467d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == ConnectivityManager.TYPE_WIFI || mNetworkType == -1) { 11477d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.acquire(); 11487d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else { 11497d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11507d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11517d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh return; 11527d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11537d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11547d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11557d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mMyWakeLock.reset(); // in case there's a leak 115679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 115779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 115879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private synchronized void onConnectivityChanged(NetworkInfo info) { 115979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // We only care about the default network, and getActiveNetworkInfo() 116079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // is the only way to distinguish them. However, as broadcasts are 116179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // delivered asynchronously, we might miss DISCONNECTED events from 116279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // getActiveNetworkInfo(), which is critical to our SIP stack. To 116379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // solve this, if it is a DISCONNECTED event to our current network, 116479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // respect it. Otherwise get a new one from getActiveNetworkInfo(). 11657d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (info == null || info.isConnected() || info.getType() != mNetworkType) { 11669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager cm = (ConnectivityManager) 11679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 116879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh info = cm.getActiveNetworkInfo(); 11699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 117179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Some devices limit SIP on Wi-Fi. In this case, if we are not on 117279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Wi-Fi, treat it as a DISCONNECTED event. 11737d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh int networkType = (info != null && info.isConnected()) ? info.getType() : -1; 11747d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipOnWifiOnly && networkType != ConnectivityManager.TYPE_WIFI) { 11757d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh networkType = -1; 11767d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 117879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Ignore the event if the current active network is not changed. 11797d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == networkType) { 11809329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: Maybe we need to send seq/generation number 118179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh return; 118279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) { 11849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: " + mNetworkType + 118579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh " -> " + networkType); 118679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 118879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh try { 11897d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 119079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = null; 119179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh stopPortMappingMeasurement(); 119279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 119379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(false); 119479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 119679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mNetworkType = networkType; 11979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11987d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 119979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = determineLocalIp(); 120079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mKeepAliveInterval = -1; 120179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 120279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 120379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(true); 12049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12067d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 120779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } catch (SipException e) { 12089329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onConnectivityChanged()", e); 12099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1212257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private static Looper createLooper() { 1213257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan HandlerThread thread = new HandlerThread("SipService.Executor"); 1214257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan thread.start(); 1215257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan return thread.getLooper(); 1216257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1217257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1218257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Executes immediate tasks in a single thread. 1219257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Hold/release wake lock for running tasks 12204cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private class MyExecutor extends Handler implements Executor { 12219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan MyExecutor() { 12229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan super(createLooper()); 12239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12254cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan @Override 12264cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan public void execute(Runnable task) { 1227257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(task); 12289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Message.obtain(this, 0/* don't care */, task).sendToTarget(); 12299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void handleMessage(Message msg) { 12339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (msg.obj instanceof Runnable) { 1234257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan executeInternal((Runnable) msg.obj); 12359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("handleMessage: not Runnable ignore msg=" + msg); 12379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1239257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1240257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void executeInternal(Runnable task) { 1241257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 1242257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan task.run(); 1243257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 12449329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("run task: " + task, t); 1245257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } finally { 1246257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(task); 1247257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1248257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1249257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 12509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 12529329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static void slog(String s) { 12569329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12579329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 12609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(TAG, s, e); 12619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} 1263