Loading android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java 0 → 100644 +191 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.pan; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.net.ConnectivityManager; import android.net.DhcpResults; import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.text.TextUtils; import android.util.Slog; import com.android.bluetooth.pan.PanService; import com.android.internal.util.AsyncChannel; /** * This class tracks the data connection associated with Bluetooth * reverse tethering. PanService calls it when a reverse tethered * connection needs to be activated or deactivated. * * @hide */ public class BluetoothTetheringNetworkFactory extends NetworkFactory { private static final String NETWORK_TYPE = "Bluetooth Tethering"; private static final String TAG = "BluetoothTetheringNetworkFactory"; private static final int NETWORK_SCORE = 69; private final NetworkCapabilities mNetworkCapabilities; private final Context mContext; private final PanService mPanService; // All accesses to these must be synchronized(this). private final NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; private NetworkAgent mNetworkAgent; public BluetoothTetheringNetworkFactory(Context context, Looper looper, PanService panService) { super(looper, context, NETWORK_TYPE, new NetworkCapabilities()); mContext = context; mPanService = panService; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); mNetworkCapabilities = new NetworkCapabilities(); initNetworkCapabilities(); setCapabilityFilter(mNetworkCapabilities); } // Called by NetworkFactory when PanService and NetworkFactory both desire a Bluetooth // reverse-tether connection. A network interface for Bluetooth reverse-tethering can be // assumed to be available because we only register our NetworkFactory when it is so. @Override protected void startNetwork() { // TODO: Handle DHCP renew. Thread dhcpThread = new Thread(new Runnable() { public void run() { LinkProperties linkProperties; synchronized (BluetoothTetheringNetworkFactory.this) { linkProperties = mLinkProperties; if (linkProperties.getInterfaceName() == null) { Slog.e(TAG, "attempted to reverse tether without interface name"); return; } log("dhcpThread(+" + linkProperties.getInterfaceName() + "): mNetworkInfo=" + mNetworkInfo); } DhcpResults dhcpResults = new DhcpResults(); // TODO: Handle DHCP renewals better. // In general runDhcp handles DHCP renewals for us, because // the dhcp client stays running, but if the renewal fails, // we will lose our IP address and connectivity without // noticing. if (!NetworkUtils.runDhcp(linkProperties.getInterfaceName(), dhcpResults)) { Slog.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); synchronized(BluetoothTetheringNetworkFactory.this) { setScoreFilter(-1); } return; } synchronized(BluetoothTetheringNetworkFactory.this) { mLinkProperties = dhcpResults.linkProperties; mNetworkInfo.setIsAvailable(true); mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); // Create our NetworkAgent. mNetworkAgent = new NetworkAgent(getLooper(), mContext, NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, NETWORK_SCORE) { public void unwanted() { BluetoothTetheringNetworkFactory.this.onCancelRequest(); }; }; } } }); dhcpThread.start(); } // Called from NetworkFactory to indicate ConnectivityService no longer desires a Bluetooth // reverse-tether network. @Override protected void stopNetwork() { // Let NetworkAgent disconnect do the teardown. } // Called by the NetworkFactory, NetworkAgent or PanService to tear down network. private synchronized void onCancelRequest() { if (!TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName()); } mLinkProperties.clear(); mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent = null; } for (BluetoothDevice device : mPanService.getConnectedDevices()) { mPanService.disconnect(device); } } // Called by PanService when a network interface for Bluetooth reverse-tethering // becomes available. We register our NetworkFactory at this point. public void startReverseTether(final String iface) { if (iface == null || TextUtils.isEmpty(iface)) { Slog.e(TAG, "attempted to reverse tether with empty interface"); return; } synchronized(this) { if (mLinkProperties.getInterfaceName() != null) { Slog.e(TAG, "attempted to reverse tether while already in process"); return; } mLinkProperties = new LinkProperties(); mLinkProperties.setInterfaceName(iface); // Advertise ourselves to ConnectivityService. register(); setScoreFilter(NETWORK_SCORE); } } // Called by PanService when a network interface for Bluetooth reverse-tethering // goes away. We stop advertising ourselves to ConnectivityService at this point. public synchronized void stopReverseTether() { if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { Slog.e(TAG, "attempted to stop reverse tether with nothing tethered"); return; } onCancelRequest(); setScoreFilter(-1); unregister(); } private void initNetworkCapabilities() { mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); // Bluetooth v3 and v4 go up to 24 Mbps. // TODO: Adjust this to actual connection bandwidth. mNetworkCapabilities.setLinkUpstreamBandwidthKbps(24 * 1000); mNetworkCapabilities.setLinkDownstreamBandwidthKbps(24 * 1000); } } android/app/src/com/android/bluetooth/pan/PanService.java +6 −42 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Service; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothTetheringDataTracker; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothPan; import android.content.Context; Loading @@ -30,21 +29,17 @@ import android.content.res.Resources.NotFoundException; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.Utils; import com.android.internal.util.AsyncChannel; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; Loading Loading @@ -80,7 +75,7 @@ public class PanService extends ProfileService { private static final String PAN_PREFERENCE_FILE = "PANMGR"; private static final String PAN_TETHER_SETTING = "TETHERSTATE"; AsyncChannel mTetherAc; private BluetoothTetheringNetworkFactory mNetworkFactory; static { Loading @@ -107,9 +102,8 @@ public class PanService extends ProfileService { initializeNative(); mNativeAvailable=true; ConnectivityManager cm = (ConnectivityManager) getSystemService( Context.CONNECTIVITY_SERVICE); cm.supplyMessenger(ConnectivityManager.TYPE_BLUETOOTH, new Messenger(mHandler)); mNetworkFactory = new BluetoothTetheringNetworkFactory(getBaseContext(), getMainLooper(), this); // Set mTetherOn based on the last saved tethering preference while starting the Pan service SharedPreferences tetherSetting = getSharedPreferences(PAN_PREFERENCE_FILE, 0); Loading @@ -120,10 +114,6 @@ public class PanService extends ProfileService { protected boolean stop() { mHandler.removeCallbacksAndMessages(null); if (mTetherAc != null) { mTetherAc.disconnect(); mTetherAc = null; } return true; } Loading Loading @@ -190,28 +180,6 @@ public class PanService extends ProfileService { convertHalState(cs.state), cs.local_role, cs.remote_role); } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { if (mTetherAc != null) { mTetherAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED); } else { mTetherAc = new AsyncChannel(); mTetherAc.connected(null, this, msg.replyTo); mTetherAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL); } } break; case AsyncChannel.CMD_CHANNEL_DISCONNECT: { if (mTetherAc != null) { mTetherAc.disconnect(); mTetherAc = null; } } break; } } }; Loading Loading @@ -465,20 +433,16 @@ public class PanService extends ProfileService { ifaceAddr = null; } } } else if (mTetherAc != null) { } else if (mNetworkFactory != null) { // PANU Role = reverse Tether Log.d(TAG, "handlePanDeviceStateChange LOCAL_PANU_ROLE:REMOTE_NAP_ROLE state = " + state + ", prevState = " + prevState); if (state == BluetoothProfile.STATE_CONNECTED) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(iface); mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_CONNECTED, lp); mNetworkFactory.startReverseTether(iface); } else if (state == BluetoothProfile.STATE_DISCONNECTED && (prevState == BluetoothProfile.STATE_CONNECTED || prevState == BluetoothProfile.STATE_DISCONNECTING)) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(iface); mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_DISCONNECTED, lp); mNetworkFactory.stopReverseTether(); } } Loading Loading
android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java 0 → 100644 +191 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.pan; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.net.ConnectivityManager; import android.net.DhcpResults; import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.text.TextUtils; import android.util.Slog; import com.android.bluetooth.pan.PanService; import com.android.internal.util.AsyncChannel; /** * This class tracks the data connection associated with Bluetooth * reverse tethering. PanService calls it when a reverse tethered * connection needs to be activated or deactivated. * * @hide */ public class BluetoothTetheringNetworkFactory extends NetworkFactory { private static final String NETWORK_TYPE = "Bluetooth Tethering"; private static final String TAG = "BluetoothTetheringNetworkFactory"; private static final int NETWORK_SCORE = 69; private final NetworkCapabilities mNetworkCapabilities; private final Context mContext; private final PanService mPanService; // All accesses to these must be synchronized(this). private final NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; private NetworkAgent mNetworkAgent; public BluetoothTetheringNetworkFactory(Context context, Looper looper, PanService panService) { super(looper, context, NETWORK_TYPE, new NetworkCapabilities()); mContext = context; mPanService = panService; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); mNetworkCapabilities = new NetworkCapabilities(); initNetworkCapabilities(); setCapabilityFilter(mNetworkCapabilities); } // Called by NetworkFactory when PanService and NetworkFactory both desire a Bluetooth // reverse-tether connection. A network interface for Bluetooth reverse-tethering can be // assumed to be available because we only register our NetworkFactory when it is so. @Override protected void startNetwork() { // TODO: Handle DHCP renew. Thread dhcpThread = new Thread(new Runnable() { public void run() { LinkProperties linkProperties; synchronized (BluetoothTetheringNetworkFactory.this) { linkProperties = mLinkProperties; if (linkProperties.getInterfaceName() == null) { Slog.e(TAG, "attempted to reverse tether without interface name"); return; } log("dhcpThread(+" + linkProperties.getInterfaceName() + "): mNetworkInfo=" + mNetworkInfo); } DhcpResults dhcpResults = new DhcpResults(); // TODO: Handle DHCP renewals better. // In general runDhcp handles DHCP renewals for us, because // the dhcp client stays running, but if the renewal fails, // we will lose our IP address and connectivity without // noticing. if (!NetworkUtils.runDhcp(linkProperties.getInterfaceName(), dhcpResults)) { Slog.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); synchronized(BluetoothTetheringNetworkFactory.this) { setScoreFilter(-1); } return; } synchronized(BluetoothTetheringNetworkFactory.this) { mLinkProperties = dhcpResults.linkProperties; mNetworkInfo.setIsAvailable(true); mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); // Create our NetworkAgent. mNetworkAgent = new NetworkAgent(getLooper(), mContext, NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, NETWORK_SCORE) { public void unwanted() { BluetoothTetheringNetworkFactory.this.onCancelRequest(); }; }; } } }); dhcpThread.start(); } // Called from NetworkFactory to indicate ConnectivityService no longer desires a Bluetooth // reverse-tether network. @Override protected void stopNetwork() { // Let NetworkAgent disconnect do the teardown. } // Called by the NetworkFactory, NetworkAgent or PanService to tear down network. private synchronized void onCancelRequest() { if (!TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName()); } mLinkProperties.clear(); mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); if (mNetworkAgent != null) { mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent = null; } for (BluetoothDevice device : mPanService.getConnectedDevices()) { mPanService.disconnect(device); } } // Called by PanService when a network interface for Bluetooth reverse-tethering // becomes available. We register our NetworkFactory at this point. public void startReverseTether(final String iface) { if (iface == null || TextUtils.isEmpty(iface)) { Slog.e(TAG, "attempted to reverse tether with empty interface"); return; } synchronized(this) { if (mLinkProperties.getInterfaceName() != null) { Slog.e(TAG, "attempted to reverse tether while already in process"); return; } mLinkProperties = new LinkProperties(); mLinkProperties.setInterfaceName(iface); // Advertise ourselves to ConnectivityService. register(); setScoreFilter(NETWORK_SCORE); } } // Called by PanService when a network interface for Bluetooth reverse-tethering // goes away. We stop advertising ourselves to ConnectivityService at this point. public synchronized void stopReverseTether() { if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { Slog.e(TAG, "attempted to stop reverse tether with nothing tethered"); return; } onCancelRequest(); setScoreFilter(-1); unregister(); } private void initNetworkCapabilities() { mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_BLUETOOTH); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); // Bluetooth v3 and v4 go up to 24 Mbps. // TODO: Adjust this to actual connection bandwidth. mNetworkCapabilities.setLinkUpstreamBandwidthKbps(24 * 1000); mNetworkCapabilities.setLinkDownstreamBandwidthKbps(24 * 1000); } }
android/app/src/com/android/bluetooth/pan/PanService.java +6 −42 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.Service; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothPan; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothTetheringDataTracker; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothPan; import android.content.Context; Loading @@ -30,21 +29,17 @@ import android.content.res.Resources.NotFoundException; import android.net.ConnectivityManager; import android.net.InterfaceConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.Utils; import com.android.internal.util.AsyncChannel; import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; Loading Loading @@ -80,7 +75,7 @@ public class PanService extends ProfileService { private static final String PAN_PREFERENCE_FILE = "PANMGR"; private static final String PAN_TETHER_SETTING = "TETHERSTATE"; AsyncChannel mTetherAc; private BluetoothTetheringNetworkFactory mNetworkFactory; static { Loading @@ -107,9 +102,8 @@ public class PanService extends ProfileService { initializeNative(); mNativeAvailable=true; ConnectivityManager cm = (ConnectivityManager) getSystemService( Context.CONNECTIVITY_SERVICE); cm.supplyMessenger(ConnectivityManager.TYPE_BLUETOOTH, new Messenger(mHandler)); mNetworkFactory = new BluetoothTetheringNetworkFactory(getBaseContext(), getMainLooper(), this); // Set mTetherOn based on the last saved tethering preference while starting the Pan service SharedPreferences tetherSetting = getSharedPreferences(PAN_PREFERENCE_FILE, 0); Loading @@ -120,10 +114,6 @@ public class PanService extends ProfileService { protected boolean stop() { mHandler.removeCallbacksAndMessages(null); if (mTetherAc != null) { mTetherAc.disconnect(); mTetherAc = null; } return true; } Loading Loading @@ -190,28 +180,6 @@ public class PanService extends ProfileService { convertHalState(cs.state), cs.local_role, cs.remote_role); } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { if (mTetherAc != null) { mTetherAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED); } else { mTetherAc = new AsyncChannel(); mTetherAc.connected(null, this, msg.replyTo); mTetherAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL); } } break; case AsyncChannel.CMD_CHANNEL_DISCONNECT: { if (mTetherAc != null) { mTetherAc.disconnect(); mTetherAc = null; } } break; } } }; Loading Loading @@ -465,20 +433,16 @@ public class PanService extends ProfileService { ifaceAddr = null; } } } else if (mTetherAc != null) { } else if (mNetworkFactory != null) { // PANU Role = reverse Tether Log.d(TAG, "handlePanDeviceStateChange LOCAL_PANU_ROLE:REMOTE_NAP_ROLE state = " + state + ", prevState = " + prevState); if (state == BluetoothProfile.STATE_CONNECTED) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(iface); mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_CONNECTED, lp); mNetworkFactory.startReverseTether(iface); } else if (state == BluetoothProfile.STATE_DISCONNECTED && (prevState == BluetoothProfile.STATE_CONNECTED || prevState == BluetoothProfile.STATE_DISCONNECTING)) { LinkProperties lp = new LinkProperties(); lp.setInterfaceName(iface); mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_DISCONNECTED, lp); mNetworkFactory.stopReverseTether(); } } Loading