• 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.Messenger;
26 import android.os.RemoteException;
27 import android.os.ServiceManager;
28 import android.util.Log;
29 
30 import java.util.concurrent.atomic.AtomicBoolean;
31 import java.util.concurrent.atomic.AtomicInteger;
32 
33 /**
34  * This class tracks the data connection associated with Ethernet
35  * This is a singleton class and an instance will be created by
36  * ConnectivityService.
37  * @hide
38  */
39 public class EthernetDataTracker implements NetworkStateTracker {
40     private static final String NETWORKTYPE = "ETHERNET";
41     private static final String TAG = "Ethernet";
42 
43     private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
44     private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
45     private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
46     private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
47 
48     private static boolean mLinkUp;
49     private LinkProperties mLinkProperties;
50     private LinkCapabilities mLinkCapabilities;
51     private NetworkInfo mNetworkInfo;
52     private InterfaceObserver mInterfaceObserver;
53     private String mHwAddr;
54 
55     /* For sending events to connectivity service handler */
56     private Handler mCsHandler;
57     private Context mContext;
58 
59     private static EthernetDataTracker sInstance;
60     private static String sIfaceMatch = "";
61     private static String mIface = "";
62 
63     private INetworkManagementService mNMService;
64 
65     private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
66         private EthernetDataTracker mTracker;
67 
InterfaceObserver(EthernetDataTracker tracker)68         InterfaceObserver(EthernetDataTracker tracker) {
69             super();
70             mTracker = tracker;
71         }
72 
interfaceStatusChanged(String iface, boolean up)73         public void interfaceStatusChanged(String iface, boolean up) {
74             Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
75         }
76 
interfaceLinkStateChanged(String iface, boolean up)77         public void interfaceLinkStateChanged(String iface, boolean up) {
78             if (mIface.equals(iface)) {
79                 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
80                 mLinkUp = up;
81                 mTracker.mNetworkInfo.setIsAvailable(up);
82 
83                 // use DHCP
84                 if (up) {
85                     mTracker.reconnect();
86                 } else {
87                     mTracker.disconnect();
88                 }
89             }
90         }
91 
interfaceAdded(String iface)92         public void interfaceAdded(String iface) {
93             mTracker.interfaceAdded(iface);
94         }
95 
interfaceRemoved(String iface)96         public void interfaceRemoved(String iface) {
97             mTracker.interfaceRemoved(iface);
98         }
99 
limitReached(String limitName, String iface)100         public void limitReached(String limitName, String iface) {
101             // Ignored.
102         }
103 
interfaceClassDataActivityChanged(String label, boolean active)104         public void interfaceClassDataActivityChanged(String label, boolean active) {
105             // Ignored.
106         }
107     }
108 
EthernetDataTracker()109     private EthernetDataTracker() {
110         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
111         mLinkProperties = new LinkProperties();
112         mLinkCapabilities = new LinkCapabilities();
113     }
114 
interfaceAdded(String iface)115     private void interfaceAdded(String iface) {
116         if (!iface.matches(sIfaceMatch))
117             return;
118 
119         Log.d(TAG, "Adding " + iface);
120 
121         synchronized(this) {
122             if(!mIface.isEmpty())
123                 return;
124             mIface = iface;
125         }
126 
127         // we don't get link status indications unless the iface is up - bring it up
128         try {
129             mNMService.setInterfaceUp(iface);
130         } catch (Exception e) {
131             Log.e(TAG, "Error upping interface " + iface + ": " + e);
132         }
133 
134         mNetworkInfo.setIsAvailable(true);
135         Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
136         msg.sendToTarget();
137     }
138 
disconnect()139     public void disconnect() {
140 
141         NetworkUtils.stopDhcp(mIface);
142 
143         mLinkProperties.clear();
144         mNetworkInfo.setIsAvailable(false);
145         mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
146 
147         Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
148         msg.sendToTarget();
149 
150         msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
151         msg.sendToTarget();
152 
153         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
154         INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
155         try {
156             service.clearInterfaceAddresses(mIface);
157         } catch (Exception e) {
158             Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
159         }
160     }
161 
interfaceRemoved(String iface)162     private void interfaceRemoved(String iface) {
163         if (!iface.equals(mIface))
164             return;
165 
166         Log.d(TAG, "Removing " + iface);
167         disconnect();
168         mIface = "";
169     }
170 
runDhcp()171     private void runDhcp() {
172         Thread dhcpThread = new Thread(new Runnable() {
173             public void run() {
174                 DhcpResults dhcpResults = new DhcpResults();
175                 if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
176                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
177                     return;
178                 }
179                 mLinkProperties = dhcpResults.linkProperties;
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 
getInstance()189     public static synchronized EthernetDataTracker getInstance() {
190         if (sInstance == null) sInstance = new EthernetDataTracker();
191         return sInstance;
192     }
193 
Clone()194     public Object Clone() throws CloneNotSupportedException {
195         throw new CloneNotSupportedException();
196     }
197 
setTeardownRequested(boolean isRequested)198     public void setTeardownRequested(boolean isRequested) {
199         mTeardownRequested.set(isRequested);
200     }
201 
isTeardownRequested()202     public boolean isTeardownRequested() {
203         return mTeardownRequested.get();
204     }
205 
206     /**
207      * Begin monitoring connectivity
208      */
startMonitoring(Context context, Handler target)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      */
teardown()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      */
reconnect()269     public boolean reconnect() {
270         if (mLinkUp) {
271             mTeardownRequested.set(false);
272             runDhcp();
273         }
274         return mLinkUp;
275     }
276 
277     @Override
captivePortalCheckComplete()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      */
setRadio(boolean turnOn)286     public boolean setRadio(boolean turnOn) {
287         return true;
288     }
289 
290     /**
291      * @return true - If are we currently tethered with another device.
292      */
isAvailable()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      */
startUsingNetworkFeature(String feature, int callingPid, int callingUid)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      */
stopUsingNetworkFeature(String feature, int callingPid, int callingUid)327     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
328         return -1;
329     }
330 
331     @Override
setUserDataEnable(boolean enabled)332     public void setUserDataEnable(boolean enabled) {
333         Log.w(TAG, "ignoring setUserDataEnable(" + enabled + ")");
334     }
335 
336     @Override
setPolicyDataEnable(boolean enabled)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      */
isPrivateDnsRouteSet()344     public boolean isPrivateDnsRouteSet() {
345         return mPrivateDnsRouteSet.get();
346     }
347 
348     /**
349      * Set a flag indicating private DNS route is set
350      */
privateDnsRouteSet(boolean enabled)351     public void privateDnsRouteSet(boolean enabled) {
352         mPrivateDnsRouteSet.set(enabled);
353     }
354 
355     /**
356      * Fetch NetworkInfo for the network
357      */
getNetworkInfo()358     public synchronized NetworkInfo getNetworkInfo() {
359         return mNetworkInfo;
360     }
361 
362     /**
363      * Fetch LinkProperties for the network
364      */
getLinkProperties()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      */
getLinkCapabilities()375     public LinkCapabilities getLinkCapabilities() {
376         return new LinkCapabilities(mLinkCapabilities);
377     }
378 
379     /**
380      * Fetch default gateway address for the network
381      */
getDefaultGatewayAddr()382     public int getDefaultGatewayAddr() {
383         return mDefaultGatewayAddr.get();
384     }
385 
386     /**
387      * Check if default route is set
388      */
isDefaultRouteSet()389     public boolean isDefaultRouteSet() {
390         return mDefaultRouteSet.get();
391     }
392 
393     /**
394      * Set a flag indicating default route is set for the network
395      */
defaultRouteSet(boolean enabled)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      */
getTcpBufferSizesPropName()404     public String getTcpBufferSizesPropName() {
405         return "net.tcp.buffersize.wifi";
406     }
407 
setDependencyMet(boolean met)408     public void setDependencyMet(boolean met) {
409         // not supported on this network
410     }
411 
412     @Override
addStackedLink(LinkProperties link)413     public void addStackedLink(LinkProperties link) {
414         mLinkProperties.addStackedLink(link);
415     }
416 
417     @Override
removeStackedLink(LinkProperties link)418     public void removeStackedLink(LinkProperties link) {
419         mLinkProperties.removeStackedLink(link);
420     }
421 
422     @Override
supplyMessenger(Messenger messenger)423     public void supplyMessenger(Messenger messenger) {
424         // not supported on this network
425     }
426 }
427