From 15c7439acb22ab079dd2ebe42bdf0d2ffd525c5d Mon Sep 17 00:00:00 2001 From: Jaikumar Ganesh Date: Tue, 21 Dec 2010 22:31:44 -0800 Subject: Add TYPE_BLUETOOTH network interface for reverse tethering. Change-Id: I2aa61ce15f57aea9e8fd3a4cb56799c8bc51e998 --- .../bluetooth/BluetoothTetheringDataTracker.java | 299 +++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 core/java/android/bluetooth/BluetoothTetheringDataTracker.java (limited to 'core/java/android/bluetooth/BluetoothTetheringDataTracker.java') 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(); + } +} -- cgit v1.1