SipService.java revision 9dbe2c72276b9968593054dcfd39fd5135a574aa
19c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/* 29c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Copyright (C) 2010, The Android Open Source Project 39c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 49c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License"); 59c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * you may not use this file except in compliance with the License. 69c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * You may obtain a copy of the License at 79c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 89c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * http://www.apache.org/licenses/LICENSE-2.0 99c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * 109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Unless required by applicable law or agreed to in writing, software 119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS, 129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * See the License for the specific language governing permissions and 149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * limitations under the License. 159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpackage com.android.server.sip; 189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.app.AlarmManager; 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; 479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.text.TextUtils; 489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport android.util.Log; 499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.io.IOException; 519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.DatagramSocket; 529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.InetAddress; 539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.net.UnknownHostException; 54a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyanimport java.util.ArrayList; 559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Collection; 569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Comparator; 579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.HashMap; 589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Iterator; 599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Map; 609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.Timer; 619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.TimerTask; 629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport java.util.TreeSet; 634cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyanimport java.util.concurrent.Executor; 649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanimport javax.sip.SipException; 659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/** 679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * @hide 689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic final class SipService extends ISipService.Stub { 70acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan static final String TAG = "SipService"; 71acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan static final boolean DEBUGV = false; 728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan static final boolean DEBUG = true; 739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int EXPIRY_TIME = 3600; 749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int SHORT_EXPIRY_TIME = 10; 759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int MIN_EXPIRY_TIME = 60; 768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int DEFAULT_KEEPALIVE_INTERVAL = 10; // in seconds 779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Context mContext; 799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mLocalIp; 809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mNetworkType; 819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mConnected; 824cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer; 8387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private WifiScanProcess mWifiScanProcess; 849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private WifiManager.WifiLock mWifiLock; 859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mWifiOnly; 86469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private IntervalMeasurementProcess mIntervalMeasurementProcess; 879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 884cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private MyExecutor mExecutor = new MyExecutor(); 899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // SipProfile URI --> group 919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, SipSessionGroupExt> mSipGroups = 929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, SipSessionGroupExt>(); 939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // session ID --> session 959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, ISipSession> mPendingSessions = 969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, ISipSession>(); 979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private ConnectivityReceiver mConnectivityReceiver; 999abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan private boolean mWifiEnabled; 100acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan private SipWakeLock mMyWakeLock; 101469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mKeepAliveInterval; 1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan /** 1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Starts the SIP service. Do nothing if the SIP API is not supported on the 1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * device. 1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public static void start(Context context) { 1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (SipManager.isApiSupported(context)) { 1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ServiceManager.addService("sip", new SipService(context)); 11022523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP)); 111dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, "SIP service started"); 1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipService(Context context) { 1169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " service started!"); 1179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext = context; 1189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnectivityReceiver = new ConnectivityReceiver(); 119acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock = new SipWakeLock((PowerManager) 120257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan context.getSystemService(Context.POWER_SERVICE)); 1219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1224cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mTimer = new SipWakeupTimer(context, mExecutor); 1239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiOnly = SipManager.isSipWifiOnly(context); 1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 126dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { 127f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang @Override 128f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang public void onReceive(Context context, Intent intent) { 129f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang String action = intent.getAction(); 1309abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { 1319abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 1329abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan WifiManager.WIFI_STATE_UNKNOWN); 1339abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan synchronized (SipService.this) { 1349abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan switch (state) { 1359abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan case WifiManager.WIFI_STATE_ENABLED: 1369abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan mWifiEnabled = true; 137617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (anyOpenedToReceiveCalls()) grabWifiLock(); 1389abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan break; 1399abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan case WifiManager.WIFI_STATE_DISABLED: 1409abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan mWifiEnabled = false; 1419abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan releaseWifiLock(); 1429abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan break; 1439abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan } 1449abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan } 145f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang } 146f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang } 147f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang }; 148f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang 149dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private void registerReceivers() { 150dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.registerReceiver(mConnectivityReceiver, 151dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 152dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.registerReceiver(mWifiStateReceiver, 153dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); 154dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, " +++ register receivers"); 155dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 156dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 157dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private void unregisterReceivers() { 158dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.unregisterReceiver(mConnectivityReceiver); 159dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.unregisterReceiver(mWifiStateReceiver); 160dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, " --- unregister receivers"); 161dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 162dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 1639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized SipProfile[] getListOfProfiles() { 1648127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1658127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 166a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan boolean isCallerRadio = isCallerRadio(); 167a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan ArrayList<SipProfile> profiles = new ArrayList<SipProfile>(); 1689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 169a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerRadio || isCallerCreator(group)) { 170a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan profiles.add(group.getLocalProfile()); 171a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 173a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return profiles.toArray(new SipProfile[profiles.size()]); 1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 176dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan public synchronized void open(SipProfile localProfile) { 1778127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1788127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 1809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 181dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan boolean addingFirstProfile = mSipGroups.isEmpty(); 1829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan createGroup(localProfile); 183dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (addingFirstProfile && !mSipGroups.isEmpty()) registerReceivers(); 1849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "openToMakeCalls()", e); 1869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void open3(SipProfile localProfile, 191845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 192845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) { 1938127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1948127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 196845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 197845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan Log.w(TAG, "incomingCallPendingIntent cannot be null; " 198845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + "the profile is not opened"); 199a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 2009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "open3: " + localProfile.getUriString() + ": " 202845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + incomingCallPendingIntent + ": " + listener); 2039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 204dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan boolean addingFirstProfile = mSipGroups.isEmpty(); 2059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile, 206845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 207dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (addingFirstProfile && !mSipGroups.isEmpty()) registerReceivers(); 2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localProfile.getAutoRegistration()) { 2099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.openToReceiveCalls(); 2109abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (mWifiEnabled) grabWifiLock(); 2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 2139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "openToReceiveCalls()", e); 2149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 218a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreator(SipSessionGroupExt group) { 219a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipProfile profile = group.getLocalProfile(); 220a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (profile.getCallingUid() == Binder.getCallingUid()); 221a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 222a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 223a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreatorOrRadio(SipSessionGroupExt group) { 224a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (isCallerRadio() || isCallerCreator(group)); 225a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 226a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 227a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerRadio() { 228a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (Binder.getCallingUid() == Process.PHONE_UID); 229a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 230a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 2319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void close(String localProfileUri) { 2328127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2338127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 234a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 235a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 236a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreatorOrRadio(group)) { 2376d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can close this profile"); 238a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 2399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 240a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 241a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group = mSipGroups.remove(localProfileUri); 242a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan notifyProfileRemoved(group.getLocalProfile()); 243a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.close(); 244257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 245617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (!anyOpenedToReceiveCalls()) { 246257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan releaseWifiLock(); 247257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.reset(); // in case there's leak 248257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 249dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (mSipGroups.isEmpty()) unregisterReceivers(); 2509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isOpened(String localProfileUri) { 2538127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2548127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 256a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 257a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 258617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return true; 259a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2606d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can query on the profile"); 261a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 262a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isRegistered(String localProfileUri) { 2668127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2678127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 269a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 270a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 271a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return group.isRegistered(); 272a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2736d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can query on the profile"); 274a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 275a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void setRegistrationListener(String localProfileUri, 2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2808127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2818127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 283a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 284a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreator(group)) { 285a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.setListener(listener); 286a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2876d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator can set listener on the profile"); 288a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession createSession(SipProfile localProfile, 2929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2938127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2948127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mConnected) return null; 2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile); 2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group.createSession(listener); 3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 3016d9d99615a30de0675271553552c3c7b49311354Joe Onorato if (DEBUG) Log.d(TAG, "createSession()", e); 3029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession getPendingSession(String callId) { 3078127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 3088127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (callId == null) return null; 3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mPendingSessions.get(callId); 3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String determineLocalIp() { 3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan DatagramSocket s = new DatagramSocket(); 3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan s.connect(InetAddress.getByName("192.168.1.1"), 80); 3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return s.getLocalAddress().getHostAddress(); 3189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 3196d9d99615a30de0675271553552c3c7b49311354Joe Onorato if (DEBUG) Log.d(TAG, "determineLocalIp()", e); 3209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // dont do anything; there should be a connectivity change going 3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile) 3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 3279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group == null) { 3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, null, null); 3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 333a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else if (!isCallerCreator(group)) { 334a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 3359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile, 340845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 341845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) throws SipException { 3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group != null) { 345a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreator(group)) { 346a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 347a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 348845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan group.setIncomingCallPendingIntent(incomingCallPendingIntent); 3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.setListener(listener); 3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, 352845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileAdded(SipProfile localProfile) { 3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile); 3619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE); 3629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileRemoved(SipProfile localProfile) { 3679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile); 3689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE); 3699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 373617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean anyOpenedToReceiveCalls() { 3749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 375617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (group.isOpenedToReceiveCalls()) return true; 3769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return false; 3789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void grabWifiLock() { 3819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiLock == null) { 3828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) Log.d(TAG, "acquire wifi lock"); 3839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock = ((WifiManager) 3849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.WIFI_SERVICE)) 3859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 3869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock.acquire(); 38787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (!mConnected) startWifiScanner(); 3889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void releaseWifiLock() { 3929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiLock != null) { 3938a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) Log.d(TAG, "release wifi lock"); 3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock.release(); 3959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock = null; 39687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang stopWifiScanner(); 39787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 39887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 39987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 40087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private synchronized void startWifiScanner() { 40187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mWifiScanProcess == null) { 40287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess = new WifiScanProcess(); 40387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 40487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess.start(); 40587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 40687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 40787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private synchronized void stopWifiScanner() { 40887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mWifiScanProcess != null) { 40987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess.stop(); 4109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void onConnectivityChanged( 4149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String type, boolean connected) { 4159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onConnectivityChanged(): " 4169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + mNetworkType + (mConnected? " CONNECTED" : " DISCONNECTED") 4179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + " --> " + type + (connected? " CONNECTED" : " DISCONNECTED")); 4189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean sameType = type.equals(mNetworkType); 4209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!sameType && !connected) return; 4219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wasWifi = "WIFI".equalsIgnoreCase(mNetworkType); 4239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean isWifi = "WIFI".equalsIgnoreCase(type); 4249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wifiOff = (isWifi && !connected) || (wasWifi && !sameType); 4259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wifiOn = isWifi && connected; 4269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wasConnected = mConnected; 4299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mNetworkType = type; 4309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnected = connected; 4319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (wasConnected) { 4339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mLocalIp = null; 4349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.onConnectivityChanged(false); 4369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 4409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mLocalIp = determineLocalIp(); 441469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mKeepAliveInterval = -1; 4429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.onConnectivityChanged(true); 4449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 44587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (isWifi && (mWifiLock != null)) stopWifiScanner(); 446257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } else { 447257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.reset(); // in case there's a leak 448469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang stopPortMappingMeasurement(); 44987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (isWifi && (mWifiLock != null)) startWifiScanner(); 4509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 4529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "onConnectivityChanged()", e); 4539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 456469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void stopPortMappingMeasurement() { 457469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (mIntervalMeasurementProcess != null) { 458469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess.stop(); 459469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess = null; 460469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 461469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 462469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 4638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void startPortMappingLifetimeMeasurement( 4648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile) { 4658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mIntervalMeasurementProcess == null) 4668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && (mKeepAliveInterval == -1) 4678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan && isBehindNAT(mLocalIp)) { 4688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.d(TAG, "start NAT port mapping timeout measurement on " 4698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + localProfile.getUriString()); 4708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 4718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mIntervalMeasurementProcess = new IntervalMeasurementProcess(localProfile); 4728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mIntervalMeasurementProcess.start(); 4738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 474469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 475469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 4769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void addPendingSession(ISipSession session) { 4779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4783f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan cleanUpPendingSessions(); 4799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mPendingSessions.put(session.getCallId(), session); 4803f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (DEBUG) Log.d(TAG, "#pending sess=" + mPendingSessions.size()); 4819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (RemoteException e) { 4829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // should not happen with a local call 4839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "addPendingSession()", e); 4849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4873f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan private void cleanUpPendingSessions() throws RemoteException { 4883f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan Map.Entry<String, ISipSession>[] entries = 4893f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.entrySet().toArray( 4903f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan new Map.Entry[mPendingSessions.size()]); 4913f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan for (Map.Entry<String, ISipSession> entry : entries) { 4923f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) { 4933f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.remove(entry.getKey()); 4943f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4953f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4963f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4973f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan 498ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup, 499ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan SipSessionGroup.SipSessionImpl ringingSession) { 500ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan String callId = ringingSession.getCallId(); 501ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 502ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if ((group != ringingGroup) && group.containsSession(callId)) { 503ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (DEBUG) Log.d(TAG, "call self: " 504ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + ringingSession.getLocalProfile().getUriString() 505ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + " -> " + group.getLocalProfile().getUriString()); 506ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return true; 507ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 508ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 509ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return false; 510ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 511ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5128a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private synchronized void onKeepAliveIntervalChanged() { 5138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 5148a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan group.onKeepAliveIntervalChanged(); 5158a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5168a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5178a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5188a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private int getKeepAliveInterval() { 5198a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return (mKeepAliveInterval < 0) 5208a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan ? DEFAULT_KEEPALIVE_INTERVAL 5218a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan : mKeepAliveInterval; 5228a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5238a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5248a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private boolean isBehindNAT(String address) { 5258a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 5268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan byte[] d = InetAddress.getByName(address).getAddress(); 5278a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((d[0] == 10) || 5288a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan (((0x000000FF & ((int)d[0])) == 172) && 5298a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan ((0x000000F0 & ((int)d[1])) == 16)) || 5308a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan (((0x000000FF & ((int)d[0])) == 192) && 5318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan ((0x000000FF & ((int)d[1])) == 168))) { 5328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return true; 5338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (UnknownHostException e) { 5358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "isBehindAT()" + address, e); 5368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan return false; 5388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 539ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class SipSessionGroupExt extends SipSessionAdapter { 5419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup mSipGroup; 542845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan private PendingIntent mIncomingCallPendingIntent; 543617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean mOpenedToReceiveCalls; 5449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private AutoRegistrationProcess mAutoRegistration = 5469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new AutoRegistrationProcess(); 5479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipSessionGroupExt(SipProfile localProfile, 549845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 5509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) throws SipException { 5519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String password = localProfile.getPassword(); 5529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipProfile p = duplicate(localProfile); 5539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup = createSipSessionGroup(mLocalIp, p, password); 554845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = incomingCallPendingIntent; 5559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipProfile getLocalProfile() { 5599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfile(); 5609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 562ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan public boolean containsSession(String callId) { 563ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return mSipGroup.containsSession(callId); 564ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 565ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 5678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mAutoRegistration.onKeepAliveIntervalChanged(); 5688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // TODO: remove this method once SipWakeupTimer can better handle variety 5718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // of timeout values 5728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan void setWakeupTimer(SipWakeupTimer timer) { 5738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSipGroup.setWakeupTimer(timer); 5748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 5758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 5769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network connectivity is tricky because network can be disconnected 5779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // at any instant so need to deal with exceptions carefully even when 5789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // you think you are connected 5799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup createSipSessionGroup(String localIp, 5809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipProfile localProfile, String password) throws SipException { 5819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 582acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan return new SipSessionGroup(localIp, localProfile, password, 5838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mTimer, mMyWakeLock); 5849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 5859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network disconnected 5869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "createSipSessionGroup(): network disconnected?"); 5879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localIp != null) { 5889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return createSipSessionGroup(null, localProfile, password); 5899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 5909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // recursive 5916d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.wtf(TAG, "impossible! recursive!"); 5929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("createSipSessionGroup"); 5939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipProfile duplicate(SipProfile p) { 5989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 5999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return new SipProfile.Builder(p).setPassword("*").build(); 6009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Exception e) { 6019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.wtf(TAG, "duplicate()", e); 6029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("duplicate profile", e); 6039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 6079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 6089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 610845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void setIncomingCallPendingIntent(PendingIntent pIntent) { 611845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = pIntent; 6129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void openToReceiveCalls() throws SipException { 615617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = true; 6169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mConnected) { 6179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.openToReceiveCalls(this); 6189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.start(mSipGroup); 6199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " openToReceiveCalls: " + getUri() + ": " 621845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 6229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onConnectivityChanged(boolean connected) 6259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 6269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.onConnectivityChanged(); 6279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 6289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan resetGroup(mLocalIp); 629617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (mOpenedToReceiveCalls) openToReceiveCalls(); 6309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 631617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan // close mSipGroup but remember mOpenedToReceiveCalls 6329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " close auto reg temporarily: " 633845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + getUri() + ": " + mIncomingCallPendingIntent); 6349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 6359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 6369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void resetGroup(String localIp) throws SipException { 6409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 6419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.reset(localIp); 6429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 6439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network disconnected 6449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "resetGroup(): network disconnected?"); 6459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localIp != null) { 6469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan resetGroup(null); // reset w/o local IP 6479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 6489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // recursive 6499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.wtf(TAG, "impossible!"); 6509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("resetGroup"); 6519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void close() { 656617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = false; 6579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 6589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 6599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " close: " + getUri() + ": " 660845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 6619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public ISipSession createSession(ISipSessionListener listener) { 6649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.createSession(listener); 6659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 668845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void onRinging(ISipSession s, SipProfile caller, 6699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String sessionDescription) { 670acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan if (DEBUGV) Log.d(TAG, "<<<<< onRinging()"); 671845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipSessionGroup.SipSessionImpl session = 672845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan (SipSessionGroup.SipSessionImpl) s; 6739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 6749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 675ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (!isRegistered() || callingSelf(this, session)) { 6769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan session.endCall(); 6779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 6789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // send out incoming call broadcast 6819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan addPendingSession(session); 6829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = SipManager.createIncomingCallBroadcast( 683845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.getCallId(), sessionDescription); 6849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": " 6859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + caller.getUri() + ": " + session.getCallId() 686845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + " " + mIncomingCallPendingIntent); 687845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent.send(mContext, 688845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipManager.INCOMING_CALL_RESULT_CODE, intent); 689845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } catch (PendingIntent.CanceledException e) { 690845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan Log.w(TAG, "pendingIntent is canceled, drop incoming call"); 691845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.endCall(); 6929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 6979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onError(ISipSession session, int errorCode, 6989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 6999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "sip session error: " 7009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 7019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 703617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan public boolean isOpenedToReceiveCalls() { 704617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return mOpenedToReceiveCalls; 7059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 7089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mAutoRegistration.isRegistered(); 7099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getUri() { 7129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfileUri(); 7139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 71687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private class WifiScanProcess implements Runnable { 71787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private static final String TAG = "\\WIFI_SCAN/"; 71887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private static final int INTERVAL = 60; 71987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private boolean mRunning = false; 72087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 72187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private WifiManager mWifiManager; 72287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 72387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void start() { 72487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mRunning) return; 72587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mRunning = true; 72687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mTimer.set(INTERVAL * 1000, this); 72787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 72887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 72987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang WifiScanProcess() { 73087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiManager = (WifiManager) 73187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mContext.getSystemService(Context.WIFI_SERVICE); 73287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 73387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 73487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void run() { 73587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang // scan and associate now 73687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (DEBUGV) Log.v(TAG, "just wake up here for wifi scanning..."); 73787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiManager.startScanActive(); 73887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 73987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 74087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void stop() { 74187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mRunning = false; 74287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mTimer.cancel(this); 74387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 74487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 74587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 7468a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private class IntervalMeasurementProcess implements 7478a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipSessionGroup.KeepAliveProcessCallback { 7488a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final String TAG = "SipKeepAliveInterval"; 749469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final int MAX_INTERVAL = 120; // seconds 750469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final int MIN_INTERVAL = SHORT_EXPIRY_TIME; 7518a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private static final int PASS_THRESHOLD = 10; 752469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroupExt mGroup; 753469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroup.SipSessionImpl mSession; 754469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private boolean mRunning; 7558a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private int mMinInterval = 10; // in seconds 756469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mMaxInterval = MAX_INTERVAL; 757469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mInterval = MAX_INTERVAL / 2; 758469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mPassCounter = 0; 759469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 7608a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public IntervalMeasurementProcess(SipProfile localProfile) { 761469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 7628a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mGroup = new SipSessionGroupExt(localProfile, null, null); 7638a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // TODO: remove this line once SipWakeupTimer can better handle 7648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // variety of timeout values 7658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mGroup.setWakeupTimer(new SipWakeupTimer(mContext, mExecutor)); 766469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mSession = (SipSessionGroup.SipSessionImpl) 7678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mGroup.createSession(null); 768469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } catch (Exception e) { 769469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang Log.w(TAG, "start interval measurement error: " + e); 770469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 771469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 772469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 773469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void start() { 7748a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 7758a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 7768a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 7778a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 7788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "start()", e); 7798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 7808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 781469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 782469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 783469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void stop() { 7848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 7858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.stopKeepAliveProcess(); 786469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 787469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 788469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 7898a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private void restart() { 790469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 791469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 7928a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.stopKeepAliveProcess(); 7938a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.startKeepAliveProcess(mInterval, this); 7948a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 7958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "restart()", e); 796469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 797469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 798469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 799469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 8008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8018a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 8039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 8048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!portChanged) { 8058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (++mPassCounter != PASS_THRESHOLD) return; 8068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update the interval, since the current interval is good to 8078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // keep the port mapping. 8088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval = mInterval; 8098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) { 8108a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.d(TAG, "measured good keepalive interval: " 8118a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 812257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 8138a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan onKeepAliveIntervalChanged(); 8148a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 8158a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Since the rport is changed, shorten the interval. 8168a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMaxInterval = mInterval; 8178a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8188a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) { 8198a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // update mKeepAliveInterval and stop measurement. 8208a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan stop(); 8218a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveInterval = mMinInterval; 8228a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) { 8238a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.d(TAG, "measured keepalive interval: " 8248a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + mKeepAliveInterval); 825469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 8268a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } else { 8278a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // calculate the new interval and continue. 8288a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mInterval = (mMaxInterval + mMinInterval) / 2; 8298a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mPassCounter = 0; 8308a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) { 8318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.d(TAG, "current interval: " + mKeepAliveInterval 8328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan + ", test new interval: " + mInterval); 8338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan restart(); 8359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 8428a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 8438a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.w(TAG, "interval measurement error: " + description); 8448a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 8459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class AutoRegistrationProcess extends SipSessionAdapter 8498a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan implements Runnable, SipSessionGroup.KeepAliveProcessCallback { 8508a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private String TAG = "SipAudoReg"; 8519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 8528a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan private SipSessionGroup.SipSessionImpl mKeepAliveSession; 8539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionListenerProxy mProxy = new SipSessionListenerProxy(); 8549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mBackoff = 1; 8559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mRegistered; 8569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private long mExpiryTime; 8579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mErrorCode; 8589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mErrorMessage; 859d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 8609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getAction() { 8629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return toString(); 8639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start(SipSessionGroup group) { 866d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) { 867d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 8689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff = 1; 8699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = (SipSessionGroup.SipSessionImpl) 8709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.createSession(this); 8719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // return right away if no active network connection. 8729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mSession == null) return; 8739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // start unregistration to clear up old registration at server 8759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: when rfc5626 is deployed, use reg-id and sip.instance 8769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // in registration to avoid adding duplicate entries to server 877257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 8789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.unregister(); 8798a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) TAG = mSession.getLocalProfile().getUriString(); 8808a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess"); 8819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 8858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 8868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onResponse(boolean portChanged) { 8878a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan synchronized (SipService.this) { 8888a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Start keep-alive interval measurement on the first successfully 8898a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // kept-alive SipSessionGroup 8908a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan startPortMappingLifetimeMeasurement(mSession.getLocalProfile()); 8918a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 8928a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (!mRunning || !portChanged) return; 8939dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8949dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // The keep alive process is stopped when port is changed; 8959dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // Nullify the session so that the process can be restarted 8969dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan // again when the re-registration is done 8979dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan mKeepAliveSession = null; 8989dbe2c72276b9968593054dcfd39fd5135a574aaHung-ying Tyan 8998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // Acquire wake lock for the registration process. The 9008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // lock will be released when registration is complete. 9018a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mMyWakeLock.acquire(mSession); 9028a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mSession.register(EXPIRY_TIME); 9038a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9048a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9058a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9068a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan // SipSessionGroup.KeepAliveProcessCallback 9078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9088a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onError(int errorCode, String description) { 9098a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "keepalive error: " + description); 9108a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9118a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 913d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 914d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 915257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mSession); 916257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mSession != null) { 917257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.setListener(null); 918257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mConnected && mRegistered) mSession.unregister(); 919257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 920d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 9219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9228a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (mKeepAliveSession != null) { 9238a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 9248a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession = null; 9259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 927d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRegistered = false; 928d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan setListener(mProxy.getListener()); 9299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9318a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan public void onKeepAliveIntervalChanged() { 9328a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (mKeepAliveSession != null) { 9338a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan int newInterval = getKeepAliveInterval(); 9348a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUGV) { 9358a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.v(TAG, "restart keepalive w interval=" + newInterval); 9368a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9378a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession.stopKeepAliveProcess(); 9388a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 9398a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession.startKeepAliveProcess(newInterval, this); 9408a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 9418a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "onKeepAliveIntervalChanged()", e); 9428a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9438a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9448a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } 9458a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan 9469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 9479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 9489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.setListener(listener); 9499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int state = (mSession == null) 9529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? SipSession.State.READY_TO_CALL 9539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan : mSession.getState(); 9549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == SipSession.State.REGISTERING) 9559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan || (state == SipSession.State.DEREGISTERING)) { 9569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(mSession); 9579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mRegistered) { 9589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = (int) 9599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (mExpiryTime - SystemClock.elapsedRealtime()); 9609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(mSession, duration); 9619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mErrorCode != SipErrorCode.NO_ERROR) { 9629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mErrorCode == SipErrorCode.TIME_OUT) { 9639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(mSession); 9649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationFailed(mSession, mErrorCode, 9669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorMessage); 9679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 968d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mConnected) { 969d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 970d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.DATA_CONNECTION_LOST, 971d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "no data connection"); 972d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mRunning) { 973d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 974d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.CLIENT_ERROR, 975d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "registration not running"); 976d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else { 977d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 978d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.IN_PROGRESS, 979d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan String.valueOf(state)); 9809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Throwable t) { 9829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "setListener(): " + t); 9839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 9889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mRegistered; 9899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 991257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // timeout handler: re-register 9928a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan @Override 9939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 994d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan synchronized (SipService.this) { 995d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 996d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 997d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = SipErrorCode.NO_ERROR; 998d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = null; 9998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if (DEBUG) Log.d(TAG, "registering"); 1000257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mConnected) { 1001257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 1002257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 1003257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 10049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void restart(int duration) { 10089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later."); 10099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 10109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(duration * 1000, this); 10119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int backoffDuration() { 10149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = SHORT_EXPIRY_TIME * mBackoff; 10159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 3600) { 10169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = 3600; 10179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff *= 2; 10199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return duration; 10219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistering(ISipSession session) { 10259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistering(): " + session); 10269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1027d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1028d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(session); 10319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1034d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean notCurrentSession(ISipSession session) { 1035d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (session != mSession) { 1036d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan ((SipSessionGroup.SipSessionImpl) session).setListener(null); 1037257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 1038d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return true; 1039d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1040d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return !mRunning; 1041d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1042d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationDone(ISipSession session, int duration) { 10459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session); 10469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1047d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(session, duration); 10509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 0) { 10529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = SystemClock.elapsedRealtime() 10539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (duration * 1000); 10549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mRegistered) { 10569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = true; 10579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // allow some overlap to avoid call drop during renew 10589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration -= MIN_EXPIRY_TIME; 10599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration < MIN_EXPIRY_TIME) { 10609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = MIN_EXPIRY_TIME; 10619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(duration); 10639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10648a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan SipProfile localProfile = mSession.getLocalProfile(); 10658a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan if ((mKeepAliveSession == null) && (isBehindNAT(mLocalIp) 10668a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan || localProfile.getSendKeepAlive())) { 10678a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession = mSession.duplicate(); 10688a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.d(TAG, "start keepalive"); 10698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan try { 10708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan mKeepAliveSession.startKeepAliveProcess( 10718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan getKeepAliveInterval(), this); 10728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan } catch (SipException e) { 10738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan Log.e(TAG, "AutoRegistrationProcess", e); 10749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1077257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = -1L; 10819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Refresh registration immediately"); 10829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan run(); 10839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 10899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 10909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": " 10919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 10929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1093d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1095fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan switch (errorCode) { 1096fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.INVALID_CREDENTIALS: 1097fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.SERVER_UNREACHABLE: 1098fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan if (DEBUG) Log.d(TAG, " pause auto-registration"); 1099fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan stop(); 11000b88a073712b1510db7c636f89c4e19f0131449aHung-ying Tyan break; 1101fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan default: 1102fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 11039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1104d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 1105d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = errorCode; 1106d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = message; 1107d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(session, errorCode, message); 1108257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 11099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 11139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationTimeout(ISipSession session) { 11149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session); 11159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1116d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1117d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 11189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorCode = SipErrorCode.TIME_OUT; 11199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(session); 1120fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 1121257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 11229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1125fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan private void restartLater() { 11269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 11279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(backoffDuration()); 11289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class ConnectivityReceiver extends BroadcastReceiver { 11329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Timer mTimer = new Timer(); 11339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private MyTimerTask mTask; 11349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 1136257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan public void onReceive(final Context context, final Intent intent) { 1137257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Run the handler in MyExecutor to be protected by wake lock 11384cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mExecutor.execute(new Runnable() { 1139257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan public void run() { 1140257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan onReceiveInternal(context, intent); 1141257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1142257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan }); 1143257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1144257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1145257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void onReceiveInternal(Context context, Intent intent) { 11469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String action = intent.getAction(); 11479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 11489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Bundle b = intent.getExtras(); 11499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (b != null) { 11509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo netInfo = (NetworkInfo) 11519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan b.get(ConnectivityManager.EXTRA_NETWORK_INFO); 11529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String type = netInfo.getTypeName(); 11539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo.State state = netInfo.getState(); 11549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiOnly && (netInfo.getType() != 11569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager.TYPE_WIFI)) { 11579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) { 11589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "Wifi only, other connectivity ignored: " 11599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + type); 11609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 11629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo activeNetInfo = getActiveNetworkInfo(); 11659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) { 11669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (activeNetInfo != null) { 11679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "active network: " 11689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + activeNetInfo.getTypeName() 11699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + ((activeNetInfo.getState() == NetworkInfo.State.CONNECTED) 11709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? " CONNECTED" : " DISCONNECTED")); 11719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 11729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "active network: null"); 11739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == NetworkInfo.State.CONNECTED) 11769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan && (activeNetInfo != null) 11779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan && (activeNetInfo.getType() != netInfo.getType())) { 11789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "ignore connect event: " + type 11799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + ", active: " + activeNetInfo.getTypeName()); 11809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 11819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (state == NetworkInfo.State.CONNECTED) { 11849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert: CONNECTED " + type); 11859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onChanged(type, true); 11869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (state == NetworkInfo.State.DISCONNECTED) { 11879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert: DISCONNECTED " + type); 11889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onChanged(type, false); 11899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 11909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert not processed: " 11919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + state + " " + type); 11929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private NetworkInfo getActiveNetworkInfo() { 11989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager cm = (ConnectivityManager) 11999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 12009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return cm.getActiveNetworkInfo(); 12019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void onChanged(String type, boolean connected) { 12049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 12059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // When turning on WIFI, it needs some time for network 12069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // connectivity to get stabile so we defer good news (because 12079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // we want to skip the interim ones) but deliver bad news 12089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // immediately 12099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 1210f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan if (mTask != null) { 1211f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mTask.cancel(); 1212f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mMyWakeLock.release(mTask); 1213f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan } 12149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask = new MyTimerTask(type, connected); 12159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.schedule(mTask, 2 * 1000L); 1216257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // hold wakup lock so that we can finish changes before the 1217257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // device goes to sleep 1218257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mTask); 12199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((mTask != null) && mTask.mNetworkType.equals(type)) { 12219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask.cancel(); 1222257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mTask); 12239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onConnectivityChanged(type, false); 12259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class MyTimerTask extends TimerTask { 12309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mConnected; 12319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mNetworkType; 12329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public MyTimerTask(String type, boolean connected) { 12349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mNetworkType = type; 12359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnected = connected; 12369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1238d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan // timeout handler 12399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 12419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // delegate to mExecutor 12424cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mExecutor.execute(new Runnable() { 12439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 12449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan realRun(); 12459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan }); 12479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void realRun() { 12509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 12519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mTask != this) { 12529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, " unexpected task: " + mNetworkType 12539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (mConnected ? " CONNECTED" : "DISCONNECTED")); 1254f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mMyWakeLock.release(this); 12559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 12569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask = null; 12589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType 12599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (mConnected ? " CONNECTED" : "DISCONNECTED")); 12609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onConnectivityChanged(mNetworkType, mConnected); 1261257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(this); 12629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1267257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private static Looper createLooper() { 1268257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan HandlerThread thread = new HandlerThread("SipService.Executor"); 1269257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan thread.start(); 1270257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan return thread.getLooper(); 1271257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1272257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1273257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Executes immediate tasks in a single thread. 1274257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Hold/release wake lock for running tasks 12754cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private class MyExecutor extends Handler implements Executor { 12769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan MyExecutor() { 12779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan super(createLooper()); 12789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12804cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan @Override 12814cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan public void execute(Runnable task) { 1282257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(task); 12839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Message.obtain(this, 0/* don't care */, task).sendToTarget(); 12849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void handleMessage(Message msg) { 12889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (msg.obj instanceof Runnable) { 1289257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan executeInternal((Runnable) msg.obj); 12909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "can't handle msg: " + msg); 12929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1294257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1295257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void executeInternal(Runnable task) { 1296257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 1297257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan task.run(); 1298257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 1299257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan Log.e(TAG, "run task: " + task, t); 1300257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } finally { 1301257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(task); 1302257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1303257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1304257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 13059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} 1306