OSDN Git Service

Merge "add Toshiba usb driver link delete Fujitsu-Toshiba bug: 9755017" into jb-mr1...
[android-x86/frameworks-base.git] / core / java / android / net / EthernetDataTracker.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.net;
18
19 import android.content.Context;
20 import android.net.NetworkInfo.DetailedState;
21 import android.os.Handler;
22 import android.os.IBinder;
23 import android.os.INetworkManagementService;
24 import android.os.Message;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
27 import android.util.Log;
28
29 import java.util.concurrent.atomic.AtomicBoolean;
30 import java.util.concurrent.atomic.AtomicInteger;
31
32 /**
33  * This class tracks the data connection associated with Ethernet
34  * This is a singleton class and an instance will be created by
35  * ConnectivityService.
36  * @hide
37  */
38 public class EthernetDataTracker implements NetworkStateTracker {
39     private static final String NETWORKTYPE = "ETHERNET";
40     private static final String TAG = "Ethernet";
41
42     private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
43     private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
44     private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
45     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
46
47     private static boolean mLinkUp;
48     private LinkProperties mLinkProperties;
49     private LinkCapabilities mLinkCapabilities;
50     private NetworkInfo mNetworkInfo;
51     private InterfaceObserver mInterfaceObserver;
52     private String mHwAddr;
53
54     /* For sending events to connectivity service handler */
55     private Handler mCsHandler;
56     private Context mContext;
57
58     private static EthernetDataTracker sInstance;
59     private static String sIfaceMatch = "";
60     private static String mIface = "";
61
62     private INetworkManagementService mNMService;
63
64     private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
65         private EthernetDataTracker mTracker;
66
67         InterfaceObserver(EthernetDataTracker tracker) {
68             super();
69             mTracker = tracker;
70         }
71
72         public void interfaceStatusChanged(String iface, boolean up) {
73             Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
74         }
75
76         public void interfaceLinkStateChanged(String iface, boolean up) {
77             if (mIface.equals(iface) && mLinkUp != up) {
78                 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
79                 mLinkUp = up;
80                 mTracker.mNetworkInfo.setIsAvailable(up);
81
82                 // use DHCP
83                 if (up) {
84                     mTracker.reconnect();
85                 } else {
86                     mTracker.disconnect();
87                 }
88             }
89         }
90
91         public void interfaceAdded(String iface) {
92             mTracker.interfaceAdded(iface);
93         }
94
95         public void interfaceRemoved(String iface) {
96             mTracker.interfaceRemoved(iface);
97         }
98
99         public void limitReached(String limitName, String iface) {
100             // Ignored.
101         }
102
103         public void interfaceClassDataActivityChanged(String label, boolean active) {
104             // Ignored.
105         }
106     }
107
108     private EthernetDataTracker() {
109         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
110         mLinkProperties = new LinkProperties();
111         mLinkCapabilities = new LinkCapabilities();
112     }
113
114     private void interfaceAdded(String iface) {
115         if (!iface.matches(sIfaceMatch))
116             return;
117
118         Log.d(TAG, "Adding " + iface);
119
120         synchronized(this) {
121             if(!mIface.isEmpty())
122                 return;
123             mIface = iface;
124         }
125
126         // we don't get link status indications unless the iface is up - bring it up
127         try {
128             mNMService.setInterfaceUp(iface);
129         } catch (Exception e) {
130             Log.e(TAG, "Error upping interface " + iface + ": " + e);
131         }
132
133         mNetworkInfo.setIsAvailable(true);
134         Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
135         msg.sendToTarget();
136     }
137
138     public void disconnect() {
139
140         NetworkUtils.stopDhcp(mIface);
141
142         mLinkProperties.clear();
143         mNetworkInfo.setIsAvailable(false);
144         mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
145
146         Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
147         msg.sendToTarget();
148
149         msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
150         msg.sendToTarget();
151
152         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
153         INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
154         try {
155             service.clearInterfaceAddresses(mIface);
156         } catch (Exception e) {
157             Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
158         }
159     }
160
161     private void interfaceRemoved(String iface) {
162         if (!iface.equals(mIface))
163             return;
164
165         Log.d(TAG, "Removing " + iface);
166         disconnect();
167         mIface = "";
168     }
169
170     private void runDhcp() {
171         Thread dhcpThread = new Thread(new Runnable() {
172             public void run() {
173                 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
174                 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
175                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
176                     return;
177                 }
178                 mLinkProperties = dhcpInfoInternal.makeLinkProperties();
179                 mLinkProperties.setInterfaceName(mIface);
180
181                 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
182                 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
183                 msg.sendToTarget();
184             }
185         });
186         dhcpThread.start();
187     }
188
189     public static synchronized EthernetDataTracker getInstance() {
190         if (sInstance == null) sInstance = new EthernetDataTracker();
191         return sInstance;
192     }
193
194     public Object Clone() throws CloneNotSupportedException {
195         throw new CloneNotSupportedException();
196     }
197
198     public void setTeardownRequested(boolean isRequested) {
199         mTeardownRequested.set(isRequested);
200     }
201
202     public boolean isTeardownRequested() {
203         return mTeardownRequested.get();
204     }
205
206     /**
207      * Begin monitoring connectivity
208      */
209     public void startMonitoring(Context context, Handler target) {
210         mContext = context;
211         mCsHandler = target;
212
213         // register for notifications from NetworkManagement Service
214         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
215         mNMService = INetworkManagementService.Stub.asInterface(b);
216
217         mInterfaceObserver = new InterfaceObserver(this);
218
219         // enable and try to connect to an ethernet interface that
220         // already exists
221         sIfaceMatch = context.getResources().getString(
222             com.android.internal.R.string.config_ethernet_iface_regex);
223         try {
224             final String[] ifaces = mNMService.listInterfaces();
225             for (String iface : ifaces) {
226                 if (iface.matches(sIfaceMatch)) {
227                     mIface = iface;
228                     mNMService.setInterfaceUp(iface);
229                     InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
230                     mLinkUp = config.hasFlag("up");
231                     if (config != null && mHwAddr == null) {
232                         mHwAddr = config.getHardwareAddress();
233                         if (mHwAddr != null) {
234                             mNetworkInfo.setExtraInfo(mHwAddr);
235                         }
236                     }
237
238                     // if a DHCP client had previously been started for this interface, then stop it
239                     NetworkUtils.stopDhcp(mIface);
240
241                     reconnect();
242                     break;
243                 }
244             }
245         } catch (RemoteException e) {
246             Log.e(TAG, "Could not get list of interfaces " + e);
247         }
248
249         try {
250             mNMService.registerObserver(mInterfaceObserver);
251         } catch (RemoteException e) {
252             Log.e(TAG, "Could not register InterfaceObserver " + e);
253         }
254     }
255
256     /**
257      * Disable connectivity to a network
258      * TODO: do away with return value after making MobileDataStateTracker async
259      */
260     public boolean teardown() {
261         mTeardownRequested.set(true);
262         NetworkUtils.stopDhcp(mIface);
263         return true;
264     }
265
266     /**
267      * Re-enable connectivity to a network after a {@link #teardown()}.
268      */
269     public boolean reconnect() {
270         if (mLinkUp) {
271             mTeardownRequested.set(false);
272             runDhcp();
273         }
274         return mLinkUp;
275     }
276
277     @Override
278     public void captivePortalCheckComplete() {
279         // not implemented
280     }
281
282     /**
283      * Turn the wireless radio off for a network.
284      * @param turnOn {@code true} to turn the radio on, {@code false}
285      */
286     public boolean setRadio(boolean turnOn) {
287         return true;
288     }
289
290     /**
291      * @return true - If are we currently tethered with another device.
292      */
293     public synchronized boolean isAvailable() {
294         return mNetworkInfo.isAvailable();
295     }
296
297     /**
298      * Tells the underlying networking system that the caller wants to
299      * begin using the named feature. The interpretation of {@code feature}
300      * is completely up to each networking implementation.
301      * @param feature the name of the feature to be used
302      * @param callingPid the process ID of the process that is issuing this request
303      * @param callingUid the user ID of the process that is issuing this request
304      * @return an integer value representing the outcome of the request.
305      * The interpretation of this value is specific to each networking
306      * implementation+feature combination, except that the value {@code -1}
307      * always indicates failure.
308      * TODO: needs to go away
309      */
310     public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
311         return -1;
312     }
313
314     /**
315      * Tells the underlying networking system that the caller is finished
316      * using the named feature. The interpretation of {@code feature}
317      * is completely up to each networking implementation.
318      * @param feature the name of the feature that is no longer needed.
319      * @param callingPid the process ID of the process that is issuing this request
320      * @param callingUid the user ID of the process that is issuing this request
321      * @return an integer value representing the outcome of the request.
322      * The interpretation of this value is specific to each networking
323      * implementation+feature combination, except that the value {@code -1}
324      * always indicates failure.
325      * TODO: needs to go away
326      */
327     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
328         return -1;
329     }
330
331     @Override
332     public void setUserDataEnable(boolean enabled) {
333         Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
334     }
335
336     @Override
337     public void setPolicyDataEnable(boolean enabled) {
338         Log.w(TAG, "ignoring setPolicyDataEnable(" + enabled + ")");
339     }
340
341     /**
342      * Check if private DNS route is set for the network
343      */
344     public boolean isPrivateDnsRouteSet() {
345         return mPrivateDnsRouteSet.get();
346     }
347
348     /**
349      * Set a flag indicating private DNS route is set
350      */
351     public void privateDnsRouteSet(boolean enabled) {
352         mPrivateDnsRouteSet.set(enabled);
353     }
354
355     /**
356      * Fetch NetworkInfo for the network
357      */
358     public synchronized NetworkInfo getNetworkInfo() {
359         return mNetworkInfo;
360     }
361
362     /**
363      * Fetch LinkProperties for the network
364      */
365     public synchronized LinkProperties getLinkProperties() {
366         return new LinkProperties(mLinkProperties);
367     }
368
369    /**
370      * A capability is an Integer/String pair, the capabilities
371      * are defined in the class LinkSocket#Key.
372      *
373      * @return a copy of this connections capabilities, may be empty but never null.
374      */
375     public LinkCapabilities getLinkCapabilities() {
376         return new LinkCapabilities(mLinkCapabilities);
377     }
378
379     /**
380      * Fetch default gateway address for the network
381      */
382     public int getDefaultGatewayAddr() {
383         return mDefaultGatewayAddr.get();
384     }
385
386     /**
387      * Check if default route is set
388      */
389     public boolean isDefaultRouteSet() {
390         return mDefaultRouteSet.get();
391     }
392
393     /**
394      * Set a flag indicating default route is set for the network
395      */
396     public void defaultRouteSet(boolean enabled) {
397         mDefaultRouteSet.set(enabled);
398     }
399
400     /**
401      * Return the system properties name associated with the tcp buffer sizes
402      * for this network.
403      */
404     public String getTcpBufferSizesPropName() {
405         return "net.tcp.buffersize.wifi";
406     }
407
408     public void setDependencyMet(boolean met) {
409         // not supported on this network
410     }
411 }