OSDN Git Service

Merge "cherrypick from master: Change-Id: I169749dc594ca1d79a802db4c53ec330924fdd2c...
[android-x86/frameworks-base.git] / core / java / android / bluetooth / BluetoothTetheringDataTracker.java
1 /*
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
17 package android.bluetooth;
18
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;
32
33 import java.net.InetAddress;
34 import java.util.concurrent.atomic.AtomicBoolean;
35 import 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  */
45 public 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         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
100         if (adapter != null) {
101             adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN);
102         }
103     }
104
105     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
115     /**
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);
121         if (mBluetoothPan != null) {
122             for (BluetoothDevice device: mBluetoothPan.getConnectedDevices()) {
123                 mBluetoothPan.disconnect(device);
124             }
125         }
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.
269                 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
270                 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
271                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
272                     return;
273                 }
274                 mLinkProperties = dhcpInfoInternal.makeLinkProperties();
275                 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     }
303 }