SipService.java revision 4cbf2d2f94aaa094dda5b93357c93234ebccb120
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; 724cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan static final boolean DEBUG = false; 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; 769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Context mContext; 789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mLocalIp; 799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mNetworkType; 809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mConnected; 814cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer; 8287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private WifiScanProcess mWifiScanProcess; 839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private WifiManager.WifiLock mWifiLock; 849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mWifiOnly; 85469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private IntervalMeasurementProcess mIntervalMeasurementProcess; 869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 874cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private MyExecutor mExecutor = new MyExecutor(); 889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // SipProfile URI --> group 909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, SipSessionGroupExt> mSipGroups = 919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, SipSessionGroupExt>(); 929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // session ID --> session 949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Map<String, ISipSession> mPendingSessions = 959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new HashMap<String, ISipSession>(); 969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private ConnectivityReceiver mConnectivityReceiver; 989abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan private boolean mWifiEnabled; 99acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan private SipWakeLock mMyWakeLock; 100469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mKeepAliveInterval; 1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan /** 1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * Starts the SIP service. Do nothing if the SIP API is not supported on the 1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan * device. 1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan */ 1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public static void start(Context context) { 1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (SipManager.isApiSupported(context)) { 1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ServiceManager.addService("sip", new SipService(context)); 10922523a59d879cf47f1e9c202d001d569fad4f69eHung-ying Tyan context.sendBroadcast(new Intent(SipManager.ACTION_SIP_SERVICE_UP)); 110dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, "SIP service started"); 1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipService(Context context) { 1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " service started!"); 1169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext = context; 1179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnectivityReceiver = new ConnectivityReceiver(); 118acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock = new SipWakeLock((PowerManager) 119257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan context.getSystemService(Context.POWER_SERVICE)); 1209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1214cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mTimer = new SipWakeupTimer(context, mExecutor); 1229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiOnly = SipManager.isSipWifiOnly(context); 1239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 125dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { 126f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang @Override 127f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang public void onReceive(Context context, Intent intent) { 128f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang String action = intent.getAction(); 1299abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { 1309abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 1319abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan WifiManager.WIFI_STATE_UNKNOWN); 1329abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan synchronized (SipService.this) { 1339abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan switch (state) { 1349abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan case WifiManager.WIFI_STATE_ENABLED: 1359abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan mWifiEnabled = true; 136617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (anyOpenedToReceiveCalls()) grabWifiLock(); 1379abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan break; 1389abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan case WifiManager.WIFI_STATE_DISABLED: 1399abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan mWifiEnabled = false; 1409abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan releaseWifiLock(); 1419abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan break; 1429abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan } 1439abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan } 144f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang } 145f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang } 146f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang }; 147f452fd81f1a308428b0bfbae883fddb9caced878Chung-yih Wang 148dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private void registerReceivers() { 149dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.registerReceiver(mConnectivityReceiver, 150dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); 151dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.registerReceiver(mWifiStateReceiver, 152dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION)); 153dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, " +++ register receivers"); 154dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 155dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 156dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan private void unregisterReceivers() { 157dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.unregisterReceiver(mConnectivityReceiver); 158dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan mContext.unregisterReceiver(mWifiStateReceiver); 159dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (DEBUG) Log.d(TAG, " --- unregister receivers"); 160dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan } 161dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan 1629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized SipProfile[] getListOfProfiles() { 1638127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1648127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 165a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan boolean isCallerRadio = isCallerRadio(); 166a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan ArrayList<SipProfile> profiles = new ArrayList<SipProfile>(); 1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 168a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerRadio || isCallerCreator(group)) { 169a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan profiles.add(group.getLocalProfile()); 170a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 1719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 172a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return profiles.toArray(new SipProfile[profiles.size()]); 1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 175dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan public synchronized void open(SipProfile localProfile) { 1768127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1778127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 180dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan boolean addingFirstProfile = mSipGroups.isEmpty(); 1819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan createGroup(localProfile); 182dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (addingFirstProfile && !mSipGroups.isEmpty()) registerReceivers(); 1839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 1849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "openToMakeCalls()", e); 1859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 1869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void open3(SipProfile localProfile, 190845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 191845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) { 1928127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 1938127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 1949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 195845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan if (incomingCallPendingIntent == null) { 196845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan Log.w(TAG, "incomingCallPendingIntent cannot be null; " 197845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + "the profile is not opened"); 198a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 1999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "open3: " + localProfile.getUriString() + ": " 201845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + incomingCallPendingIntent + ": " + listener); 2029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 203dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan boolean addingFirstProfile = mSipGroups.isEmpty(); 2049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile, 205845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 206dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (addingFirstProfile && !mSipGroups.isEmpty()) registerReceivers(); 2079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localProfile.getAutoRegistration()) { 2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.openToReceiveCalls(); 2099abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (mWifiEnabled) grabWifiLock(); 2109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "openToReceiveCalls()", e); 2139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: how to send the exception back 2149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 217a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreator(SipSessionGroupExt group) { 218a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipProfile profile = group.getLocalProfile(); 219a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (profile.getCallingUid() == Binder.getCallingUid()); 220a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 221a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 222a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerCreatorOrRadio(SipSessionGroupExt group) { 223a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (isCallerRadio() || isCallerCreator(group)); 224a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 225a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 226a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan private boolean isCallerRadio() { 227a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return (Binder.getCallingUid() == Process.PHONE_UID); 228a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 229a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 2309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void close(String localProfileUri) { 2318127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2328127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 233a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 234a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 235a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreatorOrRadio(group)) { 2366d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can close this profile"); 237a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return; 2389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 239a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan 240a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group = mSipGroups.remove(localProfileUri); 241a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan notifyProfileRemoved(group.getLocalProfile()); 242a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.close(); 243257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 244617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (!anyOpenedToReceiveCalls()) { 245257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan releaseWifiLock(); 246257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.reset(); // in case there's leak 247257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 248dc7545495e1ef8bad32cd78775f4dc072015eea0Hung-ying Tyan if (mSipGroups.isEmpty()) unregisterReceivers(); 2499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isOpened(String localProfileUri) { 2528127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2538127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 255a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 256a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 257617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return true; 258a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2596d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can query on the profile"); 260a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 261a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized boolean isRegistered(String localProfileUri) { 2658127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2668127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 268a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return false; 269a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreatorOrRadio(group)) { 270a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return group.isRegistered(); 271a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2726d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator or radio can query on the profile"); 273a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan return false; 274a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized void setRegistrationListener(String localProfileUri, 2789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2798127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2808127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(localProfileUri); 282a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (group == null) return; 283a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (isCallerCreator(group)) { 284a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan group.setListener(listener); 285a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else { 2866d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.w(TAG, "only creator can set listener on the profile"); 287a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 2889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 2899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession createSession(SipProfile localProfile, 2919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) { 2928127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 2938127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 2949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan localProfile.setCallingUid(Binder.getCallingUid()); 2959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mConnected) return null; 2969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = createGroup(localProfile); 2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group.createSession(listener); 2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 3006d9d99615a30de0675271553552c3c7b49311354Joe Onorato if (DEBUG) Log.d(TAG, "createSession()", e); 3019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public synchronized ISipSession getPendingSession(String callId) { 3068127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan mContext.enforceCallingOrSelfPermission( 3078127b35b75c13f853dc8eb2fed8bba4bf99e3eedHung-ying Tyan android.Manifest.permission.USE_SIP, null); 3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (callId == null) return null; 3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mPendingSessions.get(callId); 3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String determineLocalIp() { 3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan DatagramSocket s = new DatagramSocket(); 3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan s.connect(InetAddress.getByName("192.168.1.1"), 80); 3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return s.getLocalAddress().getHostAddress(); 3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 3186d9d99615a30de0675271553552c3c7b49311354Joe Onorato if (DEBUG) Log.d(TAG, "determineLocalIp()", e); 3199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // dont do anything; there should be a connectivity change going 3209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return null; 3219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile) 3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group == null) { 3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, null, null); 3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 332a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } else if (!isCallerCreator(group)) { 333a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroupExt createGroup(SipProfile localProfile, 339845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 340845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan ISipSessionListener listener) throws SipException { 3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String key = localProfile.getUriString(); 3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipSessionGroupExt group = mSipGroups.get(key); 3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (group != null) { 344a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan if (!isCallerCreator(group)) { 345a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan throw new SipException("only creator can access the profile"); 346a072a6e3aa75c9bd038406a5067156463b58551bHung-ying Tyan } 347845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan group.setIncomingCallPendingIntent(incomingCallPendingIntent); 3489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.setListener(listener); 3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group = new SipSessionGroupExt(localProfile, 351845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan incomingCallPendingIntent, listener); 3529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroups.put(key, group); 3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan notifyProfileAdded(localProfile); 3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return group; 3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileAdded(SipProfile localProfile) { 3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile); 3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE); 3619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void notifyProfileRemoved(SipProfile localProfile) { 3669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile); 3679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE); 3689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString()); 3699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.sendBroadcast(intent); 3709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 372617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean anyOpenedToReceiveCalls() { 3739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 374617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (group.isOpenedToReceiveCalls()) return true; 3759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return false; 3779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void grabWifiLock() { 3809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiLock == null) { 3819abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ acquire wifi lock"); 3829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock = ((WifiManager) 3839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.WIFI_SERVICE)) 3849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan .createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 3859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock.acquire(); 38687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (!mConnected) startWifiScanner(); 3879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 3899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 3909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void releaseWifiLock() { 3919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiLock != null) { 3929abf73f1bde7b1617603c888650dbda9d6a7fddfHung-ying Tyan if (DEBUG) Log.d(TAG, "~~~~~~~~~~~~~~~~~~~~~ release wifi lock"); 3939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock.release(); 3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mWifiLock = null; 39587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang stopWifiScanner(); 39687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 39787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 39887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 39987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private synchronized void startWifiScanner() { 40087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mWifiScanProcess == null) { 40187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess = new WifiScanProcess(); 40287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 40387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess.start(); 40487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 40587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 40687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private synchronized void stopWifiScanner() { 40787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mWifiScanProcess != null) { 40887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiScanProcess.stop(); 4099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void onConnectivityChanged( 4139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String type, boolean connected) { 4149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onConnectivityChanged(): " 4159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + mNetworkType + (mConnected? " CONNECTED" : " DISCONNECTED") 4169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + " --> " + type + (connected? " CONNECTED" : " DISCONNECTED")); 4179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean sameType = type.equals(mNetworkType); 4199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!sameType && !connected) return; 4209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wasWifi = "WIFI".equalsIgnoreCase(mNetworkType); 4229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean isWifi = "WIFI".equalsIgnoreCase(type); 4239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wifiOff = (isWifi && !connected) || (wasWifi && !sameType); 4249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wifiOn = isWifi && connected; 4259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan boolean wasConnected = mConnected; 4289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mNetworkType = type; 4299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnected = connected; 4309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (wasConnected) { 4329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mLocalIp = null; 4339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.onConnectivityChanged(false); 4359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 4399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mLocalIp = determineLocalIp(); 440469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mKeepAliveInterval = -1; 4419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 4429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.onConnectivityChanged(true); 4439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 44487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (isWifi && (mWifiLock != null)) stopWifiScanner(); 445257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } else { 446257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.reset(); // in case there's a leak 447469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang stopPortMappingMeasurement(); 44887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (isWifi && (mWifiLock != null)) startWifiScanner(); 4499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (SipException e) { 4519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "onConnectivityChanged()", e); 4529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 455469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void stopPortMappingMeasurement() { 456469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (mIntervalMeasurementProcess != null) { 457469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess.stop(); 458469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess = null; 459469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 460469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 461469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 462469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void startPortMappingLifetimeMeasurement(SipSessionGroup group) { 463469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess = new IntervalMeasurementProcess(group); 464469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mIntervalMeasurementProcess.start(); 465469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 466469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 4679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private synchronized void addPendingSession(ISipSession session) { 4689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 4693f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan cleanUpPendingSessions(); 4709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mPendingSessions.put(session.getCallId(), session); 4713f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (DEBUG) Log.d(TAG, "#pending sess=" + mPendingSessions.size()); 4729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (RemoteException e) { 4739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // should not happen with a local call 4749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "addPendingSession()", e); 4759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 4779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 4783f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan private void cleanUpPendingSessions() throws RemoteException { 4793f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan Map.Entry<String, ISipSession>[] entries = 4803f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.entrySet().toArray( 4813f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan new Map.Entry[mPendingSessions.size()]); 4823f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan for (Map.Entry<String, ISipSession> entry : entries) { 4833f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan if (entry.getValue().getState() != SipSession.State.INCOMING_CALL) { 4843f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan mPendingSessions.remove(entry.getKey()); 4853f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4863f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4873f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan } 4883f4d44657ccad3ed02ed0e1354387b14b07dc011Hung-ying Tyan 489ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan private synchronized boolean callingSelf(SipSessionGroupExt ringingGroup, 490ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan SipSessionGroup.SipSessionImpl ringingSession) { 491ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan String callId = ringingSession.getCallId(); 492ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan for (SipSessionGroupExt group : mSipGroups.values()) { 493ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if ((group != ringingGroup) && group.containsSession(callId)) { 494ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (DEBUG) Log.d(TAG, "call self: " 495ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + ringingSession.getLocalProfile().getUriString() 496ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan + " -> " + group.getLocalProfile().getUriString()); 497ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return true; 498ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 499ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 500ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return false; 501ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 502ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 503ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class SipSessionGroupExt extends SipSessionAdapter { 5059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup mSipGroup; 506845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan private PendingIntent mIncomingCallPendingIntent; 507617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan private boolean mOpenedToReceiveCalls; 5089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private AutoRegistrationProcess mAutoRegistration = 5109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new AutoRegistrationProcess(); 5119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipSessionGroupExt(SipProfile localProfile, 513845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan PendingIntent incomingCallPendingIntent, 5149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ISipSessionListener listener) throws SipException { 5159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String password = localProfile.getPassword(); 5169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipProfile p = duplicate(localProfile); 5179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup = createSipSessionGroup(mLocalIp, p, password); 518845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = incomingCallPendingIntent; 5199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public SipProfile getLocalProfile() { 5239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfile(); 5249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 526ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan public boolean containsSession(String callId) { 527ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan return mSipGroup.containsSession(callId); 528ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan } 529ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan 5309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network connectivity is tricky because network can be disconnected 5319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // at any instant so need to deal with exceptions carefully even when 5329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // you think you are connected 5339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup createSipSessionGroup(String localIp, 5349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan SipProfile localProfile, String password) throws SipException { 5359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 536acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan return new SipSessionGroup(localIp, localProfile, password, 537acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan mMyWakeLock); 5389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 5399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network disconnected 5409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "createSipSessionGroup(): network disconnected?"); 5419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localIp != null) { 5429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return createSipSessionGroup(null, localProfile, password); 5439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 5449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // recursive 5456d9d99615a30de0675271553552c3c7b49311354Joe Onorato Log.wtf(TAG, "impossible! recursive!"); 5469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("createSipSessionGroup"); 5479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipProfile duplicate(SipProfile p) { 5529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 5539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return new SipProfile.Builder(p).setPassword("*").build(); 5549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Exception e) { 5559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.wtf(TAG, "duplicate()", e); 5569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("duplicate profile", e); 5579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 5619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.setListener(listener); 5629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 564845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void setIncomingCallPendingIntent(PendingIntent pIntent) { 565845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent = pIntent; 5669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void openToReceiveCalls() throws SipException { 569617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = true; 5709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mConnected) { 5719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.openToReceiveCalls(this); 5729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.start(mSipGroup); 5739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " openToReceiveCalls: " + getUri() + ": " 575845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 5769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onConnectivityChanged(boolean connected) 5799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throws SipException { 5809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.onConnectivityChanged(); 5819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 5829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan resetGroup(mLocalIp); 583617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan if (mOpenedToReceiveCalls) openToReceiveCalls(); 5849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 585617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan // close mSipGroup but remember mOpenedToReceiveCalls 5869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " close auto reg temporarily: " 587845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + getUri() + ": " + mIncomingCallPendingIntent); 5889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 5899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 5909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 5929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 5939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void resetGroup(String localIp) throws SipException { 5949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 5959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.reset(localIp); 5969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (IOException e) { 5979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // network disconnected 5989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "resetGroup(): network disconnected?"); 5999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (localIp != null) { 6009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan resetGroup(null); // reset w/o local IP 6019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 6029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // recursive 6039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.wtf(TAG, "impossible!"); 6049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan throw new RuntimeException("resetGroup"); 6059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void close() { 610617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan mOpenedToReceiveCalls = false; 6119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSipGroup.close(); 6129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mAutoRegistration.stop(); 6139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " close: " + getUri() + ": " 614845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + mIncomingCallPendingIntent); 6159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public ISipSession createSession(ISipSessionListener listener) { 6189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.createSession(listener); 6199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 622845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan public void onRinging(ISipSession s, SipProfile caller, 6239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String sessionDescription) { 624acedadc1967457ac2f8981c67f884fd8c0ee853cHung-ying Tyan if (DEBUGV) Log.d(TAG, "<<<<< onRinging()"); 625845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipSessionGroup.SipSessionImpl session = 626845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan (SipSessionGroup.SipSessionImpl) s; 6279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 6289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 629ed3c0fbbd5457f43ff72cec31b8ab0bb3f7a0047Hung-ying Tyan if (!isRegistered() || callingSelf(this, session)) { 6309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan session.endCall(); 6319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 6329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // send out incoming call broadcast 6359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan addPendingSession(session); 6369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Intent intent = SipManager.createIncomingCallBroadcast( 637845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.getCallId(), sessionDescription); 6389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": " 6399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + caller.getUri() + ": " + session.getCallId() 640845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan + " " + mIncomingCallPendingIntent); 641845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan mIncomingCallPendingIntent.send(mContext, 642845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan SipManager.INCOMING_CALL_RESULT_CODE, intent); 643845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan } catch (PendingIntent.CanceledException e) { 644845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan Log.w(TAG, "pendingIntent is canceled, drop incoming call"); 645845f7332f04864c5483b3e63da5db076fc7a888aHung-ying Tyan session.endCall(); 6469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 6519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onError(ISipSession session, int errorCode, 6529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 6539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "sip session error: " 6549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 6559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 657617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan public boolean isOpenedToReceiveCalls() { 658617479363dcafe01bfa1fa025e1d9d122864a0ceHung-ying Tyan return mOpenedToReceiveCalls; 6599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 6629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mAutoRegistration.isRegistered(); 6639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 6659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getUri() { 6669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mSipGroup.getLocalProfileUri(); 6679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 6699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 67087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private class WifiScanProcess implements Runnable { 67187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private static final String TAG = "\\WIFI_SCAN/"; 67287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private static final int INTERVAL = 60; 67387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private boolean mRunning = false; 67487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 67587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang private WifiManager mWifiManager; 67687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 67787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void start() { 67887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (mRunning) return; 67987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mRunning = true; 68087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mTimer.set(INTERVAL * 1000, this); 68187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 68287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 68387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang WifiScanProcess() { 68487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiManager = (WifiManager) 68587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mContext.getSystemService(Context.WIFI_SERVICE); 68687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 68787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 68887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void run() { 68987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang // scan and associate now 69087e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang if (DEBUGV) Log.v(TAG, "just wake up here for wifi scanning..."); 69187e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mWifiManager.startScanActive(); 69287e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 69387e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 69487e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang public void stop() { 69587e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mRunning = false; 69687e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang mTimer.cancel(this); 69787e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 69887e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang } 69987e304ce2e55588dfbec18406bf910e5adcfa3a4Chung-yih Wang 700469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private class IntervalMeasurementProcess extends SipSessionAdapter 701469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang implements Runnable { 702469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final String TAG = "\\INTERVAL/"; 703469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final int MAX_INTERVAL = 120; // seconds 704469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final int MIN_INTERVAL = SHORT_EXPIRY_TIME; 705469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private static final int PASS_THRESHOLD = 6; 706469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroupExt mGroup; 707469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private SipSessionGroup.SipSessionImpl mSession; 708469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private boolean mRunning; 709469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mMinInterval = 10; 710469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mMaxInterval = MAX_INTERVAL; 711469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mInterval = MAX_INTERVAL / 2; 712469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mPassCounter = 0; 7134cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private SipWakeupTimer mTimer = new SipWakeupTimer(mContext, mExecutor); 7144cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan // TODO: fix SipWakeupTimer so that we only use one instance of the timer 715469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 716469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public IntervalMeasurementProcess(SipSessionGroup group) { 717469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 718469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mGroup = new SipSessionGroupExt( 719469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang group.getLocalProfile(), null, null); 720469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mSession = (SipSessionGroup.SipSessionImpl) 721469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mGroup.createSession(this); 722469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } catch (Exception e) { 723469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang Log.w(TAG, "start interval measurement error: " + e); 724469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 725469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 726469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 727469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void start() { 728469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (mRunning) return; 729469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mRunning = true; 730469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.set(mInterval * 1000, this); 731469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (DEBUGV) Log.v(TAG, "start interval measurement"); 732469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang run(); 733469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 734469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 735469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void stop() { 736469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mRunning = false; 737469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.cancel(this); 738469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 739469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 740469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void restart() { 741469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.cancel(this); 742469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.set(mInterval * 1000, this); 743469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 744469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 745469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void calculateNewInterval() { 746469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (!mSession.isReRegisterRequired()) { 747469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (++mPassCounter != PASS_THRESHOLD) return; 748469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // update the interval, since the current interval is good to 749469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // keep the port mapping. 750469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mKeepAliveInterval = mMinInterval = mInterval; 751469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } else { 752469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // Since the rport is changed, shorten the interval. 753469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mSession.clearReRegisterRequired(); 754469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mMaxInterval = mInterval; 755469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 756469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if ((mMaxInterval - mMinInterval) < MIN_INTERVAL) { 757469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // update mKeepAliveInterval and stop measurement. 758469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang stop(); 759469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mKeepAliveInterval = mMinInterval; 760469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (DEBUGV) Log.v(TAG, "measured interval: " + mKeepAliveInterval); 761469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } else { 762469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // calculate the new interval and continue. 763469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mInterval = (mMaxInterval + mMinInterval) / 2; 764469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mPassCounter = 0; 765469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (DEBUGV) { 766469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang Log.v(TAG, " current interval: " + mKeepAliveInterval 767469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang + "test new interval: " + mInterval); 768469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 769469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang restart(); 770469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 771469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 772469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 773469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang public void run() { 774469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 775469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (!mRunning) return; 776469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang try { 777469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mSession.sendKeepAlive(); 778469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang calculateNewInterval(); 779469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } catch (Throwable t) { 780469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang stop(); 781469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang Log.w(TAG, "interval measurement error: " + t); 782469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 783469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 784469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 785469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 786469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 787d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan // KeepAliveProcess is controlled by AutoRegistrationProcess. 788257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // All methods will be invoked in sync with SipService.this. 7899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class KeepAliveProcess implements Runnable { 7909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final String TAG = "\\KEEPALIVE/"; 7919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private static final int INTERVAL = 10; 7929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 793d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 794469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private int mInterval = INTERVAL; 7959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 7969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) { 7979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = session; 7989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 7999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start() { 801d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (mRunning) return; 802d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 8039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(INTERVAL * 1000, this); 8049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 806469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang private void restart(int duration) { 807469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (DEBUG) Log.d(TAG, "Refresh NAT port mapping " + duration + "s later."); 808469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.cancel(this); 809469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mTimer.set(duration * 1000, this); 810469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 811469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 812d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan // timeout handler 8139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 8149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 815257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (!mRunning) return; 816d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 817257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (DEBUGV) Log.v(TAG, "~~~ keepalive: " 818257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan + mSession.getLocalProfile().getUriString()); 819257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan SipSessionGroup.SipSessionImpl session = mSession.duplicate(); 820257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 821257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan session.sendKeepAlive(); 822257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (session.isReRegisterRequired()) { 823257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Acquire wake lock for the registration process. The 824257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // lock will be released when registration is complete. 825257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 826257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 827257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 828469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (mKeepAliveInterval > mInterval) { 829469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang mInterval = mKeepAliveInterval; 830469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang restart(mInterval); 831469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 832257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 833257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan Log.w(TAG, "keepalive error: " + t); 8349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 839257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (DEBUGV && (mSession != null)) Log.v(TAG, "stop keepalive:" 840257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan + mSession.getLocalProfile().getUriString()); 841d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 842d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mSession = null; 8439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 8449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class AutoRegistrationProcess extends SipSessionAdapter 8489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan implements Runnable { 8499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionGroup.SipSessionImpl mSession; 8509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private SipSessionListenerProxy mProxy = new SipSessionListenerProxy(); 8519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private KeepAliveProcess mKeepAliveProcess; 8529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mBackoff = 1; 8539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mRegistered; 8549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private long mExpiryTime; 8559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int mErrorCode; 8569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mErrorMessage; 857d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean mRunning = false; 8589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String getAction() { 8609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return toString(); 8619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void start(SipSessionGroup group) { 864d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) { 865d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = true; 8669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff = 1; 8679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession = (SipSessionGroup.SipSessionImpl) 8689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan group.createSession(this); 8699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // return right away if no active network connection. 8709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mSession == null) return; 8719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 872469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang synchronized (SipService.this) { 873469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang if (isBehindNAT(mLocalIp) 874469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang && (mIntervalMeasurementProcess == null) 875469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang && (mKeepAliveInterval == -1)) { 876469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // Start keep-alive interval measurement, here we allow 877469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // the first profile only as the target service provider 878469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang // to measure the life time of NAT port mapping. 879469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang startPortMappingLifetimeMeasurement(group); 880469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 881469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang } 882469491e7807a46f31681d21c0ddae215f7891094Chung-yih Wang 8839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // start unregistration to clear up old registration at server 8849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // TODO: when rfc5626 is deployed, use reg-id and sip.instance 8859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // in registration to avoid adding duplicate entries to server 886257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 8879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.unregister(); 8889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "start AutoRegistrationProcess for " 8899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + mSession.getLocalProfile().getUriString()); 8909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 8929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 8939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void stop() { 894d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 895d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRunning = false; 896257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mSession); 897257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mSession != null) { 898257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.setListener(null); 899257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mConnected && mRegistered) mSession.unregister(); 900257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 901d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 9029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mKeepAliveProcess != null) { 9049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess.stop(); 9059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess = null; 9069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 908d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mRegistered = false; 909d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan setListener(mProxy.getListener()); 9109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void setListener(ISipSessionListener listener) { 9139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 9149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.setListener(listener); 9159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int state = (mSession == null) 9189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? SipSession.State.READY_TO_CALL 9199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan : mSession.getState(); 9209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == SipSession.State.REGISTERING) 9219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan || (state == SipSession.State.DEREGISTERING)) { 9229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(mSession); 9239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mRegistered) { 9249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = (int) 9259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (mExpiryTime - SystemClock.elapsedRealtime()); 9269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(mSession, duration); 9279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (mErrorCode != SipErrorCode.NO_ERROR) { 9289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mErrorCode == SipErrorCode.TIME_OUT) { 9299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(mSession); 9309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationFailed(mSession, mErrorCode, 9329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorMessage); 9339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 934d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mConnected) { 935d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 936d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.DATA_CONNECTION_LOST, 937d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "no data connection"); 938d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else if (!mRunning) { 939d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 940d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.CLIENT_ERROR, 941d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan "registration not running"); 942d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } else { 943d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(mSession, 944d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan SipErrorCode.IN_PROGRESS, 945d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan String.valueOf(state)); 9469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (Throwable t) { 9489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "setListener(): " + t); 9499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public boolean isRegistered() { 9549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return mRegistered; 9559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 957257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // timeout handler: re-register 9589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 959d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan synchronized (SipService.this) { 960d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (!mRunning) return; 961d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 962d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = SipErrorCode.NO_ERROR; 963d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = null; 964d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (DEBUG) Log.d(TAG, "~~~ registering"); 965257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan if (mConnected) { 966257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mSession); 967257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mSession.register(EXPIRY_TIME); 968257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 9699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean isBehindNAT(String address) { 9739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan try { 9749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan byte[] d = InetAddress.getByName(address).getAddress(); 9759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((d[0] == 10) || 9769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (((0x000000FF & ((int)d[0])) == 172) && 9779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ((0x000000F0 & ((int)d[1])) == 16)) || 9789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan (((0x000000FF & ((int)d[0])) == 192) && 9799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ((0x000000FF & ((int)d[1])) == 168))) { 9809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return true; 9819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } catch (UnknownHostException e) { 9839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.e(TAG, "isBehindAT()" + address, e); 9849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return false; 9869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void restart(int duration) { 9899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Refresh registration " + duration + "s later."); 9909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.cancel(this); 9919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.set(duration * 1000, this); 9929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 9939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 9949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private int backoffDuration() { 9959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan int duration = SHORT_EXPIRY_TIME * mBackoff; 9969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 3600) { 9979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = 3600; 9989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 9999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mBackoff *= 2; 10009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return duration; 10029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistering(ISipSession session) { 10069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistering(): " + session); 10079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1008d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1009d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistering(session); 10129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1015d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan private boolean notCurrentSession(ISipSession session) { 1016d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (session != mSession) { 1017d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan ((SipSessionGroup.SipSessionImpl) session).setListener(null); 1018257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 1019d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return true; 1020d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1021d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan return !mRunning; 1022d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan } 1023d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationDone(ISipSession session, int duration) { 10269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session); 10279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1028d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationDone(session, duration); 10319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration > 0) { 10339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.clearReRegisterRequired(); 10349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = SystemClock.elapsedRealtime() 10359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (duration * 1000); 10369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (!mRegistered) { 10389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = true; 10399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // allow some overlap to avoid call drop during renew 10409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration -= MIN_EXPIRY_TIME; 10419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (duration < MIN_EXPIRY_TIME) { 10429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan duration = MIN_EXPIRY_TIME; 10439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(duration); 10459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (isBehindNAT(mLocalIp) || 10479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mSession.getLocalProfile().getSendKeepAlive()) { 10489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mKeepAliveProcess == null) { 10499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess = 10509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan new KeepAliveProcess(mSession); 10519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess.start(); 10539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1055257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 10579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 10589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mExpiryTime = -1L; 10599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Refresh registration immediately"); 10609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan run(); 10619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationFailed(ISipSession session, int errorCode, 10679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String message) { 10689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": " 10699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + SipErrorCode.toString(errorCode) + ": " + message); 10709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1071d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 10729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1073fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan switch (errorCode) { 1074fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.INVALID_CREDENTIALS: 1075fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan case SipErrorCode.SERVER_UNREACHABLE: 1076fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan if (DEBUG) Log.d(TAG, " pause auto-registration"); 1077fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan stop(); 10780b88a073712b1510db7c636f89c4e19f0131449aHung-ying Tyan break; 1079fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan default: 1080fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 10819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1082d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 1083d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorCode = errorCode; 1084d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mErrorMessage = message; 1085d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan mProxy.onRegistrationFailed(session, errorCode, message); 1086257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 10879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 10899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 10909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 10919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void onRegistrationTimeout(ISipSession session) { 10929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session); 10939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 1094d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan if (notCurrentSession(session)) return; 1095d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan 10969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mErrorCode = SipErrorCode.TIME_OUT; 10979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mProxy.onRegistrationTimeout(session); 1098fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan restartLater(); 1099257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(session); 11009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1103fcc474636f42243cfce960158373b9c49636a556Hung-ying Tyan private void restartLater() { 11049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mRegistered = false; 11059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan restart(backoffDuration()); 11069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mKeepAliveProcess != null) { 11079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess.stop(); 11089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mKeepAliveProcess = null; 11099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class ConnectivityReceiver extends BroadcastReceiver { 11149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private Timer mTimer = new Timer(); 11159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private MyTimerTask mTask; 11169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 1118257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan public void onReceive(final Context context, final Intent intent) { 1119257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Run the handler in MyExecutor to be protected by wake lock 11204cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mExecutor.execute(new Runnable() { 1121257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan public void run() { 1122257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan onReceiveInternal(context, intent); 1123257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1124257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan }); 1125257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1126257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1127257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void onReceiveInternal(Context context, Intent intent) { 11289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String action = intent.getAction(); 11299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 11309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Bundle b = intent.getExtras(); 11319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (b != null) { 11329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo netInfo = (NetworkInfo) 11339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan b.get(ConnectivityManager.EXTRA_NETWORK_INFO); 11349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan String type = netInfo.getTypeName(); 11359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo.State state = netInfo.getState(); 11369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mWifiOnly && (netInfo.getType() != 11389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager.TYPE_WIFI)) { 11399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) { 11409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "Wifi only, other connectivity ignored: " 11419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + type); 11429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 11449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan NetworkInfo activeNetInfo = getActiveNetworkInfo(); 11479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) { 11489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (activeNetInfo != null) { 11499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "active network: " 11509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + activeNetInfo.getTypeName() 11519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + ((activeNetInfo.getState() == NetworkInfo.State.CONNECTED) 11529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ? " CONNECTED" : " DISCONNECTED")); 11539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 11549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.d(TAG, "active network: null"); 11559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((state == NetworkInfo.State.CONNECTED) 11589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan && (activeNetInfo != null) 11599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan && (activeNetInfo.getType() != netInfo.getType())) { 11609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "ignore connect event: " + type 11619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + ", active: " + activeNetInfo.getTypeName()); 11629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 11639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (state == NetworkInfo.State.CONNECTED) { 11669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert: CONNECTED " + type); 11679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onChanged(type, true); 11689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else if (state == NetworkInfo.State.DISCONNECTED) { 11699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert: DISCONNECTED " + type); 11709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onChanged(type, false); 11719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 11729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, "Connectivity alert not processed: " 11739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + state + " " + type); 11749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private NetworkInfo getActiveNetworkInfo() { 11809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan ConnectivityManager cm = (ConnectivityManager) 11819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 11829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return cm.getActiveNetworkInfo(); 11839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 11849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 11859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void onChanged(String type, boolean connected) { 11869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 11879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // When turning on WIFI, it needs some time for network 11889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // connectivity to get stabile so we defer good news (because 11899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // we want to skip the interim ones) but deliver bad news 11909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // immediately 11919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (connected) { 1192f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan if (mTask != null) { 1193f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mTask.cancel(); 1194f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mMyWakeLock.release(mTask); 1195f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan } 11969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask = new MyTimerTask(type, connected); 11979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTimer.schedule(mTask, 2 * 1000L); 1198257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // hold wakup lock so that we can finish changes before the 1199257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // device goes to sleep 1200257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(mTask); 12019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if ((mTask != null) && mTask.mNetworkType.equals(type)) { 12039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask.cancel(); 1204257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(mTask); 12059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onConnectivityChanged(type, false); 12079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private class MyTimerTask extends TimerTask { 12129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private boolean mConnected; 12139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private String mNetworkType; 12149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public MyTimerTask(String type, boolean connected) { 12169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mNetworkType = type; 12179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mConnected = connected; 12189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1220d8d3b15f408314ac88201eee3e401a35556ba669Hung-ying Tyan // timeout handler 12219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 12239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan // delegate to mExecutor 12244cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan mExecutor.execute(new Runnable() { 12259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void run() { 12269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan realRun(); 12279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan }); 12299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan private void realRun() { 12329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan synchronized (SipService.this) { 12339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (mTask != this) { 12349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, " unexpected task: " + mNetworkType 12359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (mConnected ? " CONNECTED" : "DISCONNECTED")); 1236f4a38e8e2f83402d2307edf67ef79b6f74990c8bHung-ying Tyan mMyWakeLock.release(this); 12379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan return; 12389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan mTask = null; 12409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (DEBUG) Log.d(TAG, " deliver change for " + mNetworkType 12419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan + (mConnected ? " CONNECTED" : "DISCONNECTED")); 12429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan onConnectivityChanged(mNetworkType, mConnected); 1243257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(this); 12449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 1249257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private static Looper createLooper() { 1250257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan HandlerThread thread = new HandlerThread("SipService.Executor"); 1251257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan thread.start(); 1252257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan return thread.getLooper(); 1253257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1254257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1255257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Executes immediate tasks in a single thread. 1256257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan // Hold/release wake lock for running tasks 12574cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan private class MyExecutor extends Handler implements Executor { 12589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan MyExecutor() { 12599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan super(createLooper()); 12609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12624cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan @Override 12634cbf2d2f94aaa094dda5b93357c93234ebccb120Hung-ying Tyan public void execute(Runnable task) { 1264257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.acquire(task); 12659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Message.obtain(this, 0/* don't care */, task).sendToTarget(); 12669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan 12689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan @Override 12699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan public void handleMessage(Message msg) { 12709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan if (msg.obj instanceof Runnable) { 1271257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan executeInternal((Runnable) msg.obj); 12729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } else { 12739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan Log.w(TAG, "can't handle msg: " + msg); 12749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 12759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan } 1276257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan 1277257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan private void executeInternal(Runnable task) { 1278257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan try { 1279257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan task.run(); 1280257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } catch (Throwable t) { 1281257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan Log.e(TAG, "run task: " + task, t); 1282257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } finally { 1283257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan mMyWakeLock.release(task); 1284257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1285257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 1286257c7e2b4193bff3793fcedd8b34b7fec2b1019bHung-ying Tyan } 12879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} 1288