Loading core/java/android/server/BluetoothEventLoop.java +11 −6 Original line number Diff line number Diff line Loading @@ -463,9 +463,14 @@ class BluetoothEventLoop { } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Connected")) { int state = propValues[1].equals("true") ? BluetoothInputDevice.STATE_CONNECTED : BluetoothInputDevice.STATE_DISCONNECTED; mBluetoothService.handlePanDeviceStateChange(device, state); if (propValues[1].equals("false")) { mBluetoothService.handlePanDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED); } } else if (name.equals("Interface")) { String iface = propValues[1]; mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothInputDevice.STATE_CONNECTED); } } Loading Loading @@ -662,7 +667,7 @@ class BluetoothEventLoop { Log.i(TAG, "Rejecting incoming HID connection from " + address); } } else if (BluetoothUuid.isBnep(uuid) || BluetoothUuid.isNap(uuid) && mBluetoothService.isTetheringOn()){ mBluetoothService.allowIncomingTethering()){ authorized = true; } else { Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address); Loading Loading @@ -796,9 +801,9 @@ class BluetoothEventLoop { mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED); } private void onNetworkDeviceConnected(String address, int destUuid) { private void onNetworkDeviceConnected(String address, String iface, int destUuid) { BluetoothDevice device = mAdapter.getRemoteDevice(address); mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTED); mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED); } private void onRestartRequired() { Loading core/java/android/server/BluetoothService.java +112 −69 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources.NotFoundException; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; import android.os.Binder; Loading Loading @@ -114,7 +115,10 @@ public class BluetoothService extends IBluetooth.Stub { private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private ArrayList<String> mBluetoothIfaceAddresses; private static final String BLUETOOTH_NEAR_IFACE_ADDR_PREFIX= "192.168.44."; private int mMaxPanDevices; private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1"; private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5; private static final String BLUETOOTH_NETMASK = "255.255.255.0"; // The timeout used to sent the UUIDs Intent Loading Loading @@ -144,9 +148,10 @@ public class BluetoothService extends IBluetooth.Stub { private BluetoothA2dpService mA2dpService; private final HashMap<BluetoothDevice, Integer> mInputDevices; private final HashMap<BluetoothDevice, Integer> mPanDevices; private final HashMap<BluetoothDevice, Pair<Integer, String>> mPanDevices; private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; private static String mDockAddress; private String mDockPin; Loading Loading @@ -211,10 +216,12 @@ public class BluetoothService extends IBluetooth.Stub { mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID); // Can tether to up to 7 devices mBluetoothIfaceAddresses = new ArrayList<String>(BluetoothPan.MAX_CONNECTIONS); for (int i=1; i <= BluetoothPan.MAX_CONNECTIONS; i++) { mBluetoothIfaceAddresses.add(BLUETOOTH_NEAR_IFACE_ADDR_PREFIX + i); mBluetoothIfaceAddresses = new ArrayList<String>(); try { mMaxPanDevices = context.getResources().getInteger( com.android.internal.R.integer.config_max_pan_devices); } catch (NotFoundException e) { mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS; } mHfpProfileState.start(); Loading @@ -227,7 +234,7 @@ public class BluetoothService extends IBluetooth.Stub { filter.addAction(Intent.ACTION_DOCK_EVENT); mContext.registerReceiver(mReceiver, filter); mInputDevices = new HashMap<BluetoothDevice, Integer>(); mPanDevices = new HashMap<BluetoothDevice, Integer>(); mPanDevices = new HashMap<BluetoothDevice, Pair<Integer, String>>(); } public static synchronized String readDockBluetoothAddress() { Loading Loading @@ -1313,6 +1320,12 @@ public class BluetoothService extends IBluetooth.Stub { return mTetheringOn; } /*package*/ synchronized boolean allowIncomingTethering() { if (isTetheringOn() && getConnectedPanDevices().length < mMaxPanDevices) return true; return false; } private BroadcastReceiver mTetheringReceiver = null; public synchronized void setBluetoothTethering(boolean value) { Loading Loading @@ -1342,10 +1355,11 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized int getPanDeviceState(BluetoothDevice device) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (mPanDevices.get(device) == null) { Pair<Integer, String> panDevice = mPanDevices.get(device); if (panDevice == null) { return BluetoothPan.STATE_DISCONNECTED; } return mPanDevices.get(device); return panDevice.first; } public synchronized boolean connectPanDevice(BluetoothDevice device) { Loading @@ -1359,8 +1373,8 @@ public class BluetoothService extends IBluetooth.Stub { } int connectedCount = 0; for (BluetoothDevice BTdevice: mPanDevices.keySet()) { if (getPanDeviceState(BTdevice) == BluetoothPan.STATE_CONNECTED) { for (BluetoothDevice panDevice: mPanDevices.keySet()) { if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) { connectedCount ++; } } Loading Loading @@ -1419,21 +1433,33 @@ public class BluetoothService extends IBluetooth.Stub { return disconnectPanDeviceNative(objectPath); } /*package*/ void handlePanDeviceStateChange(BluetoothDevice device, int state) { /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, String iface, int state) { int prevState; String ifaceAddr = null; if (mPanDevices.get(device) == null) { prevState = BluetoothPan.STATE_DISCONNECTED; } else { prevState = mPanDevices.get(device); prevState = mPanDevices.get(device).first; ifaceAddr = mPanDevices.get(device).second; } if (prevState == state) return; mPanDevices.put(device, state); if (state == BluetoothPan.STATE_CONNECTED) { updateTetherState(true); ifaceAddr = enableTethering(iface); if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface"); } else if (state == BluetoothPan.STATE_DISCONNECTED) { if (ifaceAddr != null) { mBluetoothIfaceAddresses.remove(ifaceAddr); ifaceAddr = null; } } Pair<Integer, String> value = new Pair<Integer, String>(state, ifaceAddr); mPanDevices.put(device, value); Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState); Loading @@ -1441,12 +1467,35 @@ public class BluetoothService extends IBluetooth.Stub { mContext.sendBroadcast(intent, BLUETOOTH_PERM); if (DBG) log("Pan Device state : device: " + device + " State:" + prevState + "->" + state); } /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, int state) { handlePanDeviceStateChange(device, null, state); } private String createNewTetheringAddressLocked() { if (getConnectedPanDevices().length == mMaxPanDevices) { log("Max PAN device connections reached"); return null; } String address = BLUETOOTH_IFACE_ADDR_START; while (true) { if (mBluetoothIfaceAddresses.contains(address)) { String[] addr = address.split("\\."); Integer newIp = Integer.parseInt(addr[2]) + 1; address = address.replace(addr[2], newIp.toString()); } else { break; } } mBluetoothIfaceAddresses.add(address); return address; } // configured when we start tethering and unconfig'd on error or conclusion private boolean updateTetherState(boolean enabled) { Log.d(TAG, "configureBluetoothIface(" + enabled + ")"); // configured when we start tethering private synchronized String enableTethering(String iface) { log("updateTetherState:" + iface); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); Loading @@ -1455,64 +1504,58 @@ public class BluetoothService extends IBluetooth.Stub { String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); // bring toggle the interfaces String[] ifaces = new String[0]; String[] currentIfaces = new String[0]; try { ifaces = service.listInterfaces(); currentIfaces = service.listInterfaces(); } catch (Exception e) { Log.e(TAG, "Error listing Interfaces :" + e); return false; return null; } boolean found = false; for (String currIface: currentIfaces) { if (currIface.equals(iface)) { found = true; break; } } ArrayList<String> ifaceAddresses = (ArrayList<String>) mBluetoothIfaceAddresses.clone(); for (String iface : ifaces) { for (String regex : bluetoothRegexs) { if (iface.matches(regex)) { if (!found) return null; String address = createNewTetheringAddressLocked(); if (address == null) return null; InterfaceConfiguration ifcg = null; try { ifcg = service.getInterfaceConfig(iface); if (ifcg != null) { if (enabled) { String[] addr = BLUETOOTH_NETMASK.split("\\."); ifcg.netmask = (Integer.parseInt(addr[0]) << 24) + (Integer.parseInt(addr[1]) << 16) + (Integer.parseInt(addr[2]) << 8) + (Integer.parseInt(addr[3])); if (ifcg.ipAddr == 0 && !ifaceAddresses.isEmpty()) { addr = ifaceAddresses.remove(0).split("\\."); if (ifcg.ipAddr == 0) { addr = address.split("\\."); ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) + (Integer.parseInt(addr[1]) << 16) + (Integer.parseInt(addr[2]) << 8) + (Integer.parseInt(addr[3])); } else { String IfaceAddress = String.valueOf(ifcg.ipAddr >>> 24) + "." + String.valueOf((ifcg.ipAddr & 0x00FF0000) >>> 16) + "." + String.valueOf((ifcg.ipAddr & 0x0000FF00) >>> 8) + "." + String.valueOf(ifcg.ipAddr & 0x000000FF); ifaceAddresses.remove(IfaceAddress); } ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); } else { ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); } ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); service.setInterfaceConfig(iface, ifcg); if (enabled) { if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { Log.e(TAG, "Error tethering "+ifaces); } Log.e(TAG, "Error tethering "+iface); } } } catch (Exception e) { Log.e(TAG, "Error configuring interface " + iface + ", :" + e); return false; } } } return null; } return true; return address; } public synchronized boolean connectInputDevice(BluetoothDevice device) { Loading core/jni/android_server_BluetoothEventLoop.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -105,7 +105,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested", "(Ljava/lang/String;)V"); method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected", "(Ljava/lang/String;I)V"); "(Ljava/lang/String;Ljava/lang/String;I)V"); method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected", "(Ljava/lang/String;)V"); Loading Loading @@ -969,15 +969,18 @@ static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, "org.bluez.NetworkServer", "DeviceConnected")) { char *c_address; char *c_iface; uint16_t uuid; if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &c_address, DBUS_TYPE_STRING, &c_iface, DBUS_TYPE_UINT16, &uuid, DBUS_TYPE_INVALID)) { env->CallVoidMethod(nat->me, method_onNetworkDeviceConnected, env->NewStringUTF(c_address), env->NewStringUTF(c_iface), uuid); } else { LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); Loading core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ <string-array translatable="false" name="config_tether_bluetooth_regexs"> </string-array> <!-- Max number of Bluetooth tethering connections allowed. If this is updated config_tether_dhcp_range has to be updated appropriately. --> <integer translateable="false" name="config_max_pan_devices">5</integer> <!-- Dhcp range (min, max) to use for tethering purposes --> <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> Loading services/java/com/android/server/connectivity/Tethering.java +23 −3 Original line number Diff line number Diff line Loading @@ -89,15 +89,27 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; private static final String USB_NETMASK = "255.255.255.0"; // FYI - the default wifi is 192.168.43.1 and 255.255.255.0 // USB is 192.168.42.1 and 255.255.255.0 // Wifi is 192.168.43.1 and 255.255.255.0 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 // with 255.255.255.0 private String[] mDhcpRange; private static final String DHCP_DEFAULT_RANGE1_START = "192.168.42.2"; private static final String DHCP_DEFAULT_RANGE1_STOP = "192.168.42.254"; private static final String DHCP_DEFAULT_RANGE2_START = "192.168.43.2"; private static final String DHCP_DEFAULT_RANGE2_STOP = "192.168.43.254"; private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.9"; private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.2"; private static final String DHCP_DEFAULT_RANGE3_STOP = "192.168.44.254"; private static final String DHCP_DEFAULT_RANGE4_START = "192.168.45.2"; private static final String DHCP_DEFAULT_RANGE4_STOP = "192.168.45.254"; private static final String DHCP_DEFAULT_RANGE5_START = "192.168.46.2"; private static final String DHCP_DEFAULT_RANGE5_STOP = "192.168.46.254"; private static final String DHCP_DEFAULT_RANGE6_START = "192.168.47.2"; private static final String DHCP_DEFAULT_RANGE6_STOP = "192.168.47.254"; private static final String DHCP_DEFAULT_RANGE7_START = "192.168.48.2"; private static final String DHCP_DEFAULT_RANGE7_STOP = "192.168.48.254"; private String[] mDnsServers; private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; Loading Loading @@ -165,13 +177,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mDhcpRange = context.getResources().getStringArray( com.android.internal.R.array.config_tether_dhcp_range); if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { mDhcpRange = new String[6]; mDhcpRange = new String[14]; mDhcpRange[0] = DHCP_DEFAULT_RANGE1_START; mDhcpRange[1] = DHCP_DEFAULT_RANGE1_STOP; mDhcpRange[2] = DHCP_DEFAULT_RANGE2_START; mDhcpRange[3] = DHCP_DEFAULT_RANGE2_STOP; mDhcpRange[4] = DHCP_DEFAULT_RANGE3_START; mDhcpRange[5] = DHCP_DEFAULT_RANGE3_STOP; mDhcpRange[6] = DHCP_DEFAULT_RANGE4_START; mDhcpRange[7] = DHCP_DEFAULT_RANGE4_STOP; mDhcpRange[8] = DHCP_DEFAULT_RANGE5_START; mDhcpRange[9] = DHCP_DEFAULT_RANGE5_STOP; mDhcpRange[10] = DHCP_DEFAULT_RANGE6_START; mDhcpRange[11] = DHCP_DEFAULT_RANGE6_STOP; mDhcpRange[12] = DHCP_DEFAULT_RANGE7_START; mDhcpRange[13] = DHCP_DEFAULT_RANGE7_STOP; } mDunRequired = false; // resample when we turn on Loading Loading
core/java/android/server/BluetoothEventLoop.java +11 −6 Original line number Diff line number Diff line Loading @@ -463,9 +463,14 @@ class BluetoothEventLoop { } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Connected")) { int state = propValues[1].equals("true") ? BluetoothInputDevice.STATE_CONNECTED : BluetoothInputDevice.STATE_DISCONNECTED; mBluetoothService.handlePanDeviceStateChange(device, state); if (propValues[1].equals("false")) { mBluetoothService.handlePanDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTED); } } else if (name.equals("Interface")) { String iface = propValues[1]; mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothInputDevice.STATE_CONNECTED); } } Loading Loading @@ -662,7 +667,7 @@ class BluetoothEventLoop { Log.i(TAG, "Rejecting incoming HID connection from " + address); } } else if (BluetoothUuid.isBnep(uuid) || BluetoothUuid.isNap(uuid) && mBluetoothService.isTetheringOn()){ mBluetoothService.allowIncomingTethering()){ authorized = true; } else { Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address); Loading Loading @@ -796,9 +801,9 @@ class BluetoothEventLoop { mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED); } private void onNetworkDeviceConnected(String address, int destUuid) { private void onNetworkDeviceConnected(String address, String iface, int destUuid) { BluetoothDevice device = mAdapter.getRemoteDevice(address); mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTED); mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED); } private void onRestartRequired() { Loading
core/java/android/server/BluetoothService.java +112 −69 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources.NotFoundException; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; import android.os.Binder; Loading Loading @@ -114,7 +115,10 @@ public class BluetoothService extends IBluetooth.Stub { private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4; private ArrayList<String> mBluetoothIfaceAddresses; private static final String BLUETOOTH_NEAR_IFACE_ADDR_PREFIX= "192.168.44."; private int mMaxPanDevices; private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1"; private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5; private static final String BLUETOOTH_NETMASK = "255.255.255.0"; // The timeout used to sent the UUIDs Intent Loading Loading @@ -144,9 +148,10 @@ public class BluetoothService extends IBluetooth.Stub { private BluetoothA2dpService mA2dpService; private final HashMap<BluetoothDevice, Integer> mInputDevices; private final HashMap<BluetoothDevice, Integer> mPanDevices; private final HashMap<BluetoothDevice, Pair<Integer, String>> mPanDevices; private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData; private static String mDockAddress; private String mDockPin; Loading Loading @@ -211,10 +216,12 @@ public class BluetoothService extends IBluetooth.Stub { mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP); mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID); // Can tether to up to 7 devices mBluetoothIfaceAddresses = new ArrayList<String>(BluetoothPan.MAX_CONNECTIONS); for (int i=1; i <= BluetoothPan.MAX_CONNECTIONS; i++) { mBluetoothIfaceAddresses.add(BLUETOOTH_NEAR_IFACE_ADDR_PREFIX + i); mBluetoothIfaceAddresses = new ArrayList<String>(); try { mMaxPanDevices = context.getResources().getInteger( com.android.internal.R.integer.config_max_pan_devices); } catch (NotFoundException e) { mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS; } mHfpProfileState.start(); Loading @@ -227,7 +234,7 @@ public class BluetoothService extends IBluetooth.Stub { filter.addAction(Intent.ACTION_DOCK_EVENT); mContext.registerReceiver(mReceiver, filter); mInputDevices = new HashMap<BluetoothDevice, Integer>(); mPanDevices = new HashMap<BluetoothDevice, Integer>(); mPanDevices = new HashMap<BluetoothDevice, Pair<Integer, String>>(); } public static synchronized String readDockBluetoothAddress() { Loading Loading @@ -1313,6 +1320,12 @@ public class BluetoothService extends IBluetooth.Stub { return mTetheringOn; } /*package*/ synchronized boolean allowIncomingTethering() { if (isTetheringOn() && getConnectedPanDevices().length < mMaxPanDevices) return true; return false; } private BroadcastReceiver mTetheringReceiver = null; public synchronized void setBluetoothTethering(boolean value) { Loading Loading @@ -1342,10 +1355,11 @@ public class BluetoothService extends IBluetooth.Stub { public synchronized int getPanDeviceState(BluetoothDevice device) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (mPanDevices.get(device) == null) { Pair<Integer, String> panDevice = mPanDevices.get(device); if (panDevice == null) { return BluetoothPan.STATE_DISCONNECTED; } return mPanDevices.get(device); return panDevice.first; } public synchronized boolean connectPanDevice(BluetoothDevice device) { Loading @@ -1359,8 +1373,8 @@ public class BluetoothService extends IBluetooth.Stub { } int connectedCount = 0; for (BluetoothDevice BTdevice: mPanDevices.keySet()) { if (getPanDeviceState(BTdevice) == BluetoothPan.STATE_CONNECTED) { for (BluetoothDevice panDevice: mPanDevices.keySet()) { if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) { connectedCount ++; } } Loading Loading @@ -1419,21 +1433,33 @@ public class BluetoothService extends IBluetooth.Stub { return disconnectPanDeviceNative(objectPath); } /*package*/ void handlePanDeviceStateChange(BluetoothDevice device, int state) { /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, String iface, int state) { int prevState; String ifaceAddr = null; if (mPanDevices.get(device) == null) { prevState = BluetoothPan.STATE_DISCONNECTED; } else { prevState = mPanDevices.get(device); prevState = mPanDevices.get(device).first; ifaceAddr = mPanDevices.get(device).second; } if (prevState == state) return; mPanDevices.put(device, state); if (state == BluetoothPan.STATE_CONNECTED) { updateTetherState(true); ifaceAddr = enableTethering(iface); if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface"); } else if (state == BluetoothPan.STATE_DISCONNECTED) { if (ifaceAddr != null) { mBluetoothIfaceAddresses.remove(ifaceAddr); ifaceAddr = null; } } Pair<Integer, String> value = new Pair<Integer, String>(state, ifaceAddr); mPanDevices.put(device, value); Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState); Loading @@ -1441,12 +1467,35 @@ public class BluetoothService extends IBluetooth.Stub { mContext.sendBroadcast(intent, BLUETOOTH_PERM); if (DBG) log("Pan Device state : device: " + device + " State:" + prevState + "->" + state); } /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device, int state) { handlePanDeviceStateChange(device, null, state); } private String createNewTetheringAddressLocked() { if (getConnectedPanDevices().length == mMaxPanDevices) { log("Max PAN device connections reached"); return null; } String address = BLUETOOTH_IFACE_ADDR_START; while (true) { if (mBluetoothIfaceAddresses.contains(address)) { String[] addr = address.split("\\."); Integer newIp = Integer.parseInt(addr[2]) + 1; address = address.replace(addr[2], newIp.toString()); } else { break; } } mBluetoothIfaceAddresses.add(address); return address; } // configured when we start tethering and unconfig'd on error or conclusion private boolean updateTetherState(boolean enabled) { Log.d(TAG, "configureBluetoothIface(" + enabled + ")"); // configured when we start tethering private synchronized String enableTethering(String iface) { log("updateTetherState:" + iface); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); Loading @@ -1455,64 +1504,58 @@ public class BluetoothService extends IBluetooth.Stub { String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs(); // bring toggle the interfaces String[] ifaces = new String[0]; String[] currentIfaces = new String[0]; try { ifaces = service.listInterfaces(); currentIfaces = service.listInterfaces(); } catch (Exception e) { Log.e(TAG, "Error listing Interfaces :" + e); return false; return null; } boolean found = false; for (String currIface: currentIfaces) { if (currIface.equals(iface)) { found = true; break; } } ArrayList<String> ifaceAddresses = (ArrayList<String>) mBluetoothIfaceAddresses.clone(); for (String iface : ifaces) { for (String regex : bluetoothRegexs) { if (iface.matches(regex)) { if (!found) return null; String address = createNewTetheringAddressLocked(); if (address == null) return null; InterfaceConfiguration ifcg = null; try { ifcg = service.getInterfaceConfig(iface); if (ifcg != null) { if (enabled) { String[] addr = BLUETOOTH_NETMASK.split("\\."); ifcg.netmask = (Integer.parseInt(addr[0]) << 24) + (Integer.parseInt(addr[1]) << 16) + (Integer.parseInt(addr[2]) << 8) + (Integer.parseInt(addr[3])); if (ifcg.ipAddr == 0 && !ifaceAddresses.isEmpty()) { addr = ifaceAddresses.remove(0).split("\\."); if (ifcg.ipAddr == 0) { addr = address.split("\\."); ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) + (Integer.parseInt(addr[1]) << 16) + (Integer.parseInt(addr[2]) << 8) + (Integer.parseInt(addr[3])); } else { String IfaceAddress = String.valueOf(ifcg.ipAddr >>> 24) + "." + String.valueOf((ifcg.ipAddr & 0x00FF0000) >>> 16) + "." + String.valueOf((ifcg.ipAddr & 0x0000FF00) >>> 8) + "." + String.valueOf(ifcg.ipAddr & 0x000000FF); ifaceAddresses.remove(IfaceAddress); } ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); } else { ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); } ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); service.setInterfaceConfig(iface, ifcg); if (enabled) { if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { Log.e(TAG, "Error tethering "+ifaces); } Log.e(TAG, "Error tethering "+iface); } } } catch (Exception e) { Log.e(TAG, "Error configuring interface " + iface + ", :" + e); return false; } } } return null; } return true; return address; } public synchronized boolean connectInputDevice(BluetoothDevice device) { Loading
core/jni/android_server_BluetoothEventLoop.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -105,7 +105,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested", "(Ljava/lang/String;)V"); method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected", "(Ljava/lang/String;I)V"); "(Ljava/lang/String;Ljava/lang/String;I)V"); method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected", "(Ljava/lang/String;)V"); Loading Loading @@ -969,15 +969,18 @@ static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, "org.bluez.NetworkServer", "DeviceConnected")) { char *c_address; char *c_iface; uint16_t uuid; if (dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &c_address, DBUS_TYPE_STRING, &c_iface, DBUS_TYPE_UINT16, &uuid, DBUS_TYPE_INVALID)) { env->CallVoidMethod(nat->me, method_onNetworkDeviceConnected, env->NewStringUTF(c_address), env->NewStringUTF(c_iface), uuid); } else { LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); Loading
core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,10 @@ <string-array translatable="false" name="config_tether_bluetooth_regexs"> </string-array> <!-- Max number of Bluetooth tethering connections allowed. If this is updated config_tether_dhcp_range has to be updated appropriately. --> <integer translateable="false" name="config_max_pan_devices">5</integer> <!-- Dhcp range (min, max) to use for tethering purposes --> <string-array translatable="false" name="config_tether_dhcp_range"> </string-array> Loading
services/java/com/android/server/connectivity/Tethering.java +23 −3 Original line number Diff line number Diff line Loading @@ -89,15 +89,27 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; private static final String USB_NETMASK = "255.255.255.0"; // FYI - the default wifi is 192.168.43.1 and 255.255.255.0 // USB is 192.168.42.1 and 255.255.255.0 // Wifi is 192.168.43.1 and 255.255.255.0 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 // with 255.255.255.0 private String[] mDhcpRange; private static final String DHCP_DEFAULT_RANGE1_START = "192.168.42.2"; private static final String DHCP_DEFAULT_RANGE1_STOP = "192.168.42.254"; private static final String DHCP_DEFAULT_RANGE2_START = "192.168.43.2"; private static final String DHCP_DEFAULT_RANGE2_STOP = "192.168.43.254"; private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.9"; private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.2"; private static final String DHCP_DEFAULT_RANGE3_STOP = "192.168.44.254"; private static final String DHCP_DEFAULT_RANGE4_START = "192.168.45.2"; private static final String DHCP_DEFAULT_RANGE4_STOP = "192.168.45.254"; private static final String DHCP_DEFAULT_RANGE5_START = "192.168.46.2"; private static final String DHCP_DEFAULT_RANGE5_STOP = "192.168.46.254"; private static final String DHCP_DEFAULT_RANGE6_START = "192.168.47.2"; private static final String DHCP_DEFAULT_RANGE6_STOP = "192.168.47.254"; private static final String DHCP_DEFAULT_RANGE7_START = "192.168.48.2"; private static final String DHCP_DEFAULT_RANGE7_STOP = "192.168.48.254"; private String[] mDnsServers; private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; Loading Loading @@ -165,13 +177,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub { mDhcpRange = context.getResources().getStringArray( com.android.internal.R.array.config_tether_dhcp_range); if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { mDhcpRange = new String[6]; mDhcpRange = new String[14]; mDhcpRange[0] = DHCP_DEFAULT_RANGE1_START; mDhcpRange[1] = DHCP_DEFAULT_RANGE1_STOP; mDhcpRange[2] = DHCP_DEFAULT_RANGE2_START; mDhcpRange[3] = DHCP_DEFAULT_RANGE2_STOP; mDhcpRange[4] = DHCP_DEFAULT_RANGE3_START; mDhcpRange[5] = DHCP_DEFAULT_RANGE3_STOP; mDhcpRange[6] = DHCP_DEFAULT_RANGE4_START; mDhcpRange[7] = DHCP_DEFAULT_RANGE4_STOP; mDhcpRange[8] = DHCP_DEFAULT_RANGE5_START; mDhcpRange[9] = DHCP_DEFAULT_RANGE5_STOP; mDhcpRange[10] = DHCP_DEFAULT_RANGE6_START; mDhcpRange[11] = DHCP_DEFAULT_RANGE6_STOP; mDhcpRange[12] = DHCP_DEFAULT_RANGE7_START; mDhcpRange[13] = DHCP_DEFAULT_RANGE7_STOP; } mDunRequired = false; // resample when we turn on Loading