blob: cc8c77193eca8758f2d759f94e0dd1b506f5d0a0 [file] [log] [blame]
Benoit Goby19970692010-12-22 14:29:40 -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.net;
18
19import android.content.Context;
Benoit Goby19970692010-12-22 14:29:40 -080020import android.net.NetworkInfo.DetailedState;
Benoit Goby19970692010-12-22 14:29:40 -080021import android.os.Handler;
22import android.os.IBinder;
23import android.os.INetworkManagementService;
24import android.os.Message;
Robert Greenwalt665e1ae2012-08-21 19:27:00 -070025import android.os.Messenger;
Benoit Goby19970692010-12-22 14:29:40 -080026import android.os.RemoteException;
27import android.os.ServiceManager;
28import android.util.Log;
29
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090030import com.android.server.net.BaseNetworkObserver;
31
Benoit Goby19970692010-12-22 14:29:40 -080032import java.util.concurrent.atomic.AtomicBoolean;
33import java.util.concurrent.atomic.AtomicInteger;
34
35/**
36 * This class tracks the data connection associated with Ethernet
37 * This is a singleton class and an instance will be created by
38 * ConnectivityService.
39 * @hide
40 */
Vinit Deshapnde1f12cb52013-08-21 13:09:01 -070041public class EthernetDataTracker extends BaseNetworkStateTracker {
Benoit Goby19970692010-12-22 14:29:40 -080042 private static final String NETWORKTYPE = "ETHERNET";
43 private static final String TAG = "Ethernet";
44
45 private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
46 private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
47 private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
48 private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
49
Mike J. Chenf59c7d02011-06-23 15:33:15 -070050 private static boolean mLinkUp;
Benoit Goby19970692010-12-22 14:29:40 -080051 private InterfaceObserver mInterfaceObserver;
Doug Zongkerd60ae7f2011-11-03 12:45:42 -070052 private String mHwAddr;
Benoit Goby19970692010-12-22 14:29:40 -080053
54 /* For sending events to connectivity service handler */
55 private Handler mCsHandler;
Benoit Goby19970692010-12-22 14:29:40 -080056
57 private static EthernetDataTracker sInstance;
Mike J. Chenc96a6672011-06-13 13:19:43 -070058 private static String sIfaceMatch = "";
Benoit Goby19970692010-12-22 14:29:40 -080059 private static String mIface = "";
60
Robert Greenwalt198bc112012-05-07 12:34:26 -070061 private INetworkManagementService mNMService;
62
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090063 private static class InterfaceObserver extends BaseNetworkObserver {
Benoit Goby19970692010-12-22 14:29:40 -080064 private EthernetDataTracker mTracker;
65
66 InterfaceObserver(EthernetDataTracker tracker) {
67 super();
68 mTracker = tracker;
69 }
70
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090071 @Override
Mike J. Chenf59c7d02011-06-23 15:33:15 -070072 public void interfaceStatusChanged(String iface, boolean up) {
73 Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
74 }
75
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090076 @Override
Mike J. Chenf59c7d02011-06-23 15:33:15 -070077 public void interfaceLinkStateChanged(String iface, boolean up) {
Adam Hampson6a9d5762012-12-05 10:29:23 -080078 if (mIface.equals(iface)) {
Mike J. Chenf59c7d02011-06-23 15:33:15 -070079 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
80 mLinkUp = up;
Mike Lockwoodefeba012011-12-15 12:21:26 -050081 mTracker.mNetworkInfo.setIsAvailable(up);
Mike J. Chenf59c7d02011-06-23 15:33:15 -070082
83 // use DHCP
84 if (up) {
85 mTracker.reconnect();
86 } else {
Mike J. Chen4bcbefd2011-09-30 18:05:44 -070087 mTracker.disconnect();
Mike J. Chenf59c7d02011-06-23 15:33:15 -070088 }
89 }
Benoit Goby19970692010-12-22 14:29:40 -080090 }
91
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090092 @Override
Benoit Goby19970692010-12-22 14:29:40 -080093 public void interfaceAdded(String iface) {
94 mTracker.interfaceAdded(iface);
95 }
96
Lorenzo Colittidf86a9f2013-08-20 19:51:30 +090097 @Override
Benoit Goby19970692010-12-22 14:29:40 -080098 public void interfaceRemoved(String iface) {
99 mTracker.interfaceRemoved(iface);
100 }
101 }
102
103 private EthernetDataTracker() {
104 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
105 mLinkProperties = new LinkProperties();
106 mLinkCapabilities = new LinkCapabilities();
Benoit Goby19970692010-12-22 14:29:40 -0800107 }
108
109 private void interfaceAdded(String iface) {
Mike J. Chenc96a6672011-06-13 13:19:43 -0700110 if (!iface.matches(sIfaceMatch))
Benoit Goby19970692010-12-22 14:29:40 -0800111 return;
112
113 Log.d(TAG, "Adding " + iface);
114
Mike Lockwoodefeba012011-12-15 12:21:26 -0500115 synchronized(this) {
Benoit Goby19970692010-12-22 14:29:40 -0800116 if(!mIface.isEmpty())
117 return;
118 mIface = iface;
119 }
120
Robert Greenwalt198bc112012-05-07 12:34:26 -0700121 // we don't get link status indications unless the iface is up - bring it up
122 try {
123 mNMService.setInterfaceUp(iface);
124 } catch (Exception e) {
125 Log.e(TAG, "Error upping interface " + iface + ": " + e);
126 }
127
Benoit Goby19970692010-12-22 14:29:40 -0800128 mNetworkInfo.setIsAvailable(true);
129 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
130 msg.sendToTarget();
Benoit Goby19970692010-12-22 14:29:40 -0800131 }
132
Mike J. Chen4bcbefd2011-09-30 18:05:44 -0700133 public void disconnect() {
Benoit Goby19970692010-12-22 14:29:40 -0800134
135 NetworkUtils.stopDhcp(mIface);
136
137 mLinkProperties.clear();
138 mNetworkInfo.setIsAvailable(false);
Doug Zongkerd60ae7f2011-11-03 12:45:42 -0700139 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr);
Benoit Goby19970692010-12-22 14:29:40 -0800140
141 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
142 msg.sendToTarget();
143
144 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
145 msg.sendToTarget();
146
Mike J. Chen4bcbefd2011-09-30 18:05:44 -0700147 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
148 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
149 try {
150 service.clearInterfaceAddresses(mIface);
151 } catch (Exception e) {
152 Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
153 }
154 }
155
156 private void interfaceRemoved(String iface) {
157 if (!iface.equals(mIface))
158 return;
159
160 Log.d(TAG, "Removing " + iface);
Mike Lockwoodefeba012011-12-15 12:21:26 -0500161 disconnect();
Benoit Goby19970692010-12-22 14:29:40 -0800162 mIface = "";
163 }
164
165 private void runDhcp() {
166 Thread dhcpThread = new Thread(new Runnable() {
167 public void run() {
Robert Greenwalt4717c262012-10-31 14:32:53 -0700168 DhcpResults dhcpResults = new DhcpResults();
169 if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
Benoit Goby19970692010-12-22 14:29:40 -0800170 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
171 return;
172 }
Robert Greenwalt4717c262012-10-31 14:32:53 -0700173 mLinkProperties = dhcpResults.linkProperties;
Benoit Goby19970692010-12-22 14:29:40 -0800174
Peter YOON0c0f9532013-03-11 14:53:37 +0900175 mNetworkInfo.setIsAvailable(true);
Doug Zongkerd60ae7f2011-11-03 12:45:42 -0700176 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
Benoit Goby19970692010-12-22 14:29:40 -0800177 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
178 msg.sendToTarget();
179 }
180 });
181 dhcpThread.start();
182 }
183
184 public static synchronized EthernetDataTracker getInstance() {
185 if (sInstance == null) sInstance = new EthernetDataTracker();
186 return sInstance;
187 }
188
189 public Object Clone() throws CloneNotSupportedException {
190 throw new CloneNotSupportedException();
191 }
192
193 public void setTeardownRequested(boolean isRequested) {
194 mTeardownRequested.set(isRequested);
195 }
196
197 public boolean isTeardownRequested() {
198 return mTeardownRequested.get();
199 }
200
201 /**
202 * Begin monitoring connectivity
203 */
204 public void startMonitoring(Context context, Handler target) {
205 mContext = context;
206 mCsHandler = target;
207
208 // register for notifications from NetworkManagement Service
209 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
Robert Greenwalt198bc112012-05-07 12:34:26 -0700210 mNMService = INetworkManagementService.Stub.asInterface(b);
Mike J. Chenc96a6672011-06-13 13:19:43 -0700211
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700212 mInterfaceObserver = new InterfaceObserver(this);
213
214 // enable and try to connect to an ethernet interface that
215 // already exists
Mike J. Chenc96a6672011-06-13 13:19:43 -0700216 sIfaceMatch = context.getResources().getString(
217 com.android.internal.R.string.config_ethernet_iface_regex);
218 try {
Robert Greenwalt198bc112012-05-07 12:34:26 -0700219 final String[] ifaces = mNMService.listInterfaces();
Mike J. Chenc96a6672011-06-13 13:19:43 -0700220 for (String iface : ifaces) {
221 if (iface.matches(sIfaceMatch)) {
222 mIface = iface;
Robert Greenwalt198bc112012-05-07 12:34:26 -0700223 mNMService.setInterfaceUp(iface);
224 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
Vishal Mahaveerb6b72f52012-09-11 16:41:16 -0500225 mLinkUp = config.hasFlag("up");
Doug Zongkerd60ae7f2011-11-03 12:45:42 -0700226 if (config != null && mHwAddr == null) {
Mike Lockwoodefeba012011-12-15 12:21:26 -0500227 mHwAddr = config.getHardwareAddress();
Doug Zongkerd60ae7f2011-11-03 12:45:42 -0700228 if (mHwAddr != null) {
229 mNetworkInfo.setExtraInfo(mHwAddr);
230 }
231 }
Jason Simmons1d28fef2012-06-14 11:16:14 -0700232
233 // if a DHCP client had previously been started for this interface, then stop it
234 NetworkUtils.stopDhcp(mIface);
235
Mike J. Chenc96a6672011-06-13 13:19:43 -0700236 reconnect();
237 break;
238 }
239 }
240 } catch (RemoteException e) {
241 Log.e(TAG, "Could not get list of interfaces " + e);
242 }
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700243
244 try {
Robert Greenwalt198bc112012-05-07 12:34:26 -0700245 mNMService.registerObserver(mInterfaceObserver);
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700246 } catch (RemoteException e) {
247 Log.e(TAG, "Could not register InterfaceObserver " + e);
248 }
Benoit Goby19970692010-12-22 14:29:40 -0800249 }
250
251 /**
252 * Disable connectivity to a network
253 * TODO: do away with return value after making MobileDataStateTracker async
254 */
255 public boolean teardown() {
256 mTeardownRequested.set(true);
257 NetworkUtils.stopDhcp(mIface);
258 return true;
259 }
260
261 /**
262 * Re-enable connectivity to a network after a {@link #teardown()}.
263 */
264 public boolean reconnect() {
Mike Lockwoodefeba012011-12-15 12:21:26 -0500265 if (mLinkUp) {
266 mTeardownRequested.set(false);
267 runDhcp();
268 }
269 return mLinkUp;
Benoit Goby19970692010-12-22 14:29:40 -0800270 }
271
Irfan Sheriffda6da092012-08-16 12:49:23 -0700272 @Override
273 public void captivePortalCheckComplete() {
274 // not implemented
275 }
276
Wink Savilled747cbc2013-08-07 16:22:47 -0700277 @Override
278 public void captivePortalCheckCompleted(boolean isCaptivePortal) {
279 // not implemented
280 }
281
Benoit Goby19970692010-12-22 14:29:40 -0800282 /**
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
Jeff Sharkey8e28b7d2011-08-19 02:24:24 -0700331 @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 + ")");
Benoit Goby19970692010-12-22 14:29:40 -0800339 }
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() {
Jianzheng Zhoua363a102013-11-15 13:32:23 +0800405 return "net.tcp.buffersize.ethernet";
Benoit Goby19970692010-12-22 14:29:40 -0800406 }
Robert Greenwaltaf6eddb2011-04-07 15:44:10 -0700407
408 public void setDependencyMet(boolean met) {
409 // not supported on this network
410 }
Lorenzo Colitti69edd642013-03-07 11:01:12 -0800411
412 @Override
413 public void addStackedLink(LinkProperties link) {
414 mLinkProperties.addStackedLink(link);
415 }
416
417 @Override
418 public void removeStackedLink(LinkProperties link) {
419 mLinkProperties.removeStackedLink(link);
420 }
Robert Greenwalt665e1ae2012-08-21 19:27:00 -0700421
422 @Override
423 public void supplyMessenger(Messenger messenger) {
424 // not supported on this network
425 }
Benoit Goby19970692010-12-22 14:29:40 -0800426}