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; 579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException; 589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/** 609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * @hide 619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic final class SipService extends ISipService.Stub { 63acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan static final String TAG = "SipService"; 649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville static final boolean DBG = true; 659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int EXPIRY_TIME = 3600; 669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int SHORT_EXPIRY_TIME = 10; 679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int MIN_EXPIRY_TIME = 60; 688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds 69cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private static final int DEFAULT_MAX_KEEPALIVE_INTERVAL = 120; // in seconds 709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Context mContext; 729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mLocalIp; 737d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private int mNetworkType = -1; 744cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer; 759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private WifiManager.WifiLock mWifiLock; 7679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private boolean mSipOnWifiOnly; 77987b505b1c190ff0e5a05d2cc20c9b08d2b99b18Hung-ying Tyan 78d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav private final AppOpsManager mAppOps; 79d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 809329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipKeepAliveProcessCallback mSipKeepAliveProcessCallback; 819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 824cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private MyExecutor mExecutor = new MyExecutor(); 839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // SipProfile URI --> group 859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, SipSessionGroupExt> mSipGroups = 869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, SipSessionGroupExt>(); 879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // session ID --> session 899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, ISipSession> mPendingSessions = 909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, ISipSession>(); 919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private ConnectivityReceiver mConnectivityReceiver; 93acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan private SipWakeLock mMyWakeLock; 94469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mKeepAliveInterval; 95cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan /** 989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Starts the SIP service. Do nothing if the SIP API is not supported on the 999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * device. 1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public static void start(Context context) { 1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (SipManager.isApiSupported(context)) { 1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ServiceManager.addService("sip", new SipService(context)); 10422523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP)); 1059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) slog("start:"); 1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipService(Context context) { 1109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("SipService: started!"); 1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext = context; 1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnectivityReceiver = new ConnectivityReceiver(); 11379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 11479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock = ((WifiManager) 11579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh context.getSystemService(Context.WIFI_SERVICE)) 11679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 11779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.setReferenceCounted(false); 11879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mSipOnWifiOnly = SipManager.isSipWifiOnly(context); 11979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 120acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock = new SipWakeLock((PowerManager) 121257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan context.getSystemService(Context.POWER_SERVICE)); 1229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1234cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mTimer = new SipWakeupTimer(context, mExecutor); 124d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mAppOps = mContext.getSystemService(AppOpsManager.class); 125dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 126dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 1279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 128d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized SipProfile[] getListOfProfiles(String opPackageName) { 129d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "getListOfProfiles")) { 130d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return new SipProfile[0]; 131d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 132a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan boolean isCallerRadio = isCallerRadio(); 133a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan ArrayList<SipProfile> profiles = new ArrayList<SipProfile>(); 1349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 135a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerRadio || isCallerCreator(group)) { 136a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan profiles.add(group.getLocalProfile()); 137a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 1389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 139a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return profiles.toArray(new SipProfile[profiles.size()]); 1409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 143d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized void open(SipProfile localProfile, String opPackageName) { 144d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "open")) { 145d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 146d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 1479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 1489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan createGroup(localProfile); 1509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("openToMakeCalls()", e); 1529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1569329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 1579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void open3(SipProfile localProfile, 158845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 159d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, 160d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav String opPackageName) { 161d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "open3")) { 162d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 163d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 1649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 165845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 1669329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("open3: incomingCallPendingIntent cannot be null; " 167845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + "the profile is not opened"); 168a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 1699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("open3: " + localProfile.getUriString() + ": " 171845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + incomingCallPendingIntent + ": " + listener); 1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile, 174845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localProfile.getAutoRegistration()) { 1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.openToReceiveCalls(); 1777d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1809329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("open3:", e); 1819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 185a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreator(SipSessionGroupExt group) { 186a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipProfile profile = group.getLocalProfile(); 187a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (profile.getCallingUid() == Binder.getCallingUid()); 188a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 189a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 190a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreatorOrRadio(SipSessionGroupExt group) { 191a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (isCallerRadio() || isCallerCreator(group)); 192a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 193a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 194a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerRadio() { 195a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (Binder.getCallingUid() == Process.PHONE_UID); 196a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 197a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 1989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 199d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized void close(String localProfileUri, String opPackageName) { 200d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "close")) { 201d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 202d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 203a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 204a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 205a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreatorOrRadio(group)) { 2069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can close this profile"); 207a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 209a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 210a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group = mSipGroups.remove(localProfileUri); 211a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan notifyProfileRemoved(group.getLocalProfile()); 212a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.close(); 213257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 2147d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2179329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 218d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized boolean isOpened(String localProfileUri, String opPackageName) { 219d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "isOpened")) { 220d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return false; 221d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 223a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 224a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 225617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return true; 226a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 228a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 229a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2329329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 233d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized boolean isRegistered(String localProfileUri, String opPackageName) { 234d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "isRegistered")) { 235d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return false; 236d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 238a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 239a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 240a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return group.isRegistered(); 241a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator or radio can query on the profile"); 243a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 244a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2479329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void setRegistrationListener(String localProfileUri, 249d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, String opPackageName) { 250d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "setRegistrationListener")) { 251d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return; 252d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 254a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 255a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreator(group)) { 256a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.setListener(listener); 257a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("only creator can set listener on the profile"); 259a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 2639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession createSession(SipProfile localProfile, 264d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav ISipSessionListener listener, String opPackageName) { 2659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: profile" + localProfile); 266d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "createSession")) { 267d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return null; 268d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 2709329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mNetworkType == -1) { 2719329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("createSession: mNetworkType==-1 ret=null"); 2729329db04f13480ccdff013dcc00cdb96f12a921cWink Saville return null; 2739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 2749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile); 2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group.createSession(listener); 2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 2789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("createSession;", e); 2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 2809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 284d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav public synchronized ISipSession getPendingSession(String callId, String opPackageName) { 285d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav if (!canUseSip(opPackageName, "getPendingSession")) { 286d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return null; 287d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 2889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (callId == null) return null; 2899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mPendingSessions.get(callId); 2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String determineLocalIp() { 2939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan DatagramSocket s = new DatagramSocket(); 2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan s.connect(InetAddress.getByName("192.168.1.1"), 80); 2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return s.getLocalAddress().getHostAddress(); 2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 2989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) loge("determineLocalIp()", e); 2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // dont do anything; there should be a connectivity change going 3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile) 3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 3069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group == null) { 3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, null, null); 3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 312a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else if (!isCallerCreator(group)) { 313a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile, 319845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 320845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) throws SipException { 3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group != null) { 324a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreator(group)) { 325a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 326a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 327845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan group.setIncomingCallPendingIntent(incomingCallPendingIntent); 3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.setListener(listener); 3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, 331845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileAdded(SipProfile localProfile) { 3399329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile added: " + localProfile); 3409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE); 3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3437d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 1) { 3447d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh registerReceivers(); 3457d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 3469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileRemoved(SipProfile localProfile) { 3499329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("notify: profile removed: " + localProfile); 3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE); 3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3537d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipGroups.size() == 0) { 3547d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh unregisterReceivers(); 3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 358469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void stopPortMappingMeasurement() { 3599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (mSipKeepAliveProcessCallback != null) { 3609329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.stop(); 3619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = null; 362469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 363469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 364469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 3658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 3668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile) { 367cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, 368cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan DEFAULT_MAX_KEEPALIVE_INTERVAL); 36944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 37044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 37144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 37244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 3739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if ((mSipKeepAliveProcessCallback == null) 3748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && (mKeepAliveInterval == -1) 3758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && isBehindNAT(mLocalIp)) { 3769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("startPortMappingLifetimeMeasurement: profile=" 3778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + localProfile.getUriString()); 3788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 379cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval = mLastGoodKeepAliveInterval; 380cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (minInterval >= maxInterval) { 381cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If mLastGoodKeepAliveInterval also does not work, reset it 382cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // to the default min 383cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan minInterval = mLastGoodKeepAliveInterval 384cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan = DEFAULT_KEEPALIVE_INTERVAL; 3859329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log(" reset min interval to " + minInterval); 386cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 3879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback = new SipKeepAliveProcessCallback( 388cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan localProfile, minInterval, maxInterval); 3899329db04f13480ccdff013dcc00cdb96f12a921cWink Saville mSipKeepAliveProcessCallback.start(); 3908a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 391469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 392469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 39344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private void restartPortMappingLifetimeMeasurement( 39444ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan SipProfile localProfile, int maxInterval) { 39544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan stopPortMappingMeasurement(); 39644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mKeepAliveInterval = -1; 39744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement(localProfile, maxInterval); 39844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 39944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 4009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void addPendingSession(ISipSession session) { 4019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4023f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan cleanUpPendingSessions(); 4039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mPendingSessions.put(session.getCallId(), session); 4049329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("#pending sess=" + mPendingSessions.size()); 4059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (RemoteException e) { 4069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // should not happen with a local call 4079329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("addPendingSession()", e); 4089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4113f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan private void cleanUpPendingSessions() throws RemoteException { 4123f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan Map.Entry<String, ISipSession>[] entries = 4133f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.entrySet().toArray( 4143f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan new Map.Entry[mPendingSessions.size()]); 4153f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan for (Map.Entry<String, ISipSession> entry : entries) { 4163f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) { 4173f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.remove(entry.getKey()); 4183f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4193f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4203f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4213f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan 422ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup, 423ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan SipSessionGroup.SipSessionImpl ringingSession) { 424ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan String callId = ringingSession.getCallId(); 425ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 426ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if ((group != ringingGroup) && group.containsSession(callId)) { 4279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("call self: " 428ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + ringingSession.getLocalProfile().getUriString() 429ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + " -> " + group.getLocalProfile().getUriString()); 430ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return true; 431ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 432ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 433ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return false; 434ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 435ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 4368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private synchronized void onKeepAliveIntervalChanged() { 4378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan group.onKeepAliveIntervalChanged(); 4398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4428a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private int getKeepAliveInterval() { 4438a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return (mKeepAliveInterval < 0) 444cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan ? mLastGoodKeepAliveInterval 4458a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan : mKeepAliveInterval; 4468a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4478a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private boolean isBehindNAT(String address) { 4498a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 4509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: How is isBehindNAT used and why these constanst address: 4519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // 10.x.x.x | 192.168.x.x | 172.16.x.x .. 172.19.x.x 4528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan byte[] d = InetAddress.getByName(address).getAddress(); 4538a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((d[0] == 10) || 4549329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 172) && 4559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000F0 & d[1]) == 16)) || 4569329db04f13480ccdff013dcc00cdb96f12a921cWink Saville (((0x000000FF & d[0]) == 192) && 4579329db04f13480ccdff013dcc00cdb96f12a921cWink Saville ((0x000000FF & d[1]) == 168))) { 4588a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return true; 4598a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (UnknownHostException e) { 4619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("isBehindAT()" + address, e); 4628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 4638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return false; 4648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 465ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 466d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav private boolean canUseSip(String packageName, String message) { 467d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav mContext.enforceCallingOrSelfPermission( 468d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav android.Manifest.permission.USE_SIP, message); 469d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 470d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav return mAppOps.noteOp(AppOpsManager.OP_USE_SIP, Binder.getCallingUid(), 471d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav packageName) == AppOpsManager.MODE_ALLOWED; 472d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav } 473d08c8ddcf7bab2beaf212fb7607da15f51ebc09cSvetoslav 4749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class SipSessionGroupExt extends SipSessionAdapter { 4759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SSGE_TAG = "SipSessionGroupExt"; 4769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SSGE_DBG = true; 4779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup mSipGroup; 478845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan private PendingIntent mIncomingCallPendingIntent; 479617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean mOpenedToReceiveCalls; 4809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private SipAutoReg mAutoRegistration = 4829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville new SipAutoReg(); 4839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipSessionGroupExt(SipProfile localProfile, 485845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 4869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) throws SipException { 4879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("SipSessionGroupExt: profile=" + localProfile); 4881b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup = new SipSessionGroup(duplicate(localProfile), 4891b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh localProfile.getPassword(), mTimer, mMyWakeLock); 490845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = incomingCallPendingIntent; 4919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 4929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipProfile getLocalProfile() { 4959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfile(); 4969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 498ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan public boolean containsSession(String callId) { 499ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return mSipGroup.containsSession(callId); 500ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 501ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 5038a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mAutoRegistration.onKeepAliveIntervalChanged(); 5048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // TODO: remove this method once SipWakeupTimer can better handle variety 5078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // of timeout values 5088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan void setWakeupTimer(SipWakeupTimer timer) { 5098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSipGroup.setWakeupTimer(timer); 5108a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5118a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipProfile duplicate(SipProfile p) { 5139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 5149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return new SipProfile.Builder(p).setPassword("*").build(); 5159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Exception e) { 5169329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("duplicate()", e); 5179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("duplicate profile", e); 5189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 5229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 525845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void setIncomingCallPendingIntent(PendingIntent pIntent) { 526845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = pIntent; 5279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void openToReceiveCalls() throws SipException { 530617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = true; 5317d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 5329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.openToReceiveCalls(this); 5339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.start(mSipGroup); 5349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5359329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("openToReceiveCalls: " + getUri() + ": " 536845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 5379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onConnectivityChanged(boolean connected) 5409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 5419329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) { 5429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: connected=" + connected + " uri=" 5439329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + getUri() + ": " + mIncomingCallPendingIntent); 5449329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 5459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.onConnectivityChanged(); 5469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 5471b5111f16c1401437d577dfd547af10aa691d44fChia-chi Yeh mSipGroup.reset(); 548617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (mOpenedToReceiveCalls) openToReceiveCalls(); 5499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 5509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void close() { 556617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = false; 5579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5599329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("close: " + getUri() + ": " + mIncomingCallPendingIntent); 5609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public ISipSession createSession(ISipSessionListener listener) { 5639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("createSession"); 5649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.createSession(listener); 5659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 568845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void onRinging(ISipSession s, SipProfile caller, 5699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String sessionDescription) { 570845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipSessionGroup.SipSessionImpl session = 571845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan (SipSessionGroup.SipSessionImpl) s; 5729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 5739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 574ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (!isRegistered() || callingSelf(this, session)) { 5759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: end notReg or self"); 5769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan session.endCall(); 5779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 5789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // send out incoming call broadcast 5819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan addPendingSession(session); 5829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = SipManager.createIncomingCallBroadcast( 583845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.getCallId(), sessionDescription); 5849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onRinging: uri=" + getUri() + ": " 5859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + caller.getUri() + ": " + session.getCallId() 586845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + " " + mIncomingCallPendingIntent); 587845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent.send(mContext, 588845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipManager.INCOMING_CALL_RESULT_CODE, intent); 589845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } catch (PendingIntent.CanceledException e) { 5909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onRinging: pendingIntent is canceled, drop incoming call", e); 591845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.endCall(); 5929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 5979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onError(ISipSession session, int errorCode, 5989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 5999329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SSGE_DBG) log("onError: errorCode=" + errorCode + " desc=" 6009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 6019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 603617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan public boolean isOpenedToReceiveCalls() { 604617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return mOpenedToReceiveCalls; 6059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 6089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mAutoRegistration.isRegistered(); 6099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getUri() { 6129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfileUri(); 6139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6149329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6159329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 6169329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SSGE_TAG, s); 6179329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 6189329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 6209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SSGE_TAG, s, t); 6219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 6229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 6239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6259329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipKeepAliveProcessCallback implements Runnable, 6268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipSessionGroup.KeepAliveProcessCallback { 6279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final String SKAI_TAG = "SipKeepAliveProcessCallback"; 6289329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SKAI_DBG = true; 6297d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_INTERVAL = 5; // in seconds 6308a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int PASS_THRESHOLD = 10; 6317d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int NAT_MEASUREMENT_RETRY_INTERVAL = 120; // in seconds 63237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private SipProfile mLocalProfile; 633469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroupExt mGroup; 634469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroup.SipSessionImpl mSession; 635cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private int mMinInterval; 63644ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mMaxInterval; 63744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan private int mInterval; 63837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh private int mPassCount; 63944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan 6409329db04f13480ccdff013dcc00cdb96f12a921cWink Saville public SipKeepAliveProcessCallback(SipProfile localProfile, 641cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan int minInterval, int maxInterval) { 642cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMaxInterval = maxInterval; 643cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mMinInterval = minInterval; 64437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mLocalProfile = localProfile; 645469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 646469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 647469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void start() { 6488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 64937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mSession != null) { 65037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 6517d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 65237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 65337f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mInterval = (mMaxInterval + mMinInterval) / 2; 65437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mPassCount = 0; 65537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 65637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // Don't start measurement if the interval is too small 65737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mInterval < DEFAULT_KEEPALIVE_INTERVAL || checkTermination()) { 6589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: measurement aborted; interval=[" + 65937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mMinInterval + "," + mMaxInterval + "]"); 66037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh return; 66137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 66237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 6638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 6649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("start: interval=" + mInterval); 66537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 66637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = new SipSessionGroupExt(mLocalProfile, null, null); 66737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // TODO: remove this line once SipWakeupTimer can better handle 66837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh // variety of timeout values 66937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor)); 67037f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh 67137f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mSession = (SipSessionGroup.SipSessionImpl) 67237f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.createSession(null); 6738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 67437f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } catch (Throwable t) { 67537f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh onError(SipErrorCode.CLIENT_ERROR, t.toString()); 6768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 6778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 678469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 679469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 680469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void stop() { 6818a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 6827d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession != null) { 6837d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.stopKeepAliveProcess(); 6847d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession = null; 6857d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 68637f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh if (mGroup != null) { 68737f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup.close(); 68837f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh mGroup = null; 68937f93394fe5c7cfede3a780214fa99a9e2a69133Chia-chi Yeh } 6907d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 6919329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("stop"); 692469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 693469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 694469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 6958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void restart() { 696469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 6977d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // Return immediately if the measurement process is stopped 6987d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mSession == null) return; 6997d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7009329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) log("restart: interval=" + mInterval); 701469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 7028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.stopKeepAliveProcess(); 7037d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mPassCount = 0; 7048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 7058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 7069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("restart", e); 707469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 708469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 709469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 710469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 711cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan private boolean checkTermination() { 712cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan return ((mMaxInterval - mMinInterval) < MIN_INTERVAL); 713cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 714cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan 7158a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 7168a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 7178a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 7189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 7198a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!portChanged) { 72044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (++mPassCount != PASS_THRESHOLD) return; 7218a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update the interval, since the current interval is good to 7228a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // keep the port mapping. 723cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (mKeepAliveInterval > 0) { 724cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan mLastGoodKeepAliveInterval = mKeepAliveInterval; 725cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan } 7268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval = mInterval; 7279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7289329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: portChanged=" + portChanged + " mKeepAliveInterval=" 7298a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 730257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 7318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan onKeepAliveIntervalChanged(); 7328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Since the rport is changed, shorten the interval. 7348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMaxInterval = mInterval; 7358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 736cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan if (checkTermination()) { 7378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update mKeepAliveInterval and stop measurement. 7388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan stop(); 739cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // If all the measurements failed, we still set it to 740cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // mMinInterval; If mMinInterval still doesn't work, a new 741cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // measurement with min interval=DEFAULT_KEEPALIVE_INTERVAL 742cd9cb0845a0ad468bbbadadc133bc7a406e40b4aHung-ying Tyan // will be conducted. 7438a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval; 7449329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7459329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: checkTermination mKeepAliveInterval=" 7468a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 747469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 7488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 7498a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // calculate the new interval and continue. 7508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mInterval = (mMaxInterval + mMinInterval) / 2; 7519329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) { 7529329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: mKeepAliveInterval=" + mKeepAliveInterval 7539329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + ", new mInterval=" + mInterval); 7548a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan restart(); 7569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 7618a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 7628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 7639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SKAI_DBG) loge("onError: errorCode=" + errorCode + " desc=" + description); 7647d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartLater(); 7657d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7667d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7677d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan // timeout handler 7687d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan @Override 7697d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan public void run() { 7707d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7717d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restart(); 7727d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 7737d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 7747d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void restartLater() { 7758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 7767d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = NAT_MEASUREMENT_RETRY_INTERVAL; 7777d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.cancel(this); 7787d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mTimer.set(interval * 1000, this); 7798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 7839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7849329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7859329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7869329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 7879329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s); 7889329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7899329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 7909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable t) { 7919329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SKAI_TAG, s, t); 7929329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 7939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7959329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private class SipAutoReg extends SipSessionAdapter 7968a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan implements Runnable, SipSessionGroup.KeepAliveProcessCallback { 7979329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private String SAR_TAG; 7989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static final boolean SAR_DBG = true; 7997d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private static final int MIN_KEEPALIVE_SUCCESS_COUNT = 10; 8007d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 8028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private SipSessionGroup.SipSessionImpl mKeepAliveSession; 8039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionListenerProxy mProxy = new SipSessionListenerProxy(); 8049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mBackoff = 1; 8059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mRegistered; 8069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private long mExpiryTime; 8079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mErrorCode; 8089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mErrorMessage; 809d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 8109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8117d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private int mKeepAliveSuccessCount = 0; 8127d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start(SipSessionGroup group) { 814d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) { 815d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 8169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff = 1; 8179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = (SipSessionGroup.SipSessionImpl) 8189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.createSession(this); 8199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // return right away if no active network connection. 8209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mSession == null) return; 8219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // start unregistration to clear up old registration at server 8239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: when rfc5626 is deployed, use reg-id and sip.instance 8249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // in registration to avoid adding duplicate entries to server 825257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 8269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.unregister(); 8279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville SAR_TAG = "SipAutoReg:" + mSession.getLocalProfile().getUriString(); 8289329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("start: group=" + group); 8299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8327d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void startKeepAliveProcess(int interval) { 8339329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("startKeepAliveProcess: interval=" + interval); 8347d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession == null) { 8357d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = mSession.duplicate(); 8367d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8377d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8387d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8397d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan try { 8407d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.startKeepAliveProcess(interval, this); 8417d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } catch (SipException e) { 8429329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("startKeepAliveProcess: interval=" + interval, e); 8437d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8447d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8457d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8467d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan private void stopKeepAliveProcess() { 8477d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSession != null) { 8487d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 8497d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSession = null; 8507d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8517d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8527d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8537d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan 8548a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8568a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 8578a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 85844ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan if (portChanged) { 8597d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan int interval = getKeepAliveInterval(); 8607d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (mKeepAliveSuccessCount < MIN_KEEPALIVE_SUCCESS_COUNT) { 8619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8629329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onResponse: keepalive doesn't work with interval " 8639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + interval + ", past success count=" 8649329db04f13480ccdff013dcc00cdb96f12a921cWink Saville + mKeepAliveSuccessCount); 8659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 8667d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan if (interval > DEFAULT_KEEPALIVE_INTERVAL) { 8677d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan restartPortMappingLifetimeMeasurement( 8687d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mSession.getLocalProfile(), interval); 8697d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 8707d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 8717d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } else { 8729329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 8739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("keep keepalive going with interval " 87485caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + interval + ", past success count=" 87585caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh + mKeepAliveSuccessCount); 87685caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 8777d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount /= 2; 8787d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan } 87944ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } else { 88044ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // Start keep-alive interval measurement on the first 88144ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan // successfully kept-alive SipSessionGroup 88244ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan startPortMappingLifetimeMeasurement( 88344ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan mSession.getLocalProfile()); 8847d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount++; 88544ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan } 8868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8878a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!mRunning || !portChanged) return; 8889dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8899dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // The keep alive process is stopped when port is changed; 8909dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // Nullify the session so that the process can be restarted 8919dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // again when the re-registration is done 8929dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan mKeepAliveSession = null; 8939dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8948a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Acquire wake lock for the registration process. The 8958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // lock will be released when registration is complete. 8968a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMyWakeLock.acquire(mSession); 8978a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.register(EXPIRY_TIME); 8988a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9018a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 9028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9038a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 9049329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 9059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onError: errorCode=" + errorCode + " desc=" + description); 90685caf063c027ba0d1defeaff8850e12b6428c4f7Chia-chi Yeh } 90744ccfb03bb349a90546ddb3dc0063cbf4aaddaf1Hung-ying Tyan onResponse(true); // re-register immediately 9088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 911d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 912d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 913257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mSession); 914257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mSession != null) { 915257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.setListener(null); 9167d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1 && mRegistered) mSession.unregister(); 917257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 918d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 9199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9207d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan stopKeepAliveProcess(); 9219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 922d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRegistered = false; 923d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan setListener(mProxy.getListener()); 9249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 9278a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (mKeepAliveSession != null) { 9288a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan int newInterval = getKeepAliveInterval(); 9299329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) { 9309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onKeepAliveIntervalChanged: interval=" + newInterval); 9318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9327d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan mKeepAliveSuccessCount = 0; 9337d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(newInterval); 9348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 9389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 9399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.setListener(listener); 9409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int state = (mSession == null) 9439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? SipSession.State.READY_TO_CALL 9449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan : mSession.getState(); 9459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == SipSession.State.REGISTERING) 9469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan || (state == SipSession.State.DEREGISTERING)) { 9479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(mSession); 9489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mRegistered) { 9499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = (int) 9509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (mExpiryTime - SystemClock.elapsedRealtime()); 9519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(mSession, duration); 9529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mErrorCode != SipErrorCode.NO_ERROR) { 9539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mErrorCode == SipErrorCode.TIME_OUT) { 9549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(mSession); 9559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationFailed(mSession, mErrorCode, 9579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorMessage); 9589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9597d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else if (mNetworkType == -1) { 960d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 961d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.DATA_CONNECTION_LOST, 962d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "no data connection"); 963d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mRunning) { 964d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 965d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.CLIENT_ERROR, 966d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "registration not running"); 967d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else { 968d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 969d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.IN_PROGRESS, 970d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan String.valueOf(state)); 9719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Throwable t) { 9739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("setListener: ", t); 9749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 9799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mRegistered; 9809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 982257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // timeout handler: re-register 9838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 985d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan synchronized (SipService.this) { 986d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 987d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 988d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = SipErrorCode.NO_ERROR; 989d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = null; 9909329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("run: registering"); 9917d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 992257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 993257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 994257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 9959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void restart(int duration) { 9999329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("restart: duration=" + duration + "s later."); 10009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 10019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(duration * 1000, this); 10029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int backoffDuration() { 10059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = SHORT_EXPIRY_TIME * mBackoff; 10069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 3600) { 10079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = 3600; 10089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff *= 2; 10109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return duration; 10129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistering(ISipSession session) { 10169329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistering: " + session); 10179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1018d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1019d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(session); 10229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1025d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean notCurrentSession(ISipSession session) { 1026d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (session != mSession) { 1027d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan ((SipSessionGroup.SipSessionImpl) session).setListener(null); 1028257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 1029d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return true; 1030d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1031d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return !mRunning; 1032d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1033d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationDone(ISipSession session, int duration) { 10369329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationDone: " + session); 10379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1038d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(session, duration); 10419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 0) { 10439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = SystemClock.elapsedRealtime() 10449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (duration * 1000); 10459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mRegistered) { 10479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = true; 10489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // allow some overlap to avoid call drop during renew 10499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration -= MIN_EXPIRY_TIME; 10509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration < MIN_EXPIRY_TIME) { 10519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = MIN_EXPIRY_TIME; 10529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(duration); 10549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile = mSession.getLocalProfile(); 10568a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp) 10578a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan || localProfile.getSendKeepAlive())) { 10587d2904eaae91bd096eccef637dce430a41923424Hung-ying Tyan startKeepAliveProcess(getKeepAliveInterval()); 10599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1061257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = -1L; 10659329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("Refresh registration immediately"); 10669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan run(); 10679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 10739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 10749329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationFailed: " + session + ": " 10759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 10769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1077d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1079fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan switch (errorCode) { 1080fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.INVALID_CREDENTIALS: 1081fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.SERVER_UNREACHABLE: 10829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log(" pause auto-registration"); 1083fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan stop(); 10840b88a073712b1510db7c636f89c4e19f0131449aHung-ying Tyan break; 1085fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan default: 1086fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 10879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1088d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 1089d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = errorCode; 1090d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = message; 1091d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(session, errorCode, message); 1092257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationTimeout(ISipSession session) { 10989329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) log("onRegistrationTimeout: " + session); 10999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1100d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1101d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 11029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorCode = SipErrorCode.TIME_OUT; 11039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(session); 1104fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 1105257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 11069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1109fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan private void restartLater() { 11109329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (SAR_DBG) loge("restartLater"); 11119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 11129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(backoffDuration()); 11139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11149329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11159329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 11169329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(SAR_TAG, s); 11179329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11189329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11199329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s) { 11209329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s); 11219329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11229329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 11239329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 11249329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(SAR_TAG, s, e); 11259329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 11269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class ConnectivityReceiver extends BroadcastReceiver { 11299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 113079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void onReceive(Context context, Intent intent) { 113179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh Bundle bundle = intent.getExtras(); 113279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh if (bundle != null) { 113379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh final NetworkInfo info = (NetworkInfo) 113479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh bundle.get(ConnectivityManager.EXTRA_NETWORK_INFO); 11359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 113679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Run the handler in MyExecutor to be protected by wake lock 113779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mExecutor.execute(new Runnable() { 11389329db04f13480ccdff013dcc00cdb96f12a921cWink Saville @Override 113979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh public void run() { 114079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh onConnectivityChanged(info); 11419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 114279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh }); 11439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 114579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 114679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 114779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void registerReceivers() { 114879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.registerReceiver(mConnectivityReceiver, 114979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 11509329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("registerReceivers:"); 115179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 11529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 115379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private void unregisterReceivers() { 115479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mContext.unregisterReceiver(mConnectivityReceiver); 11559329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("unregisterReceivers:"); 115679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 115779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Reset variables maintained by ConnectivityReceiver. 115879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mWifiLock.release(); 11597d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mNetworkType = -1; 11607d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11617d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh 11627d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh private void updateWakeLocks() { 11637d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 11647d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (group.isOpenedToReceiveCalls()) { 11657d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // Also grab the WifiLock when we are disconnected, so the 11667d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // system will keep trying to reconnect. It will be released 11677d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh // when the system eventually connects to something else. 11687d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == ConnectivityManager.TYPE_WIFI || mNetworkType == -1) { 11697d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.acquire(); 11707d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } else { 11717d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11727d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11737d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh return; 11747d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11757d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11767d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mWifiLock.release(); 11777d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh mMyWakeLock.reset(); // in case there's a leak 117879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 117979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh 118079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh private synchronized void onConnectivityChanged(NetworkInfo info) { 118179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // We only care about the default network, and getActiveNetworkInfo() 118279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // is the only way to distinguish them. However, as broadcasts are 118379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // delivered asynchronously, we might miss DISCONNECTED events from 118479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // getActiveNetworkInfo(), which is critical to our SIP stack. To 118579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // solve this, if it is a DISCONNECTED event to our current network, 118679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // respect it. Otherwise get a new one from getActiveNetworkInfo(). 11877d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (info == null || info.isConnected() || info.getType() != mNetworkType) { 11889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager cm = (ConnectivityManager) 11899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 119079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh info = cm.getActiveNetworkInfo(); 11919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 119379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Some devices limit SIP on Wi-Fi. In this case, if we are not on 119479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Wi-Fi, treat it as a DISCONNECTED event. 11957d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh int networkType = (info != null && info.isConnected()) ? info.getType() : -1; 11967d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mSipOnWifiOnly && networkType != ConnectivityManager.TYPE_WIFI) { 11977d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh networkType = -1; 11987d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh } 11999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 120079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh // Ignore the event if the current active network is not changed. 12017d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType == networkType) { 12029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville // TODO: Maybe we need to send seq/generation number 120379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh return; 120479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12059329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) { 12069329db04f13480ccdff013dcc00cdb96f12a921cWink Saville log("onConnectivityChanged: " + mNetworkType + 120779d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh " -> " + networkType); 120879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 121079d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh try { 12117d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 121279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = null; 121379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh stopPortMappingMeasurement(); 121479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 121579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(false); 121679d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } 12179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 121879d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mNetworkType = networkType; 12199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12207d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh if (mNetworkType != -1) { 122179d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLocalIp = determineLocalIp(); 122279d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mKeepAliveInterval = -1; 122379d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh mLastGoodKeepAliveInterval = DEFAULT_KEEPALIVE_INTERVAL; 122479d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh for (SipSessionGroupExt group : mSipGroups.values()) { 122579d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh group.onConnectivityChanged(true); 12269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12287d803d942453ed2139bb590aba4c4fe025529a8fChia-chi Yeh updateWakeLocks(); 122979d4e0ecfe1bc8d369ffcdfb01dd1900b3ea10d5Chia-chi Yeh } catch (SipException e) { 12309329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("onConnectivityChanged()", e); 12319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1234257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private static Looper createLooper() { 1235257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan HandlerThread thread = new HandlerThread("SipService.Executor"); 1236257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan thread.start(); 1237257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan return thread.getLooper(); 1238257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1239257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1240257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Executes immediate tasks in a single thread. 1241257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Hold/release wake lock for running tasks 12424cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private class MyExecutor extends Handler implements Executor { 12439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan MyExecutor() { 12449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan super(createLooper()); 12459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12474cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan @Override 12484cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan public void execute(Runnable task) { 1249257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(task); 12509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Message.obtain(this, 0/* don't care */, task).sendToTarget(); 12519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void handleMessage(Message msg) { 12559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (msg.obj instanceof Runnable) { 1256257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan executeInternal((Runnable) msg.obj); 12579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12589329db04f13480ccdff013dcc00cdb96f12a921cWink Saville if (DBG) log("handleMessage: not Runnable ignore msg=" + msg); 12599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1261257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1262257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void executeInternal(Runnable task) { 1263257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 1264257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan task.run(); 1265257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 12669329db04f13480ccdff013dcc00cdb96f12a921cWink Saville loge("run task: " + task, t); 1267257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } finally { 1268257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(task); 1269257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1270257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1271257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 12729329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12739329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void log(String s) { 12749329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12769329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12779329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private static void slog(String s) { 12789329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.d(TAG, s); 12799329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12809329db04f13480ccdff013dcc00cdb96f12a921cWink Saville 12819329db04f13480ccdff013dcc00cdb96f12a921cWink Saville private void loge(String s, Throwable e) { 12829329db04f13480ccdff013dcc00cdb96f12a921cWink Saville Rlog.e(TAG, s, e); 12839329db04f13480ccdff013dcc00cdb96f12a921cWink Saville } 12849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} 1285