diff options
author | Robert Greenwalt <rgreenwalt@google.com> | 2011-06-22 14:41:09 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-06-22 14:41:09 -0700 |
commit | 7af34ab8366b2fcddfea1ddc90a89746aaaab856 (patch) | |
tree | 14d77a2d2c020b3fe28c0e1858f3d84eb0e22590 /services/java/com/android/server/connectivity | |
parent | bd67cddd0d7b1f6e971228eeb883291875ba721f (diff) | |
parent | 5ff886e5319c519a6b644a999680ea651e208981 (diff) | |
download | frameworks_base-7af34ab8366b2fcddfea1ddc90a89746aaaab856.zip frameworks_base-7af34ab8366b2fcddfea1ddc90a89746aaaab856.tar.gz frameworks_base-7af34ab8366b2fcddfea1ddc90a89746aaaab856.tar.bz2 |
Merge "resolved conflicts for merge of 7a652bc8 to master"
Diffstat (limited to 'services/java/com/android/server/connectivity')
-rw-r--r-- | services/java/com/android/server/connectivity/Tethering.java | 251 |
1 files changed, 115 insertions, 136 deletions
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 946a270..911cac2 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -57,7 +57,9 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; import java.util.LinkedList; import java.util.Set; /** @@ -82,7 +84,15 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private String[] mTetherableUsbRegexs; private String[] mTetherableWifiRegexs; private String[] mTetherableBluetoothRegexs; - private String[] mUpstreamIfaceRegexs; + private Collection<Integer> mUpstreamIfaceTypes; + + private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE); + private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI); + private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN); + + // if we have to connect to mobile, what APN type should we use? Calculated by examining the + // upstream type list and the DUN_REQUIRED secure-setting + private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE; private INetworkManagementService mNMService; private Looper mLooper; @@ -112,9 +122,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4"; - // resampled each time we turn on tethering - used as cache for settings/config-val - private boolean mDunRequired; // configuration info - must use DUN apn on 3g - private StateMachine mTetherMasterSM; private Notification mTetheredNotification; @@ -159,7 +166,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { mDhcpRange = DHCP_DEFAULT_RANGE; } - mDunRequired = false; // resample when we turn on mTetherableUsbRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_usb_regexs); @@ -167,8 +173,15 @@ public class Tethering extends INetworkManagementEventObserver.Stub { com.android.internal.R.array.config_tether_wifi_regexs); mTetherableBluetoothRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_bluetooth_regexs); - mUpstreamIfaceRegexs = context.getResources().getStringArray( - com.android.internal.R.array.config_tether_upstream_regexs); + int ifaceTypes[] = context.getResources().getIntArray( + com.android.internal.R.array.config_tether_upstream_types); + mUpstreamIfaceTypes = new ArrayList(); + for (int i : ifaceTypes) { + mUpstreamIfaceTypes.add(new Integer(i)); + } + + // check if the upstream type list needs to be modified due to secure-settings + checkDunRequired(); // TODO - remove and rely on real notifications of the current iface mDnsServers = new String[2]; @@ -582,16 +595,44 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return mTetherableBluetoothRegexs; } - public String[] getUpstreamIfaceRegexs() { - return mUpstreamIfaceRegexs; + public int[] getUpstreamIfaceTypes() { + int values[] = new int[mUpstreamIfaceTypes.size()]; + Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); + for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { + values[i] = iterator.next(); + } + return values; } - public boolean isDunRequired() { - boolean defaultVal = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_tether_dun_required); - boolean result = (Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1); - return result; + public void checkDunRequired() { + int requiredApn = ((Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.TETHER_DUN_REQUIRED, 0) == 1) ? + ConnectivityManager.TYPE_MOBILE_DUN : + ConnectivityManager.TYPE_MOBILE_HIPRI); + if (mPreferredUpstreamMobileApn != requiredApn) { + if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { + while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { + mUpstreamIfaceTypes.remove(MOBILE_TYPE); + } + while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { + mUpstreamIfaceTypes.remove(HIPRI_TYPE); + } + if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { + mUpstreamIfaceTypes.add(DUN_TYPE); + } + } else { + while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { + mUpstreamIfaceTypes.remove(DUN_TYPE); + } + if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { + mUpstreamIfaceTypes.add(MOBILE_TYPE); + } + if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { + mUpstreamIfaceTypes.add(HIPRI_TYPE); + } + } + mPreferredUpstreamMobileApn = requiredApn; + } } public String[] getTetheredIfaces() { @@ -648,17 +689,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return retVal; } - public void handleTetherIfaceChange(String iface) { - // check if iface is white listed - for (String regex : mUpstreamIfaceRegexs) { - if (iface.matches(regex)) { - if (DEBUG) Log.d(TAG, "Tethering got Interface Change"); - mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface); - break; - } - } - } - class TetherInterfaceSM extends StateMachine { // notification from the master SM that it's not in tether mode static final int CMD_TETHER_MODE_DEAD = 1; @@ -1051,8 +1081,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { static final int CMD_CELL_CONNECTION_RENEW = 4; // we don't have a valid upstream conn, check again after a delay static final int CMD_RETRY_UPSTREAM = 5; - // received an indication that upstream interface has changed - static final int CMD_IFACE_CHANGED = 6; // This indicates what a timeout event relates to. A state that // sends itself a delayed timeout event and handles incoming timeout events @@ -1072,7 +1100,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private ArrayList mNotifyList; private int mCurrentConnectionSequence; - private boolean mMobileReserved = false; + private int mMobileApnReserved = ConnectivityManager.TYPE_NONE; private String mUpstreamIfaceName = null; @@ -1111,22 +1139,34 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public boolean processMessage(Message m) { return false; } - protected boolean turnOnMobileConnection() { + protected String enableString(int apnType) { + switch (apnType) { + case ConnectivityManager.TYPE_MOBILE_DUN: + return Phone.FEATURE_ENABLE_DUN_ALWAYS; + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + return Phone.FEATURE_ENABLE_HIPRI; + } + return null; + } + protected boolean turnOnUpstreamMobileConnection(int apnType) { boolean retValue = true; - if (mMobileReserved) return retValue; + if (apnType == ConnectivityManager.TYPE_NONE) return false; + if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection(); IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int result = Phone.APN_REQUEST_FAILED; + String enableString = enableString(apnType); + if (enableString == null) return false; try { result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, - (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS : - Phone.FEATURE_ENABLE_HIPRI), new Binder()); + enableString, new Binder()); } catch (Exception e) { } switch (result) { case Phone.APN_ALREADY_ACTIVE: case Phone.APN_REQUEST_STARTED: - mMobileReserved = true; + mMobileApnReserved = apnType; Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW); m.arg1 = ++mCurrentConnectionSequence; sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS); @@ -1139,18 +1179,17 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return retValue; } - protected boolean turnOffMobileConnection() { - if (mMobileReserved) { + protected boolean turnOffUpstreamMobileConnection() { + if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); try { cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, - (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS : - Phone.FEATURE_ENABLE_HIPRI)); + enableString(mMobileApnReserved)); } catch (Exception e) { return false; } - mMobileReserved = false; + mMobileApnReserved = ConnectivityManager.TYPE_NONE; } return true; } @@ -1196,108 +1235,55 @@ public class Tethering extends INetworkManagementEventObserver.Stub { transitionTo(mInitialState); return true; } - protected String findActiveUpstreamIface() { - // check for what iface we can use - if none found switch to error. + + protected void chooseUpstreamType(boolean tryCell) { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); + int upType = ConnectivityManager.TYPE_NONE; + String iface = null; - try { - LinkProperties defaultProp = cm.getActiveLinkProperties(); - if (defaultProp != null) { - String iface = defaultProp.getInterfaceName(); - for(String regex : mUpstreamIfaceRegexs) { - if (iface.matches(regex)) return iface; - } - } - } catch (RemoteException e) { } - - String[] ifaces = new String[0]; - try { - ifaces = mNMService.listInterfaces(); - } catch (Exception e) { - Log.e(TAG, "Error listing Interfaces", e); - return null; - } - - for (String regex : mUpstreamIfaceRegexs) { - for (String iface : ifaces) { - if (iface.matches(regex)) { - // verify it is active - InterfaceConfiguration ifcg = null; - try { - ifcg = mNMService.getInterfaceConfig(iface); - if (ifcg.isActive()) { - return iface; - } - } catch (Exception e) { - Log.e(TAG, "Error getting iface config", e); - // ignore - try next - continue; - } - } + for (Integer netType : mUpstreamIfaceTypes) { + NetworkInfo info = null; + try { + info = cm.getNetworkInfo(netType.intValue()); + } catch (RemoteException e) { } + if ((info != null) && info.isConnected()) { + upType = netType.intValue(); + break; } } - return null; - } - protected void chooseUpstreamType(boolean tryCell) { - // decide if the current upstream is good or not and if not - // do something about it (start up DUN if required or HiPri if not) - String iface = findActiveUpstreamIface(); - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); - mMobileReserved = false; if (DEBUG) { - Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired =" - + mDunRequired + ", iface=" + iface); + Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn =" + + mPreferredUpstreamMobileApn + ", got type=" + upType); } - if (iface != null) { - try { - if (mDunRequired) { - // check if Dun is on - we can use that - NetworkInfo info = cm.getNetworkInfo( - ConnectivityManager.TYPE_MOBILE_DUN); - if (info.isConnected()) { - if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface); - // even if we're already connected - it may be somebody else's - // refcount, so add our own - turnOnMobileConnection(); - } else { - // verify the iface is not the default mobile - can't use that! - info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); - if (info.isConnected()) { - iface = null; // can't accept this one - } - } - } else { - if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection"); - NetworkInfo info = cm.getNetworkInfo( - ConnectivityManager.TYPE_MOBILE_HIPRI); - if (info.isConnected()) { - if (DEBUG) Log.d(TAG, "yes - hipri in use"); - // even if we're already connected - it may be sombody else's - // refcount, so add our own - turnOnMobileConnection(); - } - } - } catch (RemoteException e) { - Log.e(TAG, "RemoteException calling ConnectivityManager", e); - iface = null; - } + + // if we're on DUN, put our own grab on it + if (upType == ConnectivityManager.TYPE_MOBILE_DUN || + upType == ConnectivityManager.TYPE_MOBILE_HIPRI) { + turnOnUpstreamMobileConnection(upType); } - // may have been set to null in the if above - if (iface == null ) { - boolean success = false; - if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) { - success = turnOnMobileConnection(); + + if (upType == ConnectivityManager.TYPE_NONE) { + boolean tryAgainLater = true; + if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) && + (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) { + // we think mobile should be coming up - don't set a retry + tryAgainLater = false; } - if (!success) { - // wait for things to settle and retry + if (tryAgainLater) { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); } + } else { + LinkProperties linkProperties = null; + try { + linkProperties = cm.getLinkProperties(upType); + } catch (RemoteException e) { } + if (linkProperties != null) iface = linkProperties.getInterfaceName(); } notifyTetheredOfNewUpstreamIface(iface); } + protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); mUpstreamIfaceName = ifaceName; @@ -1312,7 +1298,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { class InitialState extends TetherMasterUtilState { @Override public void enter() { - mMobileReserved = false; } @Override public boolean processMessage(Message message) { @@ -1320,7 +1305,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { boolean retValue = true; switch (message.what) { case CMD_TETHER_MODE_REQUESTED: - mDunRequired = isDunRequired(); + checkDunRequired(); TetherInterfaceSM who = (TetherInterfaceSM)message.obj; if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString()); mNotifyList.add(who); @@ -1354,7 +1339,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } @Override public void exit() { - turnOffMobileConnection(); + turnOffUpstreamMobileConnection(); notifyTetheredOfNewUpstreamIface(null); } @Override @@ -1392,19 +1377,13 @@ public class Tethering extends INetworkManagementEventObserver.Stub { Log.d(TAG, "renewing mobile connection - requeuing for another " + CELL_CONNECTION_RENEW_MS + "ms"); } - mMobileReserved = false; // need to renew it - turnOnMobileConnection(); + turnOnUpstreamMobileConnection(mMobileApnReserved); } break; case CMD_RETRY_UPSTREAM: chooseUpstreamType(mTryCell); mTryCell = !mTryCell; break; - case CMD_IFACE_CHANGED: - String iface = (String)message.obj; - if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface); - notifyTetheredOfNewUpstreamIface(iface); - break; default: retValue = false; break; |