blob: 83d1bda82100f4b07986fd327962113726163fd0 [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.LinkCapabilities;
23import android.net.LinkProperties;
24import android.net.NetworkInfo;
25import android.net.NetworkInfo.DetailedState;
26import android.net.NetworkStateTracker;
27import android.net.NetworkUtils;
28import android.os.Handler;
29import android.os.Message;
30import android.util.Log;
31
Jaikumar Ganesh15c74392010-12-21 22:31:44 -080032import java.util.concurrent.atomic.AtomicBoolean;
33import java.util.concurrent.atomic.AtomicInteger;
34
35/**
36 * This class tracks the data connection associated with Bluetooth
37 * reverse tethering. This is a singleton class and an instance will be
38 * created by ConnectivityService. BluetoothService will call into this
39 * when a reverse tethered connection needs to be activated.
40 *
41 * @hide
42 */
43public class BluetoothTetheringDataTracker implements NetworkStateTracker {
44 private static final String NETWORKTYPE = "BLUETOOTH_TETHER";
45 private static final String TAG = "BluetoothTethering";
46
47 private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
48 private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
49 private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
50 private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
51
52 private LinkProperties mLinkProperties;
53 private LinkCapabilities mLinkCapabilities;
54 private NetworkInfo mNetworkInfo;
55
56 private BluetoothPan mBluetoothPan;
57 private BluetoothDevice mDevice;
58 private static String mIface;
59
60 /* For sending events to connectivity service handler */
61 private Handler mCsHandler;
62 private Context mContext;
63 public static BluetoothTetheringDataTracker sInstance;
64
65 private BluetoothTetheringDataTracker() {
66 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, "");
67 mLinkProperties = new LinkProperties();
68 mLinkCapabilities = new LinkCapabilities();
69
70 mNetworkInfo.setIsAvailable(false);
71 setTeardownRequested(false);
72 }
73
74 public static synchronized BluetoothTetheringDataTracker getInstance() {
75 if (sInstance == null) sInstance = new BluetoothTetheringDataTracker();
76 return sInstance;
77 }
78
79 public Object Clone() throws CloneNotSupportedException {
80 throw new CloneNotSupportedException();
81 }
82
83 public void setTeardownRequested(boolean isRequested) {
84 mTeardownRequested.set(isRequested);
85 }
86
87 public boolean isTeardownRequested() {
88 return mTeardownRequested.get();
89 }
90
91 /**
92 * Begin monitoring connectivity
93 */
94 public void startMonitoring(Context context, Handler target) {
95 mContext = context;
96 mCsHandler = target;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -080097 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
98 if (adapter != null) {
99 adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
100 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800101 }
102
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -0800103 private BluetoothProfile.ServiceListener mProfileServiceListener =
104 new BluetoothProfile.ServiceListener() {
105 public void onServiceConnected(int profile, BluetoothProfile proxy) {
106 mBluetoothPan = (BluetoothPan) proxy;
107 }
108 public void onServiceDisconnected(int profile) {
109 mBluetoothPan = null;
110 }
111 };
112
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800113 /**
114 * Disable connectivity to a network
115 * TODO: do away with return value after making MobileDataStateTracker async
116 */
117 public boolean teardown() {
118 mTeardownRequested.set(true);
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -0800119 if (mBluetoothPan != null) {
120 for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
121 mBluetoothPan.disconnect(device);
122 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800123 }
124 return true;
125 }
126
127 /**
128 * Re-enable connectivity to a network after a {@link #teardown()}.
129 */
130 public boolean reconnect() {
131 mTeardownRequested.set(false);
132 //Ignore
133 return true;
134 }
135
136 /**
137 * Turn the wireless radio off for a network.
138 * @param turnOn {@code true} to turn the radio on, {@code false}
139 */
140 public boolean setRadio(boolean turnOn) {
141 return true;
142 }
143
144 /**
145 * @return true - If are we currently tethered with another device.
146 */
147 public synchronized boolean isAvailable() {
148 return mNetworkInfo.isAvailable();
149 }
150
151 /**
152 * Tells the underlying networking system that the caller wants to
153 * begin using the named feature. The interpretation of {@code feature}
154 * is completely up to each networking implementation.
155 * @param feature the name of the feature to be used
156 * @param callingPid the process ID of the process that is issuing this request
157 * @param callingUid the user ID of the process that is issuing this request
158 * @return an integer value representing the outcome of the request.
159 * The interpretation of this value is specific to each networking
160 * implementation+feature combination, except that the value {@code -1}
161 * always indicates failure.
162 * TODO: needs to go away
163 */
164 public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
165 return -1;
166 }
167
168 /**
169 * Tells the underlying networking system that the caller is finished
170 * using the named feature. The interpretation of {@code feature}
171 * is completely up to each networking implementation.
172 * @param feature the name of the feature that is no longer needed.
173 * @param callingPid the process ID of the process that is issuing this request
174 * @param callingUid the user ID of the process that is issuing this request
175 * @return an integer value representing the outcome of the request.
176 * The interpretation of this value is specific to each networking
177 * implementation+feature combination, except that the value {@code -1}
178 * always indicates failure.
179 * TODO: needs to go away
180 */
181 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
182 return -1;
183 }
184
Jeff Sharkey8e28b7d2011-08-19 02:24:24 -0700185 @Override
186 public void setUserDataEnable(boolean enabled) {
187 Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
188 }
189
190 @Override
191 public void setPolicyDataEnable(boolean enabled) {
192 Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800193 }
194
195 /**
196 * Check if private DNS route is set for the network
197 */
198 public boolean isPrivateDnsRouteSet() {
199 return mPrivateDnsRouteSet.get();
200 }
201
202 /**
203 * Set a flag indicating private DNS route is set
204 */
205 public void privateDnsRouteSet(boolean enabled) {
206 mPrivateDnsRouteSet.set(enabled);
207 }
208
209 /**
210 * Fetch NetworkInfo for the network
211 */
212 public synchronized NetworkInfo getNetworkInfo() {
213 return mNetworkInfo;
214 }
215
216 /**
217 * Fetch LinkProperties for the network
218 */
219 public synchronized LinkProperties getLinkProperties() {
220 return new LinkProperties(mLinkProperties);
221 }
222
223 /**
224 * A capability is an Integer/String pair, the capabilities
225 * are defined in the class LinkSocket#Key.
226 *
227 * @return a copy of this connections capabilities, may be empty but never null.
228 */
229 public LinkCapabilities getLinkCapabilities() {
230 return new LinkCapabilities(mLinkCapabilities);
231 }
232
233 /**
234 * Fetch default gateway address for the network
235 */
236 public int getDefaultGatewayAddr() {
237 return mDefaultGatewayAddr.get();
238 }
239
240 /**
241 * Check if default route is set
242 */
243 public boolean isDefaultRouteSet() {
244 return mDefaultRouteSet.get();
245 }
246
247 /**
248 * Set a flag indicating default route is set for the network
249 */
250 public void defaultRouteSet(boolean enabled) {
251 mDefaultRouteSet.set(enabled);
252 }
253
254 /**
255 * Return the system properties name associated with the tcp buffer sizes
256 * for this network.
257 */
258 public String getTcpBufferSizesPropName() {
259 return "net.tcp.buffersize.wifi";
260 }
261
262
263 public synchronized void startReverseTether(String iface, BluetoothDevice device) {
264 mIface = iface;
265 mDevice = device;
266 Thread dhcpThread = new Thread(new Runnable() {
267 public void run() {
268 //TODO(): Add callbacks for failure and success case.
269 //Currently this thread runs independently.
Robert Greenwalt0216e612011-01-14 16:29:58 -0800270 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
271 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800272 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
273 return;
274 }
Robert Greenwalt0216e612011-01-14 16:29:58 -0800275 mLinkProperties = dhcpInfoInternal.makeLinkProperties();
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800276 mLinkProperties.setInterfaceName(mIface);
277
278 mNetworkInfo.setIsAvailable(true);
279 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
280
281 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
282 msg.sendToTarget();
283
284 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
285 msg.sendToTarget();
286 }
287 });
288 dhcpThread.start();
289 }
290
291 public synchronized void stopReverseTether(String iface) {
292 NetworkUtils.stopDhcp(iface);
293
294 mLinkProperties.clear();
295 mNetworkInfo.setIsAvailable(false);
296 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
297
298 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
299 msg.sendToTarget();
300
301 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
302 msg.sendToTarget();
303 }
Robert Greenwaltd55a6b42011-03-25 13:09:25 -0700304
305 public void setDependencyMet(boolean met) {
306 // not supported on this network
307 }
Jaikumar Ganesh15c74392010-12-21 22:31:44 -0800308}