diff options
author | Paul Jensen <pauljensen@google.com> | 2014-06-26 15:11:53 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-06-24 07:59:24 +0000 |
commit | fb23c060031422c34aa8233cb3868d187f36a9dc (patch) | |
tree | e7a73908c3f486a57f14d272fc3265304ddbab5f | |
parent | 689fb16c3dcca9a8d09a8572586a654b1ad38d7d (diff) | |
parent | 58ff480f24ba9905edf86c98035f5e9ad76a453a (diff) | |
download | android_packages_apps_Bluetooth-fb23c060031422c34aa8233cb3868d187f36a9dc.tar.gz android_packages_apps_Bluetooth-fb23c060031422c34aa8233cb3868d187f36a9dc.tar.bz2 android_packages_apps_Bluetooth-fb23c060031422c34aa8233cb3868d187f36a9dc.zip |
Merge "Convert BluetoothTetheringDataTracker into a NetworkFactory."
-rw-r--r-- | src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java | 191 | ||||
-rwxr-xr-x | src/com/android/bluetooth/pan/PanService.java | 48 |
2 files changed, 197 insertions, 42 deletions
diff --git a/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java b/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java new file mode 100644 index 000000000..9040005d8 --- /dev/null +++ b/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java @@ -0,0 +1,191 @@ +/* + * 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); + } +} diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java index 0646f16ac..2443864f2 100755 --- a/src/com/android/bluetooth/pan/PanService.java +++ b/src/com/android/bluetooth/pan/PanService.java @@ -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; @@ -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; @@ -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 { @@ -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); @@ -120,10 +114,6 @@ public class PanService extends ProfileService { protected boolean stop() { mHandler.removeCallbacksAndMessages(null); - if (mTetherAc != null) { - mTetherAc.disconnect(); - mTetherAc = null; - } return true; } @@ -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; } } }; @@ -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(); } } |