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 19d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslavimport android.app.AppOpsManager; 209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.app.PendingIntent; 219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.BroadcastReceiver; 229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.Context; 239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.Intent; 249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.content.IntentFilter; 259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.ConnectivityManager; 269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.NetworkInfo; 279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipService; 289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipSession; 299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.ISipSessionListener; 309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipErrorCode; 319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipManager; 329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipProfile; 339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipSession; 349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.sip.SipSessionAdapter; 359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.net.wifi.WifiManager; 369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Binder; 379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Bundle; 389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Handler; 399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.HandlerThread; 409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Looper; 419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.Message; 42257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyanimport android.os.PowerManager; 43a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyanimport android.os.Process; 449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.RemoteException; 459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.ServiceManager; 469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.os.SystemClock; 479329db04f13480ccdff013dcc00cdb96f12a921cWink Savilleimport android.telephony.Rlog; 489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.io.IOException; 509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.DatagramSocket; 519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.InetAddress; 529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.UnknownHostException; 53a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyanimport java.util.ArrayList; 549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.HashMap; 559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Map; 564cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyanimport java.util.concurrent.Executor; 57226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon 589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException; 599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/** 619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * @hide 629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic final class SipService extends ISipService.Stub { 64acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan static final String TAG = "SipService"; 659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville static final boolean DBG = true; 669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int EXPIRY_TIME = 3600; 679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int SHORT_EXPIRY_TIME = 10; 689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int MIN_EXPIRY_TIME = 60; 698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds 70cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private static final int DEFAULT_MAX_KEEPALIVE_INTERVAL = 120; // in seconds 719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Context mContext; 739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mLocalIp; 747d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private int mNetworkType = -1; 754cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer; 769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private WifiManager.WifiLock mWifiLock; 7779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private boolean mSipOnWifiOnly; 78987b505b1c190ff0e5a05d2cc20c9b08d2b99b18Hung-ying Tyan 79d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav private final AppOpsManager mAppOps; 80d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipKeepAliveProcessCallback mSipKeepAliveProcessCallback; 829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 834cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private MyExecutor mExecutor = new MyExecutor(); 849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // SipProfile URI --> group 869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, SipSessionGroupExt> mSipGroups = 879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, SipSessionGroupExt>(); 889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // session ID --> session 909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, ISipSession> mPendingSessions = 919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, ISipSession>(); 929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private ConnectivityReceiver mConnectivityReceiver; 94acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan private SipWakeLock mMyWakeLock; 95469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mKeepAliveInterval; 96cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan /** 999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Starts the SIP service. Do nothing if the SIP API is not supported on the 1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * device. 1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public static void start(Context context) { 1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (SipManager.isApiSupported(context)) { 104f08fe9659343327dc29da410b64597b33613c732Brad Ebinger if (ServiceManager.getService("sip") == null) { 105f08fe9659343327dc29da410b64597b33613c732Brad Ebinger ServiceManager.addService("sip", new SipService(context)); 106f08fe9659343327dc29da410b64597b33613c732Brad Ebinger context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP)); 107f08fe9659343327dc29da410b64597b33613c732Brad Ebinger if (DBG) slog("start:"); 108f08fe9659343327dc29da410b64597b33613c732Brad Ebinger } 1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipService(Context context) { 1139329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("SipService: started!"); 1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext = context; 1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnectivityReceiver = new ConnectivityReceiver(); 11679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 11779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock = ((WifiManager) 11879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh context.getSystemService(Context.WIFI_SERVICE)) 11979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 12079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.setReferenceCounted(false); 12179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mSipOnWifiOnly = SipManager.isSipWifiOnly(context); 12279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 123acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock = new SipWakeLock((PowerManager) 124257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan context.getSystemService(Context.POWER_SERVICE)); 1259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1264cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mTimer = new SipWakeupTimer(context, mExecutor); 127d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mAppOps = mContext.getSystemService(AppOpsManager.class); 128dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 129dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 1309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 131d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized SipProfile[] getListOfProfiles(String opPackageName) { 132d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "getListOfProfiles")) { 133d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return new SipProfile[0]; 134d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 135a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan boolean isCallerRadio = isCallerRadio(); 136a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan ArrayList<SipProfile> profiles = new ArrayList<SipProfile>(); 1379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 138a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerRadio || isCallerCreator(group)) { 139a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan profiles.add(group.getLocalProfile()); 140a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 142a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return profiles.toArray(new SipProfile[profiles.size()]); 1439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 146d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized void open(SipProfile localProfile, String opPackageName) { 147d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "open")) { 148d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 149d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 1509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 1519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan createGroup(localProfile); 1539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("openToMakeCalls()", e); 1559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 1609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void open3(SipProfile localProfile, 161845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 162d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, 163d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav String opPackageName) { 164d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "open3")) { 165d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 166d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 168845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 1699329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("open3: incomingCallPendingIntent cannot be null; " 170845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + "the profile is not opened"); 171a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 173226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon if (DBG) log("open3: " + obfuscateSipUri(localProfile.getUriString()) + ": " 174845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + incomingCallPendingIntent + ": " + listener); 1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile, 177845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localProfile.getAutoRegistration()) { 1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.openToReceiveCalls(); 1807d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 1819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("open3:", e); 1849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 188a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreator(SipSessionGroupExt group) { 189a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipProfile profile = group.getLocalProfile(); 190a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (profile.getCallingUid() == Binder.getCallingUid()); 191a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 192a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 193a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreatorOrRadio(SipSessionGroupExt group) { 194a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (isCallerRadio() || isCallerCreator(group)); 195a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 196a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 197a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerRadio() { 198a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (Binder.getCallingUid() == Process.PHONE_UID); 199a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 200a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 2019329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 202d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized void close(String localProfileUri, String opPackageName) { 203d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "close")) { 204d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 205d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 206a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 207a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 208a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreatorOrRadio(group)) { 2099329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can close this profile"); 210a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 212a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 213a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group = mSipGroups.remove(localProfileUri); 214a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan notifyProfileRemoved(group.getLocalProfile()); 215a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.close(); 216257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 2177d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 2189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 221d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized boolean isOpened(String localProfileUri, String opPackageName) { 222d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "isOpened")) { 223d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return false; 224d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 226a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 227a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 228617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return true; 229a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 231a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 232a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 236d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized boolean isRegistered(String localProfileUri, String opPackageName) { 237d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "isRegistered")) { 238d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return false; 239d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 241a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 242a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 243a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return group.isRegistered(); 244a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 246a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 247a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void setRegistrationListener(String localProfileUri, 252d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, String opPackageName) { 253d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "setRegistrationListener")) { 254d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 255d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 257a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 258a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreator(group)) { 259a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.setListener(listener); 260a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator can set listener on the profile"); 262a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession createSession(SipProfile localProfile, 267d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, String opPackageName) { 2689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: profile" + localProfile); 269d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "createSession")) { 270d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return null; 271d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 2739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mNetworkType == -1) { 2749329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: mNetworkType==-1 ret=null"); 2759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville return null; 2769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile); 2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group.createSession(listener); 2809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 2819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("createSession;", e); 2829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 2839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2869329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 287d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized ISipSession getPendingSession(String callId, String opPackageName) { 288d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "getPendingSession")) { 289d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return null; 290d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (callId == null) return null; 2929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mPendingSessions.get(callId); 2939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String determineLocalIp() { 2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan DatagramSocket s = new DatagramSocket(); 2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan s.connect(InetAddress.getByName("192.168.1.1"), 80); 2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return s.getLocalAddress().getHostAddress(); 3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 3019329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("determineLocalIp()", e); 3029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // dont do anything; there should be a connectivity change going 3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile) 3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group == null) { 3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, null, null); 3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 315a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else if (!isCallerCreator(group)) { 316a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile, 322845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 323845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) throws SipException { 3249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group != null) { 327a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreator(group)) { 328a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 329a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 330845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan group.setIncomingCallPendingIntent(incomingCallPendingIntent); 3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.setListener(listener); 3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, 334845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 3359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileAdded(SipProfile localProfile) { 3429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile added: " + localProfile); 3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE); 3449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3467d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 1) { 3477d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh registerReceivers(); 3487d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileRemoved(SipProfile localProfile) { 3529329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile removed: " + localProfile); 3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE); 3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3567d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 0) { 3577d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh unregisterReceivers(); 3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 361469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void stopPortMappingMeasurement() { 3629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mSipKeepAliveProcessCallback != null) { 3639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.stop(); 3649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = null; 365469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 366469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 367469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 3688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 3698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile) { 370cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, 371cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan DEFAULT_MAX_KEEPALIVE_INTERVAL); 37244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 37344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 37444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 37544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 3769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if ((mSipKeepAliveProcessCallback == null) 3778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && (mKeepAliveInterval == -1) 3788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && isBehindNAT(mLocalIp)) { 3799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("startPortMappingLifetimeMeasurement: profile=" 3808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + localProfile.getUriString()); 3818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 382cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval = mLastGoodKeepAliveInterval; 383cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (minInterval >= maxInterval) { 384cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If mLastGoodKeepAliveInterval also does not work, reset it 385cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // to the default min 386cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan minInterval = mLastGoodKeepAliveInterval 387cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan = DEFAULT_KEEPALIVE_INTERVAL; 3889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log(" reset min interval to " + minInterval); 389cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 3909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback( 391cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan localProfile, minInterval, maxInterval); 3929329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.start(); 3938a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 394469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 395469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 39644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void restartPortMappingLifetimeMeasurement( 39744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 39844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan stopPortMappingMeasurement(); 39944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mKeepAliveInterval = -1; 40044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, maxInterval); 40144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 40244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 4039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void addPendingSession(ISipSession session) { 4049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4053f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan cleanUpPendingSessions(); 4069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mPendingSessions.put(session.getCallId(), session); 4079329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("#pending sess=" + mPendingSessions.size()); 4089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (RemoteException e) { 4099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // should not happen with a local call 4109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("addPendingSession()", e); 4119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4143f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan private void cleanUpPendingSessions() throws RemoteException { 4153f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan Map.Entry<String, ISipSession>[] entries = 4163f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.entrySet().toArray( 4173f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan new Map.Entry[mPendingSessions.size()]); 4183f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan for (Map.Entry<String, ISipSession> entry : entries) { 4193f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) { 4203f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.remove(entry.getKey()); 4213f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4223f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4233f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4243f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan 425ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup, 426ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan SipSessionGroup.SipSessionImpl ringingSession) { 427ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan String callId = ringingSession.getCallId(); 428ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 429ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if ((group != ringingGroup) && group.containsSession(callId)) { 4309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("call self: " 431ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + ringingSession.getLocalProfile().getUriString() 432ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + " -> " + group.getLocalProfile().getUriString()); 433ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return true; 434ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 435ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 436ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return false; 437ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 438ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 4398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private synchronized void onKeepAliveIntervalChanged() { 4408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan group.onKeepAliveIntervalChanged(); 4428a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4438a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4448a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4458a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private int getKeepAliveInterval() { 4468a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return (mKeepAliveInterval < 0) 447cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan ? mLastGoodKeepAliveInterval 4488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan : mKeepAliveInterval; 4498a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4518a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private boolean isBehindNAT(String address) { 4528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 4539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: How is isBehindNAT used and why these constanst address: 4549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // 10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x 4558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan byte[] d = InetAddress.getByName(address).getAddress(); 4568a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((d[0] == 10) || 4579329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 172) && 4589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000F0 & d[1]) == 16)) || 4599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 192) && 4609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000FF & d[1]) == 168))) { 4618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return true; 4628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (UnknownHostException e) { 4649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("isBehindAT()" + address, e); 4658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return false; 4678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 468ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 469d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav private boolean canUseSip(String packageName, String message) { 470d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.enforceCallingOrSelfPermission( 471d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav android.Manifest.permission.USE_SIP, message); 472d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 473d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return mAppOps.noteOp(AppOpsManager.OP_USE_SIP, Binder.getCallingUid(), 474d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav packageName) == AppOpsManager.MODE_ALLOWED; 475d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 476d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 4779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class SipSessionGroupExt extends SipSessionAdapter { 4789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SSGE_TAG = "SipSessionGroupExt"; 4799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SSGE_DBG = true; 4809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup mSipGroup; 481845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan private PendingIntent mIncomingCallPendingIntent; 482617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean mOpenedToReceiveCalls; 4839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipAutoReg mAutoRegistration = 4859329db04f13480ccdff013dcc00cdb96f12a921cWink Saville new SipAutoReg(); 4869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipSessionGroupExt(SipProfile localProfile, 488845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 4899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) throws SipException { 4909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("SipSessionGroupExt: profile=" + localProfile); 4911b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup = new SipSessionGroup(duplicate(localProfile), 4921b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh localProfile.getPassword(), mTimer, mMyWakeLock); 493845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = incomingCallPendingIntent; 4949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 4959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipProfile getLocalProfile() { 4989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfile(); 4999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 501ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan public boolean containsSession(String callId) { 502ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return mSipGroup.containsSession(callId); 503ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 504ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 5068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mAutoRegistration.onKeepAliveIntervalChanged(); 5078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // TODO: remove this method once SipWakeupTimer can better handle variety 5108a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // of timeout values 5118a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan void setWakeupTimer(SipWakeupTimer timer) { 5128a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSipGroup.setWakeupTimer(timer); 5138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5148a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipProfile duplicate(SipProfile p) { 5169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 5179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return new SipProfile.Builder(p).setPassword("*").build(); 5189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Exception e) { 5199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("duplicate()", e); 5209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("duplicate profile", e); 5219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 5259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 528845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void setIncomingCallPendingIntent(PendingIntent pIntent) { 529845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = pIntent; 5309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 532226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon public void openToReceiveCalls() { 533617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = true; 5347d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 5359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.openToReceiveCalls(this); 5369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.start(mSipGroup); 5379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 538226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon if (SSGE_DBG) log("openToReceiveCalls: " + obfuscateSipUri(getUri()) + ": " 539845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 5409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onConnectivityChanged(boolean connected) 5439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 5449329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) { 5459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: connected=" + connected + " uri=" 546226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon + obfuscateSipUri(getUri()) + ": " + mIncomingCallPendingIntent); 5479329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 5489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.onConnectivityChanged(); 5499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 5501b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup.reset(); 551617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (mOpenedToReceiveCalls) openToReceiveCalls(); 5529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 5539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void close() { 559617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = false; 5609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 562226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon if (SSGE_DBG) log("close: " + obfuscateSipUri(getUri()) + ": " 563226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon + mIncomingCallPendingIntent); 5649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public ISipSession createSession(ISipSessionListener listener) { 5679329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("createSession"); 5689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.createSession(listener); 5699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 572845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void onRinging(ISipSession s, SipProfile caller, 5739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String sessionDescription) { 574845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipSessionGroup.SipSessionImpl session = 575845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan (SipSessionGroup.SipSessionImpl) s; 5769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 5779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 578ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (!isRegistered() || callingSelf(this, session)) { 5799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: end notReg or self"); 5809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan session.endCall(); 5819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 5829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // send out incoming call broadcast 5859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan addPendingSession(session); 5869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = SipManager.createIncomingCallBroadcast( 587845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.getCallId(), sessionDescription); 5889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: uri=" + getUri() + ": " 5899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + caller.getUri() + ": " + session.getCallId() 590845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + " " + mIncomingCallPendingIntent); 591845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent.send(mContext, 592845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipManager.INCOMING_CALL_RESULT_CODE, intent); 593845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } catch (PendingIntent.CanceledException e) { 5949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onRinging: pendingIntent is canceled, drop incoming call", e); 595845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.endCall(); 5969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 6019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onError(ISipSession session, int errorCode, 6029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 6039329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onError: errorCode=" + errorCode + " desc=" 6049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 6059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 607617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan public boolean isOpenedToReceiveCalls() { 608617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return mOpenedToReceiveCalls; 6099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 6129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mAutoRegistration.isRegistered(); 6139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getUri() { 6169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfileUri(); 6179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6189329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 6209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SSGE_TAG, s); 6219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 6229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6239329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 6249329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SSGE_TAG, s, t); 6259329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 6269329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6299329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipKeepAliveProcessCallback implements Runnable, 6308a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipSessionGroup.KeepAliveProcessCallback { 6319329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SKAI_TAG = "SipKeepAliveProcessCallback"; 6329329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SKAI_DBG = true; 6337d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_INTERVAL = 5; // in seconds 6348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int PASS_THRESHOLD = 10; 6357d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds 63637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private SipProfile mLocalProfile; 637469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroupExt mGroup; 638469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroup.SipSessionImpl mSession; 639cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mMinInterval; 64044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mMaxInterval; 64144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mInterval; 64237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private int mPassCount; 64344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 6449329db04f13480ccdff013dcc00cdb96f12a921cWink Saville public SipKeepAliveProcessCallback(SipProfile localProfile, 645cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval, int maxInterval) { 646cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMaxInterval = maxInterval; 647cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMinInterval = minInterval; 64837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mLocalProfile = localProfile; 649469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 650469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 651469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void start() { 6528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 65337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mSession != null) { 65437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 6557d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 65637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 65737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mInterval = (mMaxInterval + mMinInterval) / 2; 65837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mPassCount = 0; 65937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 66037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // Don't start measurement if the interval is too small 66137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mInterval < DEFAULT_KEEPALIVE_INTERVAL || checkTermination()) { 6629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: measurement aborted; interval=[" + 66337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mMinInterval + "," + mMaxInterval + "]"); 66437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 66537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 66637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 6678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 6689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: interval=" + mInterval); 66937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 67037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = new SipSessionGroupExt(mLocalProfile, null, null); 67137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // TODO: remove this line once SipWakeupTimer can better handle 67237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // variety of timeout values 67337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor)); 67437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 67537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mSession = (SipSessionGroup.SipSessionImpl) 67637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.createSession(null); 6778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 67837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } catch (Throwable t) { 67937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh onError(SipErrorCode.CLIENT_ERROR, t.toString()); 6808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 6818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 682469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 683469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 684469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void stop() { 6858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 6867d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession != null) { 6877d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.stopKeepAliveProcess(); 6887d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession = null; 6897d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 69037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mGroup != null) { 69137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.close(); 69237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = null; 69337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 6947d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 6959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("stop"); 696469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 697469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 698469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 6998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void restart() { 700469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 7017d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // Return immediately if the measurement process is stopped 7027d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession == null) return; 7037d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7049329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("restart: interval=" + mInterval); 705469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 7068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.stopKeepAliveProcess(); 7077d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mPassCount = 0; 7088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 7098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 7109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("restart", e); 711469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 712469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 713469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 714469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 715cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private boolean checkTermination() { 716cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan return ((mMaxInterval - mMinInterval) < MIN_INTERVAL); 717cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 718cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan 7198a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 7208a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 7218a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 7229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 7238a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!portChanged) { 72444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (++mPassCount != PASS_THRESHOLD) return; 7258a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update the interval, since the current interval is good to 7268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // keep the port mapping. 727cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (mKeepAliveInterval > 0) { 728cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mLastGoodKeepAliveInterval = mKeepAliveInterval; 729cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 7308a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval = mInterval; 7319329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7329329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: portChanged=" + portChanged + " mKeepAliveInterval=" 7338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 734257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 7358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan onKeepAliveIntervalChanged(); 7368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Since the rport is changed, shorten the interval. 7388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMaxInterval = mInterval; 7398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 740cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (checkTermination()) { 7418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update mKeepAliveInterval and stop measurement. 7428a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan stop(); 743cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If all the measurements failed, we still set it to 744cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // mMinInterval; If mMinInterval still doesn't work, a new 745cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL 746cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // will be conducted. 7478a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval; 7489329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7499329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: checkTermination mKeepAliveInterval=" 7508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 751469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 7528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7538a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // calculate the new interval and continue. 7548a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mInterval = (mMaxInterval + mMinInterval) / 2; 7559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7569329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: mKeepAliveInterval=" + mKeepAliveInterval 7579329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + ", new mInterval=" + mInterval); 7588a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7598a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan restart(); 7609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 7658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 7668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 7679329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) loge("onError: errorCode=" + errorCode + " desc=" + description); 7687d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartLater(); 7697d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7707d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7717d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // timeout handler 7727d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan @Override 7737d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan public void run() { 7747d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7757d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restart(); 7767d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7777d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7787d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void restartLater() { 7798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 7807d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = NAT_MEASUREMENT_RETRY_INTERVAL; 7817d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7827d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.set(interval * 1000, this); 7838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7859329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7869329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 7879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7899329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 7919329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7929329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7939329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7949329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 7959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s, t); 7969329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7999329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipAutoReg extends SipSessionAdapter 8008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan implements Runnable, SipSessionGroup.KeepAliveProcessCallback { 8019329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private String SAR_TAG; 8029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SAR_DBG = true; 8037d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10; 8047d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 8068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private SipSessionGroup.SipSessionImpl mKeepAliveSession; 8079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionListenerProxy mProxy = new SipSessionListenerProxy(); 8089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mBackoff = 1; 8099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mRegistered; 8109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private long mExpiryTime; 8119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mErrorCode; 8129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mErrorMessage; 813d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 8149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8157d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private int mKeepAliveSuccessCount = 0; 8167d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start(SipSessionGroup group) { 818d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) { 819d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 8209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff = 1; 8219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = (SipSessionGroup.SipSessionImpl) 8229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.createSession(this); 8239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // return right away if no active network connection. 8249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mSession == null) return; 8259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // start unregistration to clear up old registration at server 8279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: when rfc5626 is deployed, use reg-id and sip.instance 8289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // in registration to avoid adding duplicate entries to server 829257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 8309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.unregister(); 831226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon SAR_TAG = "SipAutoReg:" + 832226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon obfuscateSipUri(mSession.getLocalProfile().getUriString()); 8339329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("start: group=" + group); 8349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8377d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void startKeepAliveProcess(int interval) { 8389329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("startKeepAliveProcess: interval=" + interval); 8397d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession == null) { 8407d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = mSession.duplicate(); 8417d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8427d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8437d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8447d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan try { 8457d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.startKeepAliveProcess(interval, this); 8467d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } catch (SipException e) { 8479329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("startKeepAliveProcess: interval=" + interval, e); 8487d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8497d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8507d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8517d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void stopKeepAliveProcess() { 8527d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession != null) { 8537d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8547d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = null; 8557d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8567d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8577d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8587d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8598a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 8628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 86344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (portChanged) { 8647d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = getKeepAliveInterval(); 8657d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) { 8669329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8679329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: keepalive doesn't work with interval " 8689329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + interval + ", past success count=" 8699329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + mKeepAliveSuccessCount); 8709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 8717d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (interval > DEFAULT_KEEPALIVE_INTERVAL) { 8727d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartPortMappingLifetimeMeasurement( 8737d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.getLocalProfile(), interval); 8747d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8757d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8767d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("keep keepalive going with interval " 87985caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + interval + ", past success count=" 88085caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + mKeepAliveSuccessCount); 88185caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 8827d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount /= 2; 8837d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 88444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } else { 88544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // Start keep-alive interval measurement on the first 88644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // successfully kept-alive SipSessionGroup 88744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement( 88844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mSession.getLocalProfile()); 8897d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount++; 89044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 8918a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8928a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!mRunning || !portChanged) return; 8939dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8949dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // The keep alive process is stopped when port is changed; 8959dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // Nullify the session so that the process can be restarted 8969dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // again when the re-registration is done 8979dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan mKeepAliveSession = null; 8989dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Acquire wake lock for the registration process. The 9008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // lock will be released when registration is complete. 9018a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMyWakeLock.acquire(mSession); 9028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.register(EXPIRY_TIME); 9038a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 9078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 9099329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 9109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onError: errorCode=" + errorCode + " desc=" + description); 91185caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 91244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan onResponse(true); // re-register immediately 9138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9148a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 916d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 917d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 918257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mSession); 919257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mSession != null) { 920257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.setListener(null); 9217d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1 && mRegistered) mSession.unregister(); 922257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 923d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 9249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9257d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan stopKeepAliveProcess(); 9269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 927d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRegistered = false; 928d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan setListener(mProxy.getListener()); 9299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 9328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (mKeepAliveSession != null) { 9338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan int newInterval = getKeepAliveInterval(); 9349329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 9359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onKeepAliveIntervalChanged: interval=" + newInterval); 9368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9377d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 9387d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(newInterval); 9398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 9439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 9449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.setListener(listener); 9459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int state = (mSession == null) 9489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? SipSession.State.READY_TO_CALL 9499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan : mSession.getState(); 9509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == SipSession.State.REGISTERING) 9519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan || (state == SipSession.State.DEREGISTERING)) { 9529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(mSession); 9539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mRegistered) { 9549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = (int) 9559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (mExpiryTime - SystemClock.elapsedRealtime()); 9569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(mSession, duration); 9579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mErrorCode != SipErrorCode.NO_ERROR) { 9589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mErrorCode == SipErrorCode.TIME_OUT) { 9599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(mSession); 9609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationFailed(mSession, mErrorCode, 9629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorMessage); 9639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9647d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else if (mNetworkType == -1) { 965d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 966d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.DATA_CONNECTION_LOST, 967d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "no data connection"); 968d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mRunning) { 969d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 970d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.CLIENT_ERROR, 971d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "registration not running"); 972d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else { 973d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 974d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.IN_PROGRESS, 975d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan String.valueOf(state)); 9769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Throwable t) { 9789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("setListener: ", t); 9799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 9849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mRegistered; 9859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 987257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // timeout handler: re-register 9888a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 990d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan synchronized (SipService.this) { 991d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 992d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 993d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = SipErrorCode.NO_ERROR; 994d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = null; 9959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("run: registering"); 9967d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 997257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 998257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 999257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 10009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void restart(int duration) { 10049329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("restart: duration=" + duration + "s later."); 10059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 10069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(duration * 1000, this); 10079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int backoffDuration() { 10109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = SHORT_EXPIRY_TIME * mBackoff; 10119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 3600) { 10129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = 3600; 10139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff *= 2; 10159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return duration; 10179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistering(ISipSession session) { 10219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistering: " + session); 10229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1023d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1024d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(session); 10279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1030d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean notCurrentSession(ISipSession session) { 1031d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (session != mSession) { 1032d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan ((SipSessionGroup.SipSessionImpl) session).setListener(null); 1033257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 1034d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return true; 1035d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1036d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return !mRunning; 1037d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1038d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationDone(ISipSession session, int duration) { 10419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationDone: " + session); 10429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1043d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(session, duration); 10469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 0) { 10489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = SystemClock.elapsedRealtime() 10499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (duration * 1000); 10509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mRegistered) { 10529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = true; 10539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // allow some overlap to avoid call drop during renew 10549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration -= MIN_EXPIRY_TIME; 10559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration < MIN_EXPIRY_TIME) { 10569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = MIN_EXPIRY_TIME; 10579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(duration); 10599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile = mSession.getLocalProfile(); 10618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp) 10628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan || localProfile.getSendKeepAlive())) { 10637d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(getKeepAliveInterval()); 10649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1066257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = -1L; 10709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("Refresh registration immediately"); 10719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan run(); 10729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 10789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 10799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationFailed: " + session + ": " 10809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 10819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1082d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1084fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan switch (errorCode) { 1085fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.INVALID_CREDENTIALS: 1086fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.SERVER_UNREACHABLE: 10879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log(" pause auto-registration"); 1088fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan stop(); 10890b88a073712b1510db7c636f89c4e19f0131449aHung-ying Tyan break; 1090fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan default: 1091fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 10929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1093d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 1094d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = errorCode; 1095d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = message; 1096d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(session, errorCode, message); 1097257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 11029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationTimeout(ISipSession session) { 11039329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationTimeout: " + session); 11049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1105d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1106d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 11079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorCode = SipErrorCode.TIME_OUT; 11089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(session); 1109fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 1110257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 11119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1114fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan private void restartLater() { 11159329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) loge("restartLater"); 11169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 11179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(backoffDuration()); 11189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 11219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SAR_TAG, s); 11229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11239329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11249329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 11259329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s); 11269329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11289329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 11299329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s, e); 11309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class ConnectivityReceiver extends BroadcastReceiver { 11349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 113579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void onReceive(Context context, Intent intent) { 113679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh Bundle bundle = intent.getExtras(); 113779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh if (bundle != null) { 113879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh final NetworkInfo info = (NetworkInfo) 113979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh bundle.get(ConnectivityManager.EXTRA_NETWORK_INFO); 11409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 114179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Run the handler in MyExecutor to be protected by wake lock 114279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mExecutor.execute(new Runnable() { 11439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 114479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void run() { 114579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh onConnectivityChanged(info); 11469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 114779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh }); 11489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 115079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 115179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 115279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void registerReceivers() { 115379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.registerReceiver(mConnectivityReceiver, 115479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 11559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("registerReceivers:"); 115679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 115879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void unregisterReceivers() { 115979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.unregisterReceiver(mConnectivityReceiver); 11609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("unregisterReceivers:"); 116179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 116279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Reset variables maintained by ConnectivityReceiver. 116379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.release(); 11647d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mNetworkType = -1; 11657d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11667d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh 11677d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private void updateWakeLocks() { 11687d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 11697d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (group.isOpenedToReceiveCalls()) { 11707d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // Also grab the WifiLock when we are disconnected, so the 11717d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // system will keep trying to reconnect. It will be released 11727d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // when the system eventually connects to something else. 11737d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == ConnectivityManager.TYPE_WIFI || mNetworkType == -1) { 11747d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.acquire(); 11757d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else { 11767d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11777d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11787d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh return; 11797d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11807d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11817d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11827d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mMyWakeLock.reset(); // in case there's a leak 118379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 118479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 118579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private synchronized void onConnectivityChanged(NetworkInfo info) { 118679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // We only care about the default network, and getActiveNetworkInfo() 118779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // is the only way to distinguish them. However, as broadcasts are 118879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // delivered asynchronously, we might miss DISCONNECTED events from 118979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // getActiveNetworkInfo(), which is critical to our SIP stack. To 119079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // solve this, if it is a DISCONNECTED event to our current network, 119179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // respect it. Otherwise get a new one from getActiveNetworkInfo(). 11927d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (info == null || info.isConnected() || info.getType() != mNetworkType) { 11939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager cm = (ConnectivityManager) 11949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 119579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh info = cm.getActiveNetworkInfo(); 11969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 119879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Some devices limit SIP on Wi-Fi. In this case, if we are not on 119979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Wi-Fi, treat it as a DISCONNECTED event. 12007d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh int networkType = (info != null && info.isConnected()) ? info.getType() : -1; 12017d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipOnWifiOnly && networkType != ConnectivityManager.TYPE_WIFI) { 12027d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh networkType = -1; 12037d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 12049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 120579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Ignore the event if the current active network is not changed. 12067d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == networkType) { 12079329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: Maybe we need to send seq/generation number 120879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh return; 120979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) { 12119329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: " + mNetworkType + 121279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh " -> " + networkType); 121379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 121579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh try { 12167d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 121779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = null; 121879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh stopPortMappingMeasurement(); 121979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 122079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(false); 122179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 122379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mNetworkType = networkType; 12249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12257d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 122679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = determineLocalIp(); 122779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mKeepAliveInterval = -1; 122879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 122979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 123079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(true); 12319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12337d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 123479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } catch (SipException e) { 12359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onConnectivityChanged()", e); 12369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1239257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private static Looper createLooper() { 1240257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan HandlerThread thread = new HandlerThread("SipService.Executor"); 1241257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan thread.start(); 1242257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan return thread.getLooper(); 1243257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1244257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1245257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Executes immediate tasks in a single thread. 1246257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Hold/release wake lock for running tasks 12474cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private class MyExecutor extends Handler implements Executor { 12489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan MyExecutor() { 12499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan super(createLooper()); 12509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12524cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan @Override 12534cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan public void execute(Runnable task) { 1254257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(task); 12559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Message.obtain(this, 0/* don't care */, task).sendToTarget(); 12569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void handleMessage(Message msg) { 12609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (msg.obj instanceof Runnable) { 1261257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan executeInternal((Runnable) msg.obj); 12629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("handleMessage: not Runnable ignore msg=" + msg); 12649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1266257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1267257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void executeInternal(Runnable task) { 1268257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 1269257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan task.run(); 1270257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 12719329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("run task: " + task, t); 1272257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } finally { 1273257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(task); 1274257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1275257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1276257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 12779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 12799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12809329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static void slog(String s) { 12839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12859329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12869329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 12879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(TAG, s, e); 12889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 1289226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon 1290226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon public static String obfuscateSipUri(String sipUri) { 1291226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon StringBuilder sb = new StringBuilder(); 1292226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon int start = 0; 1293226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon sipUri = sipUri.trim(); 1294226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon if (sipUri.startsWith("sip:")) { 1295226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon start = 4; 1296226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon sb.append("sip:"); 1297226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon } 1298226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon 1299226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon char prevC = '\0'; 1300226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon int len = sipUri.length(); 1301226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon for (int i = start; i < len; i++) { 1302226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon char c = sipUri.charAt(i); 1303226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon char nextC = (i + 1 < len) ? sipUri.charAt(i + 1) : '\0'; 1304226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon char charToAppend = '*'; 1305226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon 1306226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon // This logic allows the first and last letter before an '@' sign to show up without 1307226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon // obfuscation as well as the first and last letter an '@' sign. 1308226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon // e.g.: brad@comment.it => b**d@c******.*t 1309226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon if ((i - start < 1) || 1310226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon (i + 1 == len) || 1311226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon isAllowedCharacter(c) || 1312226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon (prevC == '@') || 1313226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon (nextC == '@')) { 1314226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon charToAppend = c; 1315226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon } 1316226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon sb.append(charToAppend); 1317226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon prevC = c; 1318226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon } 1319226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon return sb.toString(); 1320226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon } 1321226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon 1322226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon private static boolean isAllowedCharacter(char c) { 1323226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon return c == '@' || c == '.'; 1324226ac3ad92a383436a13da89959178d51a0cec1bSantos Cordon } 13259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} 1326