blob: a7b00375e8413bd57052cc519d0f3a101459d65c [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;
Robert Greenwalt0216e612011-01-14 16:29:58 -080021import android.net.DhcpInfoInternal;
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080022import 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;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -080099 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
100 if (adapter != null) {
101 adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
102 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800103 }
104
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -0800105 private BluetoothProfile.ServiceListener mProfileServiceListener =
106 new BluetoothProfile.ServiceListener() {
107 public void onServiceConnected(int profile, BluetoothProfile proxy) {
108 mBluetoothPan = (BluetoothPan) proxy;
109 }
110 public void onServiceDisconnected(int profile) {
111 mBluetoothPan = null;
112 }
113 };
114
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800115 /**
116 * Disable connectivity to a network
117 * TODO: do away with return value after making MobileDataStateTracker async
118 */
119 public boolean teardown() {
120 mTeardownRequested.set(true);
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -0800121 if (mBluetoothPan != null) {
122 for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
123 mBluetoothPan.disconnect(device);
124 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800125 }
126 return true;
127 }
128
129 /**
130 * Re-enable connectivity to a network after a {@link #teardown()}.
131 */
132 public boolean reconnect() {
133 mTeardownRequested.set(false);
134 //Ignore
135 return true;
136 }
137
138 /**
139 * Turn the wireless radio off for a network.
140 * @param turnOn {@code true} to turn the radio on, {@code false}
141 */
142 public boolean setRadio(boolean turnOn) {
143 return true;
144 }
145
146 /**
147 * @return true - If are we currently tethered with another device.
148 */
149 public synchronized boolean isAvailable() {
150 return mNetworkInfo.isAvailable();
151 }
152
153 /**
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
165 */
166 public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
167 return -1;
168 }
169
170 /**
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
182 */
183 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
184 return -1;
185 }
186
187 /**
188 * @param enabled
189 */
190 public void setDataEnable(boolean enabled) {
191 android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled);
192 }
193
194 /**
195 * Check if private DNS route is set for the network
196 */
197 public boolean isPrivateDnsRouteSet() {
198 return mPrivateDnsRouteSet.get();
199 }
200
201 /**
202 * Set a flag indicating private DNS route is set
203 */
204 public void privateDnsRouteSet(boolean enabled) {
205 mPrivateDnsRouteSet.set(enabled);
206 }
207
208 /**
209 * Fetch NetworkInfo for the network
210 */
211 public synchronized NetworkInfo getNetworkInfo() {
212 return mNetworkInfo;
213 }
214
215 /**
216 * Fetch LinkProperties for the network
217 */
218 public synchronized LinkProperties getLinkProperties() {
219 return new LinkProperties(mLinkProperties);
220 }
221
222 /**
223 * A capability is an Integer/String pair, the capabilities
224 * are defined in the class LinkSocket#Key.
225 *
226 * @return a copy of this connections capabilities, may be empty but never null.
227 */
228 public LinkCapabilities getLinkCapabilities() {
229 return new LinkCapabilities(mLinkCapabilities);
230 }
231
232 /**
233 * Fetch default gateway address for the network
234 */
235 public int getDefaultGatewayAddr() {
236 return mDefaultGatewayAddr.get();
237 }
238
239 /**
240 * Check if default route is set
241 */
242 public boolean isDefaultRouteSet() {
243 return mDefaultRouteSet.get();
244 }
245
246 /**
247 * Set a flag indicating default route is set for the network
248 */
249 public void defaultRouteSet(boolean enabled) {
250 mDefaultRouteSet.set(enabled);
251 }
252
253 /**
254 * Return the system properties name associated with the tcp buffer sizes
255 * for this network.
256 */
257 public String getTcpBufferSizesPropName() {
258 return "net.tcp.buffersize.wifi";
259 }
260
261
262 public synchronized void startReverseTether(String iface, BluetoothDevice device) {
263 mIface = iface;
264 mDevice = device;
265 Thread dhcpThread = new Thread(new Runnable() {
266 public void run() {
267 //TODO(): Add callbacks for failure and success case.
268 //Currently this thread runs independently.
Robert Greenwalt0216e612011-01-14 16:29:58 -0800269 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
270 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800271 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
272 return;
273 }
Robert Greenwalt0216e612011-01-14 16:29:58 -0800274 mLinkProperties = dhcpInfoInternal.makeLinkProperties();
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800275 mLinkProperties.setInterfaceName(mIface);
276
277 mNetworkInfo.setIsAvailable(true);
278 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
279
280 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
281 msg.sendToTarget();
282
283 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
284 msg.sendToTarget();
285 }
286 });
287 dhcpThread.start();
288 }
289
290 public synchronized void stopReverseTether(String iface) {
291 NetworkUtils.stopDhcp(iface);
292
293 mLinkProperties.clear();
294 mNetworkInfo.setIsAvailable(false);
295 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
296
297 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
298 msg.sendToTarget();
299
300 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
301 msg.sendToTarget();
302 }
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700303
304 public void setDependencyMet(boolean met) {
305 // not supported on this network
306 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800307}