Loading core/res/res/values/config.xml +9 −1 Original line number Diff line number Diff line Loading @@ -83,9 +83,17 @@ </string-array> <!-- Dhcp range (min, max) to use for tethering purposes --> <string-array name="config_tether_dhcp_range"> <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> <!-- Regex array of allowable upstream ifaces for tethering - for example if you want tethering on your a new interface called "foo2" add "foo\\d" here --> <string-array translatable="false" name="config_tether_upstream_regexs"> </string-array> <!-- Boolean indicating if we require the use of DUN on mobile for tethering --> <bool translatable="false" name="config_tether_dun_required">true</bool> <!-- Flag indicating whether the keyguard should be bypassed when the slider is open. This can be set or unset depending how easily the slider can be opened (for example, in a pocket or purse). --> Loading services/java/com/android/server/ConnectivityService.java +10 −3 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { private Tethering mTethering; private boolean mTetheringConfigValid = false; /** * Sometimes we want to refer to the individual network state Loading Loading @@ -320,6 +321,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } mTethering = new Tethering(mContext); mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) || !mTethering.isDunRequired()) && (mTethering.getTetherableUsbRegexs().length != 0 || mTethering.getTetherableWifiRegexs().length != 0) && mTethering.getUpstreamIfaceRegexs().length != 0); } Loading Loading @@ -1498,8 +1505,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { public boolean isTetheringSupported() { enforceTetherAccessPermission(); int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); return ((Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0) && (mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null)); boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); return tetherEnabledInSettings && mTetheringConfigValid; } } services/java/com/android/server/connectivity/Tethering.java +126 −121 Original line number Diff line number Diff line Loading @@ -66,10 +66,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private final String TAG = "Tethering"; private boolean mPlaySounds = false; private boolean mBooted = false; //used to remember if we got connected before boot finished private boolean mDeferedUsbConnection = false; // TODO - remove both of these - should be part of interface inspection/selection stuff private String[] mTetherableUsbRegexs; private String[] mTetherableWifiRegexs; private String[] mUpstreamIfaceRegexs; private HashMap<String, TetherInterfaceSM> mIfaces; Loading @@ -87,6 +91,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; private static final String DNS_DEFAULT_SERVER2 = "4.2.2.2"; private boolean mDunRequired; private boolean mUseHiPri; private String mUpstreamIfaceName; HierarchicalStateMachine mTetherMasterSM; Loading Loading @@ -114,6 +120,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_BOOT_COMPLETED); mStateReceiver = new StateReceiver(); mContext.registerReceiver(mStateReceiver, filter); Loading @@ -129,17 +136,20 @@ public class Tethering extends INetworkManagementEventObserver.Stub { tmp[1] = new String(""); mDhcpRange = tmp; } mDunRequired = context.getResources().getBoolean( com.android.internal.R.bool.config_tether_dun_required); mTetherableUsbRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_usb_regexs); mTetherableWifiRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_wifi_regexs); mUpstreamIfaceRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_upstream_regexs); // TODO - remove and rely on real notifications of the current iface mDnsServers = new String[2]; mDnsServers[0] = DNS_DEFAULT_SERVER1; mDnsServers[1] = DNS_DEFAULT_SERVER2; mUpstreamIfaceName = "rmnet0"; } public void interfaceLinkStatusChanged(String iface, boolean link) { Loading Loading @@ -426,12 +436,18 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { boolean usbConnected = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == BatteryManager.BATTERY_PLUGGED_USB); if (mBooted) { Tethering.this.enableUsbIfaces(usbConnected); // add or remove them } else { mDeferedUsbConnection = usbConnected; } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { NetworkInfo info = service.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_DUN); int netType = (mUseHiPri ? ConnectivityManager.TYPE_MOBILE_HIPRI: ConnectivityManager.TYPE_MOBILE_DUN); NetworkInfo info = service.getNetworkInfo(netType); int msg; if (info != null && info.isConnected() == true) { msg = TetherMasterSM.CMD_CELL_DUN_ENABLED; Loading @@ -440,6 +456,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } mTetherMasterSM.sendMessage(mTetherMasterSM.obtainMessage(msg)); } catch (RemoteException e) {} } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { mBooted = true; if (mDeferedUsbConnection) { Tethering.this.enableUsbIfaces(true); } } } } Loading Loading @@ -523,8 +544,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); // TODO - clean this up - maybe a better regex? ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running ",""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running",""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); } service.setInterfaceConfig(iface, ifcg); } Loading @@ -539,89 +559,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return true; } private void handleTtyConnect() { Log.d(TAG, "handleTtyConnect"); // for each of the available Tty not already supported by a ppp session, // create a ppp session // TODO - this should be data-driven rather than hard coded. String[] allowedTtys = new String[1]; allowedTtys[0] = new String("ttyGS0"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] availableTtys; try { availableTtys = service.listTtys(); } catch (RemoteException e) { Log.e(TAG, "error listing Ttys :" + e); return; } for (String tty : availableTtys) { for (String pattern : allowedTtys) { if (tty.matches(pattern)) { synchronized (this) { if (!mActiveTtys.contains(tty)) { // TODO - don't hardcode this try { // local, remote, dns service.attachPppd(tty, "169.254.1.128", "169.254.1.1", "169.254.1.128", "0.0.0.0"); } catch (Exception e) { Log.e(TAG, "error calling attachPppd: " + e); return; } Log.d(TAG, "started Pppd on tty " + tty); mActiveTtys.add(tty); // TODO - remove this after we detect the new iface interfaceAdded("ppp0"); } } } } } } private synchronized void handleTtyDisconnect() { Log.d(TAG, "handleTtyDisconnect"); // TODO - this should be data-driven rather than hard coded. String[] allowedTtys = new String[1]; allowedTtys[0] = new String("ttyGS0"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] availableTtys; try { availableTtys = service.listTtys(); } catch (RemoteException e) { Log.e(TAG, "error listing Ttys :" + e); return; } for (String tty : availableTtys) { for (String pattern : allowedTtys) { if (tty.matches(pattern)) { synchronized (this) { if (mActiveTtys.contains(tty)) { try { service.detachPppd(tty); } catch (Exception e) { Log.e(TAG, "error calling detachPppd on " + tty + " :" + e); } mActiveTtys.remove(tty); // TODO - remove this after we detect the new iface interfaceRemoved("ppp0"); return; } } } } } } public String[] getTetherableUsbRegexs() { return mTetherableUsbRegexs; } Loading @@ -630,6 +567,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return mTetherableWifiRegexs; } public String[] getUpstreamIfaceRegexs() { return mUpstreamIfaceRegexs; } public boolean isDunRequired() { return mDunRequired; } public String[] getTetheredIfaces() { ArrayList<String> list = new ArrayList<String>(); synchronized (mIfaces) { Loading Loading @@ -1217,7 +1162,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { int retValue = Phone.APN_REQUEST_FAILED; try { retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_DUN, new Binder()); (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN), new Binder()); } catch (Exception e) { } return retValue; Loading @@ -1228,7 +1174,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IConnectivityManager.Stub.asInterface(b); try { service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_DUN); (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN)); } catch (Exception e) { return false; } Loading Loading @@ -1278,9 +1224,45 @@ public class Tethering extends INetworkManagementEventObserver.Stub { transitionTo(mInitialState); return true; } public String findActiveUpstreamIface() { // check for what iface we can use - if none found switch to error. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] ifaces = new String[0]; try { ifaces = service.listInterfaces(); } catch (Exception e) { Log.e(TAG, "Error listing Interfaces :" + e); return null; } for (String iface : ifaces) { for (String regex : mUpstreamIfaceRegexs) { if (iface.matches(regex)) { // verify it is up! InterfaceConfiguration ifcg = null; try { ifcg = service.getInterfaceConfig(iface); } catch (Exception e) { Log.e(TAG, "Error getting iface config :" + e); // ignore - try next continue; } if (ifcg.interfaceFlags.contains("up")) { return iface; } } } } return null; } } class InitialState extends TetherMasterUtilState { @Override public void enter() { mUseHiPri = false; } @Override public boolean processMessage(Message message) { Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); Loading Loading @@ -1313,6 +1295,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { class CellDunRequestedState extends TetherMasterUtilState { @Override public void enter() { mUseHiPri = (findActiveUpstreamIface() == null && !mDunRequired); if (mDunRequired || mUseHiPri) { ++mSequenceNumber; int result = turnOnMobileDun(); switch (result) { Loading @@ -1334,7 +1318,12 @@ public class Tethering extends INetworkManagementEventObserver.Stub { sendMessageDelayed(m, CELL_DUN_TIMEOUT_MS); break; default: Log.e(TAG, "Unknown return value from startUsingNetworkFeature " + result); Log.e(TAG, "Unknown return value from startUsingNetworkFeature " + result); } } else { Log.d(TAG, "no Dun Required. Skipping to Active"); sendMessage(obtainMessage(CMD_CELL_DUN_ENABLED)); } } Loading @@ -1353,7 +1342,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } transitionTo(mInitialState); } } Loading Loading @@ -1399,7 +1390,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } transitionTo(mInitialState); } } Loading @@ -1424,13 +1417,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { class TetherModeAliveState extends TetherMasterUtilState { @Override public void enter() { if (mDunRequired || mUseHiPri) { Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms"); sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS); } mUpstreamIfaceName = findActiveUpstreamIface(); if (mUpstreamIfaceName == null) { Log.d(TAG, "Erroring our of tether - no upstream ifaces available"); sendMessage(obtainMessage(CMD_CELL_DUN_DISABLED)); } else { for (Object o : mNotifyList) { TetherInterfaceSM sm = (TetherInterfaceSM)o; sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE)); } } } @Override public boolean processMessage(Message message) { Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); Loading @@ -1447,8 +1448,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } turnOffMasterTetherSettings(); // transitions appropriately mUpstreamIfaceName = null; } } break; Loading @@ -1461,6 +1465,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { TetherInterfaceSM.CMD_TETHER_MODE_DEAD)); } turnOffMasterTetherSettings(); // transitions appropriately mUpstreamIfaceName = null; break; case CMD_CELL_DUN_RENEW: Log.d(TAG, "renewing dun connection - requeuing for another " + Loading Loading
core/res/res/values/config.xml +9 −1 Original line number Diff line number Diff line Loading @@ -83,9 +83,17 @@ </string-array> <!-- Dhcp range (min, max) to use for tethering purposes --> <string-array name="config_tether_dhcp_range"> <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> <!-- Regex array of allowable upstream ifaces for tethering - for example if you want tethering on your a new interface called "foo2" add "foo\\d" here --> <string-array translatable="false" name="config_tether_upstream_regexs"> </string-array> <!-- Boolean indicating if we require the use of DUN on mobile for tethering --> <bool translatable="false" name="config_tether_dun_required">true</bool> <!-- Flag indicating whether the keyguard should be bypassed when the slider is open. This can be set or unset depending how easily the slider can be opened (for example, in a pocket or purse). --> Loading
services/java/com/android/server/ConnectivityService.java +10 −3 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { private Tethering mTethering; private boolean mTetheringConfigValid = false; /** * Sometimes we want to refer to the individual network state Loading Loading @@ -320,6 +321,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } mTethering = new Tethering(mContext); mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) || !mTethering.isDunRequired()) && (mTethering.getTetherableUsbRegexs().length != 0 || mTethering.getTetherableWifiRegexs().length != 0) && mTethering.getUpstreamIfaceRegexs().length != 0); } Loading Loading @@ -1498,8 +1505,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { public boolean isTetheringSupported() { enforceTetherAccessPermission(); int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); return ((Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0) && (mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null)); boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); return tetherEnabledInSettings && mTetheringConfigValid; } }
services/java/com/android/server/connectivity/Tethering.java +126 −121 Original line number Diff line number Diff line Loading @@ -66,10 +66,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private final String TAG = "Tethering"; private boolean mPlaySounds = false; private boolean mBooted = false; //used to remember if we got connected before boot finished private boolean mDeferedUsbConnection = false; // TODO - remove both of these - should be part of interface inspection/selection stuff private String[] mTetherableUsbRegexs; private String[] mTetherableWifiRegexs; private String[] mUpstreamIfaceRegexs; private HashMap<String, TetherInterfaceSM> mIfaces; Loading @@ -87,6 +91,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; private static final String DNS_DEFAULT_SERVER2 = "4.2.2.2"; private boolean mDunRequired; private boolean mUseHiPri; private String mUpstreamIfaceName; HierarchicalStateMachine mTetherMasterSM; Loading Loading @@ -114,6 +120,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_BOOT_COMPLETED); mStateReceiver = new StateReceiver(); mContext.registerReceiver(mStateReceiver, filter); Loading @@ -129,17 +136,20 @@ public class Tethering extends INetworkManagementEventObserver.Stub { tmp[1] = new String(""); mDhcpRange = tmp; } mDunRequired = context.getResources().getBoolean( com.android.internal.R.bool.config_tether_dun_required); mTetherableUsbRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_usb_regexs); mTetherableWifiRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_wifi_regexs); mUpstreamIfaceRegexs = context.getResources().getStringArray( com.android.internal.R.array.config_tether_upstream_regexs); // TODO - remove and rely on real notifications of the current iface mDnsServers = new String[2]; mDnsServers[0] = DNS_DEFAULT_SERVER1; mDnsServers[1] = DNS_DEFAULT_SERVER2; mUpstreamIfaceName = "rmnet0"; } public void interfaceLinkStatusChanged(String iface, boolean link) { Loading Loading @@ -426,12 +436,18 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { boolean usbConnected = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == BatteryManager.BATTERY_PLUGGED_USB); if (mBooted) { Tethering.this.enableUsbIfaces(usbConnected); // add or remove them } else { mDeferedUsbConnection = usbConnected; } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { NetworkInfo info = service.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_DUN); int netType = (mUseHiPri ? ConnectivityManager.TYPE_MOBILE_HIPRI: ConnectivityManager.TYPE_MOBILE_DUN); NetworkInfo info = service.getNetworkInfo(netType); int msg; if (info != null && info.isConnected() == true) { msg = TetherMasterSM.CMD_CELL_DUN_ENABLED; Loading @@ -440,6 +456,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } mTetherMasterSM.sendMessage(mTetherMasterSM.obtainMessage(msg)); } catch (RemoteException e) {} } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { mBooted = true; if (mDeferedUsbConnection) { Tethering.this.enableUsbIfaces(true); } } } } Loading Loading @@ -523,8 +544,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); // TODO - clean this up - maybe a better regex? ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running ",""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running",""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); } service.setInterfaceConfig(iface, ifcg); } Loading @@ -539,89 +559,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return true; } private void handleTtyConnect() { Log.d(TAG, "handleTtyConnect"); // for each of the available Tty not already supported by a ppp session, // create a ppp session // TODO - this should be data-driven rather than hard coded. String[] allowedTtys = new String[1]; allowedTtys[0] = new String("ttyGS0"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] availableTtys; try { availableTtys = service.listTtys(); } catch (RemoteException e) { Log.e(TAG, "error listing Ttys :" + e); return; } for (String tty : availableTtys) { for (String pattern : allowedTtys) { if (tty.matches(pattern)) { synchronized (this) { if (!mActiveTtys.contains(tty)) { // TODO - don't hardcode this try { // local, remote, dns service.attachPppd(tty, "169.254.1.128", "169.254.1.1", "169.254.1.128", "0.0.0.0"); } catch (Exception e) { Log.e(TAG, "error calling attachPppd: " + e); return; } Log.d(TAG, "started Pppd on tty " + tty); mActiveTtys.add(tty); // TODO - remove this after we detect the new iface interfaceAdded("ppp0"); } } } } } } private synchronized void handleTtyDisconnect() { Log.d(TAG, "handleTtyDisconnect"); // TODO - this should be data-driven rather than hard coded. String[] allowedTtys = new String[1]; allowedTtys[0] = new String("ttyGS0"); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] availableTtys; try { availableTtys = service.listTtys(); } catch (RemoteException e) { Log.e(TAG, "error listing Ttys :" + e); return; } for (String tty : availableTtys) { for (String pattern : allowedTtys) { if (tty.matches(pattern)) { synchronized (this) { if (mActiveTtys.contains(tty)) { try { service.detachPppd(tty); } catch (Exception e) { Log.e(TAG, "error calling detachPppd on " + tty + " :" + e); } mActiveTtys.remove(tty); // TODO - remove this after we detect the new iface interfaceRemoved("ppp0"); return; } } } } } } public String[] getTetherableUsbRegexs() { return mTetherableUsbRegexs; } Loading @@ -630,6 +567,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return mTetherableWifiRegexs; } public String[] getUpstreamIfaceRegexs() { return mUpstreamIfaceRegexs; } public boolean isDunRequired() { return mDunRequired; } public String[] getTetheredIfaces() { ArrayList<String> list = new ArrayList<String>(); synchronized (mIfaces) { Loading Loading @@ -1217,7 +1162,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { int retValue = Phone.APN_REQUEST_FAILED; try { retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_DUN, new Binder()); (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN), new Binder()); } catch (Exception e) { } return retValue; Loading @@ -1228,7 +1174,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { IConnectivityManager.Stub.asInterface(b); try { service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_DUN); (mUseHiPri ? Phone.FEATURE_ENABLE_HIPRI : Phone.FEATURE_ENABLE_DUN)); } catch (Exception e) { return false; } Loading Loading @@ -1278,9 +1224,45 @@ public class Tethering extends INetworkManagementEventObserver.Stub { transitionTo(mInitialState); return true; } public String findActiveUpstreamIface() { // check for what iface we can use - if none found switch to error. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); String[] ifaces = new String[0]; try { ifaces = service.listInterfaces(); } catch (Exception e) { Log.e(TAG, "Error listing Interfaces :" + e); return null; } for (String iface : ifaces) { for (String regex : mUpstreamIfaceRegexs) { if (iface.matches(regex)) { // verify it is up! InterfaceConfiguration ifcg = null; try { ifcg = service.getInterfaceConfig(iface); } catch (Exception e) { Log.e(TAG, "Error getting iface config :" + e); // ignore - try next continue; } if (ifcg.interfaceFlags.contains("up")) { return iface; } } } } return null; } } class InitialState extends TetherMasterUtilState { @Override public void enter() { mUseHiPri = false; } @Override public boolean processMessage(Message message) { Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); Loading Loading @@ -1313,6 +1295,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { class CellDunRequestedState extends TetherMasterUtilState { @Override public void enter() { mUseHiPri = (findActiveUpstreamIface() == null && !mDunRequired); if (mDunRequired || mUseHiPri) { ++mSequenceNumber; int result = turnOnMobileDun(); switch (result) { Loading @@ -1334,7 +1318,12 @@ public class Tethering extends INetworkManagementEventObserver.Stub { sendMessageDelayed(m, CELL_DUN_TIMEOUT_MS); break; default: Log.e(TAG, "Unknown return value from startUsingNetworkFeature " + result); Log.e(TAG, "Unknown return value from startUsingNetworkFeature " + result); } } else { Log.d(TAG, "no Dun Required. Skipping to Active"); sendMessage(obtainMessage(CMD_CELL_DUN_ENABLED)); } } Loading @@ -1353,7 +1342,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } transitionTo(mInitialState); } } Loading Loading @@ -1399,7 +1390,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } transitionTo(mInitialState); } } Loading @@ -1424,13 +1417,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { class TetherModeAliveState extends TetherMasterUtilState { @Override public void enter() { if (mDunRequired || mUseHiPri) { Log.d(TAG, "renewing Dun in " + CELL_DUN_RENEW_MS + "ms"); sendMessageDelayed(obtainMessage(CMD_CELL_DUN_RENEW), CELL_DUN_RENEW_MS); } mUpstreamIfaceName = findActiveUpstreamIface(); if (mUpstreamIfaceName == null) { Log.d(TAG, "Erroring our of tether - no upstream ifaces available"); sendMessage(obtainMessage(CMD_CELL_DUN_DISABLED)); } else { for (Object o : mNotifyList) { TetherInterfaceSM sm = (TetherInterfaceSM)o; sm.sendMessage(sm.obtainMessage(TetherInterfaceSM.CMD_TETHER_MODE_ALIVE)); } } } @Override public boolean processMessage(Message message) { Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); Loading @@ -1447,8 +1448,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (index != -1) { mNotifyList.remove(index); if (mNotifyList.isEmpty()) { if (mDunRequired || mUseHiPri) { turnOffMobileDun(); } turnOffMasterTetherSettings(); // transitions appropriately mUpstreamIfaceName = null; } } break; Loading @@ -1461,6 +1465,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { TetherInterfaceSM.CMD_TETHER_MODE_DEAD)); } turnOffMasterTetherSettings(); // transitions appropriately mUpstreamIfaceName = null; break; case CMD_CELL_DUN_RENEW: Log.d(TAG, "renewing dun connection - requeuing for another " + Loading