summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaikumar Ganesh <jaikumar@google.com>2010-12-21 22:31:44 -0800
committerJaikumar Ganesh <jaikumar@google.com>2010-12-22 15:24:18 -0800
commit15c7439acb22ab079dd2ebe42bdf0d2ffd525c5d (patch)
tree25fac424972b32834a98a1c0a2ee53ca1970f1a9
parent93e7d00f3f0466c088f70568941f5276316b9bd2 (diff)
downloadframeworks_base-15c7439acb22ab079dd2ebe42bdf0d2ffd525c5d.zip
frameworks_base-15c7439acb22ab079dd2ebe42bdf0d2ffd525c5d.tar.gz
frameworks_base-15c7439acb22ab079dd2ebe42bdf0d2ffd525c5d.tar.bz2
Add TYPE_BLUETOOTH network interface for reverse tethering.
Change-Id: I2aa61ce15f57aea9e8fd3a4cb56799c8bc51e998
-rw-r--r--core/java/android/bluetooth/BluetoothTetheringDataTracker.java299
-rw-r--r--core/java/android/net/ConnectivityManager.java10
-rw-r--r--services/java/com/android/server/ConnectivityService.java11
3 files changed, 313 insertions, 7 deletions
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
new file mode 100644
index 0000000..7b083f1
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 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 android.bluetooth;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.DhcpInfo;
+import android.net.LinkAddress;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkStateTracker;
+import android.net.NetworkUtils;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class tracks the data connection associated with Bluetooth
+ * reverse tethering. This is a singleton class and an instance will be
+ * created by ConnectivityService. BluetoothService will call into this
+ * when a reverse tethered connection needs to be activated.
+ *
+ * @hide
+ */
+public class BluetoothTetheringDataTracker implements NetworkStateTracker {
+ private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
+ private static final String TAG = "BluetoothTethering";
+
+ private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
+ private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
+ private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
+ private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+
+ private LinkProperties mLinkProperties;
+ private LinkCapabilities mLinkCapabilities;
+ private NetworkInfo mNetworkInfo;
+
+ private BluetoothPan mBluetoothPan;
+ private BluetoothDevice mDevice;
+ private static String mIface;
+
+ /* For sending events to connectivity service handler */
+ private Handler mCsHandler;
+ private Context mContext;
+ public static BluetoothTetheringDataTracker sInstance;
+
+ private BluetoothTetheringDataTracker() {
+ mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
+ mLinkProperties = new LinkProperties();
+ mLinkCapabilities = new LinkCapabilities();
+
+ mNetworkInfo.setIsAvailable(false);
+ setTeardownRequested(false);
+ }
+
+ public static synchronized BluetoothTetheringDataTracker getInstance() {
+ if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
+ return sInstance;
+ }
+
+ public Object Clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }
+
+ public void setTeardownRequested(boolean isRequested) {
+ mTeardownRequested.set(isRequested);
+ }
+
+ public boolean isTeardownRequested() {
+ return mTeardownRequested.get();
+ }
+
+ /**
+ * Begin monitoring connectivity
+ */
+ public void startMonitoring(Context context, Handler target) {
+ mContext = context;
+ mCsHandler = target;
+ mBluetoothPan = new BluetoothPan(mContext);
+ }
+
+ /**
+ * Disable connectivity to a network
+ * TODO: do away with return value after making MobileDataStateTracker async
+ */
+ public boolean teardown() {
+ mTeardownRequested.set(true);
+ for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
+ mBluetoothPan.disconnect(device);
+ }
+ return true;
+ }
+
+ /**
+ * Re-enable connectivity to a network after a {@link #teardown()}.
+ */
+ public boolean reconnect() {
+ mTeardownRequested.set(false);
+ //Ignore
+ return true;
+ }
+
+ /**
+ * Turn the wireless radio off for a network.
+ * @param turnOn {@code true} to turn the radio on, {@code false}
+ */
+ public boolean setRadio(boolean turnOn) {
+ return true;
+ }
+
+ /**
+ * @return true - If are we currently tethered with another device.
+ */
+ public synchronized boolean isAvailable() {
+ return mNetworkInfo.isAvailable();
+ }
+
+ /**
+ * Tells the underlying networking system that the caller wants to
+ * begin using the named feature. The interpretation of {@code feature}
+ * is completely up to each networking implementation.
+ * @param feature the name of the feature to be used
+ * @param callingPid the process ID of the process that is issuing this request
+ * @param callingUid the user ID of the process that is issuing this request
+ * @return an integer value representing the outcome of the request.
+ * The interpretation of this value is specific to each networking
+ * implementation+feature combination, except that the value {@code -1}
+ * always indicates failure.
+ * TODO: needs to go away
+ */
+ public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+ return -1;
+ }
+
+ /**
+ * Tells the underlying networking system that the caller is finished
+ * using the named feature. The interpretation of {@code feature}
+ * is completely up to each networking implementation.
+ * @param feature the name of the feature that is no longer needed.
+ * @param callingPid the process ID of the process that is issuing this request
+ * @param callingUid the user ID of the process that is issuing this request
+ * @return an integer value representing the outcome of the request.
+ * The interpretation of this value is specific to each networking
+ * implementation+feature combination, except that the value {@code -1}
+ * always indicates failure.
+ * TODO: needs to go away
+ */
+ public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
+ return -1;
+ }
+
+ /**
+ * @param enabled
+ */
+ public void setDataEnable(boolean enabled) {
+ android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
+ }
+
+ /**
+ * Check if private DNS route is set for the network
+ */
+ public boolean isPrivateDnsRouteSet() {
+ return mPrivateDnsRouteSet.get();
+ }
+
+ /**
+ * Set a flag indicating private DNS route is set
+ */
+ public void privateDnsRouteSet(boolean enabled) {
+ mPrivateDnsRouteSet.set(enabled);
+ }
+
+ /**
+ * Fetch NetworkInfo for the network
+ */
+ public synchronized NetworkInfo getNetworkInfo() {
+ return mNetworkInfo;
+ }
+
+ /**
+ * Fetch LinkProperties for the network
+ */
+ public synchronized LinkProperties getLinkProperties() {
+ return new LinkProperties(mLinkProperties);
+ }
+
+ /**
+ * A capability is an Integer/String pair, the capabilities
+ * are defined in the class LinkSocket#Key.
+ *
+ * @return a copy of this connections capabilities, may be empty but never null.
+ */
+ public LinkCapabilities getLinkCapabilities() {
+ return new LinkCapabilities(mLinkCapabilities);
+ }
+
+ /**
+ * Fetch default gateway address for the network
+ */
+ public int getDefaultGatewayAddr() {
+ return mDefaultGatewayAddr.get();
+ }
+
+ /**
+ * Check if default route is set
+ */
+ public boolean isDefaultRouteSet() {
+ return mDefaultRouteSet.get();
+ }
+
+ /**
+ * Set a flag indicating default route is set for the network
+ */
+ public void defaultRouteSet(boolean enabled) {
+ mDefaultRouteSet.set(enabled);
+ }
+
+ /**
+ * Return the system properties name associated with the tcp buffer sizes
+ * for this network.
+ */
+ public String getTcpBufferSizesPropName() {
+ return "net.tcp.buffersize.wifi";
+ }
+
+
+ public synchronized void startReverseTether(String iface, BluetoothDevice device) {
+ mIface = iface;
+ mDevice = device;
+ Thread dhcpThread = new Thread(new Runnable() {
+ public void run() {
+ //TODO(): Add callbacks for failure and success case.
+ //Currently this thread runs independently.
+ DhcpInfo dhcpInfo = new DhcpInfo();
+ if (!NetworkUtils.runDhcp(mIface, dhcpInfo)) {
+ Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
+ return;
+ }
+ mLinkProperties.addLinkAddress(new LinkAddress(
+ NetworkUtils.intToInetAddress(dhcpInfo.ipAddress),
+ NetworkUtils.intToInetAddress(dhcpInfo.netmask)));
+ mLinkProperties.setGateway(NetworkUtils.intToInetAddress(dhcpInfo.gateway));
+ InetAddress dns1Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns1);
+ if (dns1Addr == null || dns1Addr.equals("0.0.0.0")) {
+ mLinkProperties.addDns(dns1Addr);
+ }
+ InetAddress dns2Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns2);
+ if (dns2Addr == null || dns2Addr.equals("0.0.0.0")) {
+ mLinkProperties.addDns(dns2Addr);
+ }
+ mLinkProperties.setInterfaceName(mIface);
+
+ mNetworkInfo.setIsAvailable(true);
+ mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
+
+ Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+
+ msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+ }
+ });
+ dhcpThread.start();
+ }
+
+ public synchronized void stopReverseTether(String iface) {
+ NetworkUtils.stopDhcp(iface);
+
+ mLinkProperties.clear();
+ mNetworkInfo.setIsAvailable(false);
+ mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
+
+ Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+
+ msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+ msg.sendToTarget();
+ }
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3d685cb..7e809f5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -213,10 +213,16 @@ public class ConnectivityManager
*/
public static final int TYPE_WIMAX = 6;
+ /**
+ * Bluetooth data connection. This is used for Bluetooth reverse tethering.
+ * @hide
+ */
+ public static final int TYPE_BLUETOOTH = 7;
+
/** {@hide} */
- public static final int TYPE_DUMMY = 7;
+ public static final int TYPE_DUMMY = 8;
/** {@hide} TODO: Need to adjust this for WiMAX. */
- public static final int MAX_RADIO_TYPE = TYPE_WIFI;
+ public static final int MAX_RADIO_TYPE = TYPE_DUMMY;
/** {@hide} TODO: Need to adjust this for WiMAX. */
public static final int MAX_NETWORK_TYPE = TYPE_DUMMY;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3e2eac2..e7e4302 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,8 +16,7 @@
package com.android.server;
-import android.app.Notification;
-import android.app.NotificationManager;
+import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -26,9 +25,9 @@ import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.DummyDataStateTracker;
import android.net.IConnectivityManager;
+import android.net.LinkProperties;
import android.net.MobileDataStateTracker;
import android.net.NetworkInfo;
-import android.net.LinkProperties;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
@@ -50,7 +49,6 @@ import android.util.EventLog;
import android.util.Slog;
import com.android.internal.telephony.Phone;
-
import com.android.server.connectivity.Tethering;
import java.io.FileDescriptor;
@@ -58,7 +56,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
-import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
@@ -412,6 +409,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetAttributes[netType].mName);
mNetTrackers[netType].startMonitoring(context, mHandler);
break;
+ case ConnectivityManager.TYPE_BLUETOOTH:
+ mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
+ mNetTrackers[netType].startMonitoring(context, mHandler);
+ break;
default:
loge("Trying to create a DataStateTracker for an unknown radio type " +
mNetAttributes[netType].mRadio);