diff options
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); |