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