2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.bluetooth;
19 import android.content.Context;
20 import android.net.ConnectivityManager;
21 import android.net.DhcpInfoInternal;
22 import android.net.LinkAddress;
23 import android.net.LinkCapabilities;
24 import android.net.LinkProperties;
25 import android.net.NetworkInfo;
26 import android.net.NetworkInfo.DetailedState;
27 import android.net.NetworkStateTracker;
28 import android.net.NetworkUtils;
29 import android.os.Handler;
30 import android.os.Message;
31 import android.util.Log;
33 import java.net.InetAddress;
34 import java.util.concurrent.atomic.AtomicBoolean;
35 import java.util.concurrent.atomic.AtomicInteger;
38 * This class tracks the data connection associated with Bluetooth
39 * reverse tethering. This is a singleton class and an instance will be
40 * created by ConnectivityService. BluetoothService will call into this
41 * when a reverse tethered connection needs to be activated.
45 public class BluetoothTetheringDataTracker implements NetworkStateTracker {
46 private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
47 private static final String TAG = "BluetoothTethering";
49 private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
50 private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
51 private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
52 private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
54 private LinkProperties mLinkProperties;
55 private LinkCapabilities mLinkCapabilities;
56 private NetworkInfo mNetworkInfo;
58 private BluetoothPan mBluetoothPan;
59 private BluetoothDevice mDevice;
60 private static String mIface;
62 /* For sending events to connectivity service handler */
63 private Handler mCsHandler;
64 private Context mContext;
65 public static BluetoothTetheringDataTracker sInstance;
67 private BluetoothTetheringDataTracker() {
68 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
69 mLinkProperties = new LinkProperties();
70 mLinkCapabilities = new LinkCapabilities();
72 mNetworkInfo.setIsAvailable(false);
73 setTeardownRequested(false);
76 public static synchronized BluetoothTetheringDataTracker getInstance() {
77 if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
81 public Object Clone() throws CloneNotSupportedException {
82 throw new CloneNotSupportedException();
85 public void setTeardownRequested(boolean isRequested) {
86 mTeardownRequested.set(isRequested);
89 public boolean isTeardownRequested() {
90 return mTeardownRequested.get();
94 * Begin monitoring connectivity
96 public void startMonitoring(Context context, Handler target) {
99 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
100 if (adapter != null) {
101 adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
105 private BluetoothProfile.ServiceListener mProfileServiceListener =
106 new BluetoothProfile.ServiceListener() {
107 public void onServiceConnected(int profile, BluetoothProfile proxy) {
108 mBluetoothPan = (BluetoothPan) proxy;
110 public void onServiceDisconnected(int profile) {
111 mBluetoothPan = null;
116 * Disable connectivity to a network
117 * TODO: do away with return value after making MobileDataStateTracker async
119 public boolean teardown() {
120 mTeardownRequested.set(true);
121 if (mBluetoothPan != null) {
122 for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
123 mBluetoothPan.disconnect(device);
130 * Re-enable connectivity to a network after a {@link #teardown()}.
132 public boolean reconnect() {
133 mTeardownRequested.set(false);
139 * Turn the wireless radio off for a network.
140 * @param turnOn {@code true} to turn the radio on, {@code false}
142 public boolean setRadio(boolean turnOn) {
147 * @return true - If are we currently tethered with another device.
149 public synchronized boolean isAvailable() {
150 return mNetworkInfo.isAvailable();
154 * Tells the underlying networking system that the caller wants to
155 * begin using the named feature. The interpretation of {@code feature}
156 * is completely up to each networking implementation.
157 * @param feature the name of the feature to be used
158 * @param callingPid the process ID of the process that is issuing this request
159 * @param callingUid the user ID of the process that is issuing this request
160 * @return an integer value representing the outcome of the request.
161 * The interpretation of this value is specific to each networking
162 * implementation+feature combination, except that the value {@code -1}
163 * always indicates failure.
164 * TODO: needs to go away
166 public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
171 * Tells the underlying networking system that the caller is finished
172 * using the named feature. The interpretation of {@code feature}
173 * is completely up to each networking implementation.
174 * @param feature the name of the feature that is no longer needed.
175 * @param callingPid the process ID of the process that is issuing this request
176 * @param callingUid the user ID of the process that is issuing this request
177 * @return an integer value representing the outcome of the request.
178 * The interpretation of this value is specific to each networking
179 * implementation+feature combination, except that the value {@code -1}
180 * always indicates failure.
181 * TODO: needs to go away
183 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
190 public void setDataEnable(boolean enabled) {
191 android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
195 * Check if private DNS route is set for the network
197 public boolean isPrivateDnsRouteSet() {
198 return mPrivateDnsRouteSet.get();
202 * Set a flag indicating private DNS route is set
204 public void privateDnsRouteSet(boolean enabled) {
205 mPrivateDnsRouteSet.set(enabled);
209 * Fetch NetworkInfo for the network
211 public synchronized NetworkInfo getNetworkInfo() {
216 * Fetch LinkProperties for the network
218 public synchronized LinkProperties getLinkProperties() {
219 return new LinkProperties(mLinkProperties);
223 * A capability is an Integer/String pair, the capabilities
224 * are defined in the class LinkSocket#Key.
226 * @return a copy of this connections capabilities, may be empty but never null.
228 public LinkCapabilities getLinkCapabilities() {
229 return new LinkCapabilities(mLinkCapabilities);
233 * Fetch default gateway address for the network
235 public int getDefaultGatewayAddr() {
236 return mDefaultGatewayAddr.get();
240 * Check if default route is set
242 public boolean isDefaultRouteSet() {
243 return mDefaultRouteSet.get();
247 * Set a flag indicating default route is set for the network
249 public void defaultRouteSet(boolean enabled) {
250 mDefaultRouteSet.set(enabled);
254 * Return the system properties name associated with the tcp buffer sizes
257 public String getTcpBufferSizesPropName() {
258 return "net.tcp.buffersize.wifi";
262 public synchronized void startReverseTether(String iface, BluetoothDevice device) {
265 Thread dhcpThread = new Thread(new Runnable() {
267 //TODO(): Add callbacks for failure and success case.
268 //Currently this thread runs independently.
269 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
270 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
271 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
274 mLinkProperties = dhcpInfoInternal.makeLinkProperties();
275 mLinkProperties.setInterfaceName(mIface);
277 mNetworkInfo.setIsAvailable(true);
278 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
280 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
283 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
290 public synchronized void stopReverseTether(String iface) {
291 NetworkUtils.stopDhcp(iface);
293 mLinkProperties.clear();
294 mNetworkInfo.setIsAvailable(false);
295 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
297 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
300 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);