summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Jensen <pauljensen@google.com>2014-06-26 15:11:53 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-06-24 07:59:24 +0000
commitfb23c060031422c34aa8233cb3868d187f36a9dc (patch)
treee7a73908c3f486a57f14d272fc3265304ddbab5f
parent689fb16c3dcca9a8d09a8572586a654b1ad38d7d (diff)
parent58ff480f24ba9905edf86c98035f5e9ad76a453a (diff)
downloadandroid_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.java191
-rwxr-xr-xsrc/com/android/bluetooth/pan/PanService.java48
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();
}
}