blob: 7b083f10e2bd4fe145b07dadddf7ebe8a2528eac [file] [log] [blame]
Jaikumar Ganesh15c74392010-12-21 22:31:44 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package android.bluetooth;
18
19import android.content.Context;
20import android.net.ConnectivityManager;
21import android.net.DhcpInfo;
22import android.net.LinkAddress;
23import android.net.LinkCapabilities;
24import android.net.LinkProperties;
25import android.net.NetworkInfo;
26import android.net.NetworkInfo.DetailedState;
27import android.net.NetworkStateTracker;
28import android.net.NetworkUtils;
29import android.os.Handler;
30import android.os.Message;
31import android.util.Log;
32
33import java.net.InetAddress;
34import java.util.concurrent.atomic.AtomicBoolean;
35import java.util.concurrent.atomic.AtomicInteger;
36
37/**
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.
42 *
43 * @hide
44 */
45public class BluetoothTetheringDataTracker implements NetworkStateTracker {
46 private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
47 private static final String TAG = "BluetoothTethering";
48
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);
53
54 private LinkProperties mLinkProperties;
55 private LinkCapabilities mLinkCapabilities;
56 private NetworkInfo mNetworkInfo;
57
58 private BluetoothPan mBluetoothPan;
59 private BluetoothDevice mDevice;
60 private static String mIface;
61
62 /* For sending events to connectivity service handler */
63 private Handler mCsHandler;
64 private Context mContext;
65 public static BluetoothTetheringDataTracker sInstance;
66
67 private BluetoothTetheringDataTracker() {
68 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
69 mLinkProperties = new LinkProperties();
70 mLinkCapabilities = new LinkCapabilities();
71
72 mNetworkInfo.setIsAvailable(false);
73 setTeardownRequested(false);
74 }
75
76 public static synchronized BluetoothTetheringDataTracker getInstance() {
77 if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
78 return sInstance;
79 }
80
81 public Object Clone() throws CloneNotSupportedException {
82 throw new CloneNotSupportedException();
83 }
84
85 public void setTeardownRequested(boolean isRequested) {
86 mTeardownRequested.set(isRequested);
87 }
88
89 public boolean isTeardownRequested() {
90 return mTeardownRequested.get();
91 }
92
93 /**
94 * Begin monitoring connectivity
95 */
96 public void startMonitoring(Context context, Handler target) {
97 mContext = context;
98 mCsHandler = target;
99 mBluetoothPan = new BluetoothPan(mContext);
100 }
101
102 /**
103 * Disable connectivity to a network
104 * TODO: do away with return value after making MobileDataStateTracker async
105 */
106 public boolean teardown() {
107 mTeardownRequested.set(true);
108 for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
109 mBluetoothPan.disconnect(device);
110 }
111 return true;
112 }
113
114 /**
115 * Re-enable connectivity to a network after a {@link #teardown()}.
116 */
117 public boolean reconnect() {
118 mTeardownRequested.set(false);
119 //Ignore
120 return true;
121 }
122
123 /**
124 * Turn the wireless radio off for a network.
125 * @param turnOn {@code true} to turn the radio on, {@code false}
126 */
127 public boolean setRadio(boolean turnOn) {
128 return true;
129 }
130
131 /**
132 * @return true - If are we currently tethered with another device.
133 */
134 public synchronized boolean isAvailable() {
135 return mNetworkInfo.isAvailable();
136 }
137
138 /**
139 * Tells the underlying networking system that the caller wants to
140 * begin using the named feature. The interpretation of {@code feature}
141 * is completely up to each networking implementation.
142 * @param feature the name of the feature to be used
143 * @param callingPid the process ID of the process that is issuing this request
144 * @param callingUid the user ID of the process that is issuing this request
145 * @return an integer value representing the outcome of the request.
146 * The interpretation of this value is specific to each networking
147 * implementation+feature combination, except that the value {@code -1}
148 * always indicates failure.
149 * TODO: needs to go away
150 */
151 public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
152 return -1;
153 }
154
155 /**
156 * Tells the underlying networking system that the caller is finished
157 * using the named feature. The interpretation of {@code feature}
158 * is completely up to each networking implementation.
159 * @param feature the name of the feature that is no longer needed.
160 * @param callingPid the process ID of the process that is issuing this request
161 * @param callingUid the user ID of the process that is issuing this request
162 * @return an integer value representing the outcome of the request.
163 * The interpretation of this value is specific to each networking
164 * implementation+feature combination, except that the value {@code -1}
165 * always indicates failure.
166 * TODO: needs to go away
167 */
168 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
169 return -1;
170 }
171
172 /**
173 * @param enabled
174 */
175 public void setDataEnable(boolean enabled) {
176 android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
177 }
178
179 /**
180 * Check if private DNS route is set for the network
181 */
182 public boolean isPrivateDnsRouteSet() {
183 return mPrivateDnsRouteSet.get();
184 }
185
186 /**
187 * Set a flag indicating private DNS route is set
188 */
189 public void privateDnsRouteSet(boolean enabled) {
190 mPrivateDnsRouteSet.set(enabled);
191 }
192
193 /**
194 * Fetch NetworkInfo for the network
195 */
196 public synchronized NetworkInfo getNetworkInfo() {
197 return mNetworkInfo;
198 }
199
200 /**
201 * Fetch LinkProperties for the network
202 */
203 public synchronized LinkProperties getLinkProperties() {
204 return new LinkProperties(mLinkProperties);
205 }
206
207 /**
208 * A capability is an Integer/String pair, the capabilities
209 * are defined in the class LinkSocket#Key.
210 *
211 * @return a copy of this connections capabilities, may be empty but never null.
212 */
213 public LinkCapabilities getLinkCapabilities() {
214 return new LinkCapabilities(mLinkCapabilities);
215 }
216
217 /**
218 * Fetch default gateway address for the network
219 */
220 public int getDefaultGatewayAddr() {
221 return mDefaultGatewayAddr.get();
222 }
223
224 /**
225 * Check if default route is set
226 */
227 public boolean isDefaultRouteSet() {
228 return mDefaultRouteSet.get();
229 }
230
231 /**
232 * Set a flag indicating default route is set for the network
233 */
234 public void defaultRouteSet(boolean enabled) {
235 mDefaultRouteSet.set(enabled);
236 }
237
238 /**
239 * Return the system properties name associated with the tcp buffer sizes
240 * for this network.
241 */
242 public String getTcpBufferSizesPropName() {
243 return "net.tcp.buffersize.wifi";
244 }
245
246
247 public synchronized void startReverseTether(String iface, BluetoothDevice device) {
248 mIface = iface;
249 mDevice = device;
250 Thread dhcpThread = new Thread(new Runnable() {
251 public void run() {
252 //TODO(): Add callbacks for failure and success case.
253 //Currently this thread runs independently.
254 DhcpInfo dhcpInfo = new DhcpInfo();
255 if (!NetworkUtils.runDhcp(mIface, dhcpInfo)) {
256 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
257 return;
258 }
259 mLinkProperties.addLinkAddress(new LinkAddress(
260 NetworkUtils.intToInetAddress(dhcpInfo.ipAddress),
261 NetworkUtils.intToInetAddress(dhcpInfo.netmask)));
262 mLinkProperties.setGateway(NetworkUtils.intToInetAddress(dhcpInfo.gateway));
263 InetAddress dns1Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns1);
264 if (dns1Addr == null || dns1Addr.equals("0.0.0.0")) {
265 mLinkProperties.addDns(dns1Addr);
266 }
267 InetAddress dns2Addr = NetworkUtils.intToInetAddress(dhcpInfo.dns2);
268 if (dns2Addr == null || dns2Addr.equals("0.0.0.0")) {
269 mLinkProperties.addDns(dns2Addr);
270 }
271 mLinkProperties.setInterfaceName(mIface);
272
273 mNetworkInfo.setIsAvailable(true);
274 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
275
276 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
277 msg.sendToTarget();
278
279 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
280 msg.sendToTarget();
281 }
282 });
283 dhcpThread.start();
284 }
285
286 public synchronized void stopReverseTether(String iface) {
287 NetworkUtils.stopDhcp(iface);
288
289 mLinkProperties.clear();
290 mNetworkInfo.setIsAvailable(false);
291 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
292
293 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
294 msg.sendToTarget();
295
296 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
297 msg.sendToTarget();
298 }
299}