From 08c39c6a11f728e113811a6a85c109cfc80ce28e Mon Sep 17 00:00:00 2001 From: Benoit Goby Date: Wed, 22 Dec 2010 14:29:40 -0800 Subject: Add support for USB Ethernet adapters Change-Id: I6ae34a32d0e1b6f21c484b8639c3e7ce086e568d --- core/java/android/net/ConnectivityManager.java | 4 +- core/java/android/net/EthernetDataTracker.java | 333 +++++++++++++++++++++ .../com/android/server/ConnectivityService.java | 5 + 3 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 core/java/android/net/EthernetDataTracker.java diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index cab8ed2..491c73a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -224,9 +224,9 @@ public class ConnectivityManager /** {@hide} */ public static final int TYPE_ETHERNET = 9; /** {@hide} TODO: Need to adjust this for WiMAX. */ - public static final int MAX_RADIO_TYPE = TYPE_DUMMY; + public static final int MAX_RADIO_TYPE = TYPE_ETHERNET; /** {@hide} TODO: Need to adjust this for WiMAX. */ - public static final int MAX_NETWORK_TYPE = TYPE_DUMMY; + public static final int MAX_NETWORK_TYPE = TYPE_ETHERNET; public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI; diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java new file mode 100644 index 0000000..df5fdd0 --- /dev/null +++ b/core/java/android/net/EthernetDataTracker.java @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.DhcpInfoInternal; +import android.net.LinkAddress; +import android.net.LinkCapabilities; +import android.net.LinkProperties; +import android.net.NetworkInfo; +import android.net.NetworkInfo.DetailedState; +import android.net.NetworkStateTracker; +import android.net.NetworkUtils; +import android.os.Handler; +import android.os.IBinder; +import android.os.INetworkManagementService; +import android.os.Message; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import java.net.InetAddress; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * This class tracks the data connection associated with Ethernet + * This is a singleton class and an instance will be created by + * ConnectivityService. + * @hide + */ +public class EthernetDataTracker implements NetworkStateTracker { + private static final String NETWORKTYPE = "ETHERNET"; + private static final String TAG = "Ethernet"; + + private AtomicBoolean mTeardownRequested = new AtomicBoolean(false); + private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false); + private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); + private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false); + + private LinkProperties mLinkProperties; + private LinkCapabilities mLinkCapabilities; + private NetworkInfo mNetworkInfo; + private InterfaceObserver mInterfaceObserver; + + /* For sending events to connectivity service handler */ + private Handler mCsHandler; + private Context mContext; + + private static EthernetDataTracker sInstance; + private static String mIface = ""; + + private static class InterfaceObserver extends INetworkManagementEventObserver.Stub { + private EthernetDataTracker mTracker; + + InterfaceObserver(EthernetDataTracker tracker) { + super(); + mTracker = tracker; + } + + public void interfaceLinkStatusChanged(String iface, boolean up) { + Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down")); + } + + public void interfaceAdded(String iface) { + mTracker.interfaceAdded(iface); + } + + public void interfaceRemoved(String iface) { + mTracker.interfaceRemoved(iface); + } + } + + private EthernetDataTracker() { + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, ""); + mLinkProperties = new LinkProperties(); + mLinkCapabilities = new LinkCapabilities(); + + mNetworkInfo.setIsAvailable(false); + setTeardownRequested(false); + } + + private void interfaceAdded(String iface) { + if (!iface.matches("eth\\d")) + return; + + Log.d(TAG, "Adding " + iface); + + synchronized(mIface) { + if(!mIface.isEmpty()) + return; + mIface = iface; + } + + mNetworkInfo.setIsAvailable(true); + Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); + msg.sendToTarget(); + + runDhcp(); + } + + private void interfaceRemoved(String iface) { + if (!iface.equals(mIface)) + return; + + Log.d(TAG, "Removing " + iface); + + NetworkUtils.stopDhcp(mIface); + + mLinkProperties.clear(); + mNetworkInfo.setIsAvailable(false); + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); + + Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); + msg.sendToTarget(); + + msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); + msg.sendToTarget(); + + mIface = ""; + } + + private void runDhcp() { + Thread dhcpThread = new Thread(new Runnable() { + public void run() { + DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); + if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) { + Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); + return; + } + mLinkProperties = dhcpInfoInternal.makeLinkProperties(); + mLinkProperties.setInterfaceName(mIface); + + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); + Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); + msg.sendToTarget(); + } + }); + dhcpThread.start(); + } + + public static synchronized EthernetDataTracker getInstance() { + if (sInstance == null) sInstance = new EthernetDataTracker(); + return sInstance; + } + + public Object Clone() throws CloneNotSupportedException { + throw new CloneNotSupportedException(); + } + + public void setTeardownRequested(boolean isRequested) { + mTeardownRequested.set(isRequested); + } + + public boolean isTeardownRequested() { + return mTeardownRequested.get(); + } + + /** + * Begin monitoring connectivity + */ + public void startMonitoring(Context context, Handler target) { + mContext = context; + mCsHandler = target; + + // register for notifications from NetworkManagement Service + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); + mInterfaceObserver = new InterfaceObserver(this); + try { + service.registerObserver(mInterfaceObserver); + } catch (RemoteException e) { + Log.e(TAG, "Could not register InterfaceObserver " + e); + } + } + + /** + * Disable connectivity to a network + * TODO: do away with return value after making MobileDataStateTracker async + */ + public boolean teardown() { + mTeardownRequested.set(true); + NetworkUtils.stopDhcp(mIface); + return true; + } + + /** + * Re-enable connectivity to a network after a {@link #teardown()}. + */ + public boolean reconnect() { + mTeardownRequested.set(false); + runDhcp(); + return true; + } + + /** + * Turn the wireless radio off for a network. + * @param turnOn {@code true} to turn the radio on, {@code false} + */ + public boolean setRadio(boolean turnOn) { + return true; + } + + /** + * @return true - If are we currently tethered with another device. + */ + public synchronized boolean isAvailable() { + return mNetworkInfo.isAvailable(); + } + + /** + * Tells the underlying networking system that the caller wants to + * begin using the named feature. The interpretation of {@code feature} + * is completely up to each networking implementation. + * @param feature the name of the feature to be used + * @param callingPid the process ID of the process that is issuing this request + * @param callingUid the user ID of the process that is issuing this request + * @return an integer value representing the outcome of the request. + * The interpretation of this value is specific to each networking + * implementation+feature combination, except that the value {@code -1} + * always indicates failure. + * TODO: needs to go away + */ + public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + + /** + * Tells the underlying networking system that the caller is finished + * using the named feature. The interpretation of {@code feature} + * is completely up to each networking implementation. + * @param feature the name of the feature that is no longer needed. + * @param callingPid the process ID of the process that is issuing this request + * @param callingUid the user ID of the process that is issuing this request + * @return an integer value representing the outcome of the request. + * The interpretation of this value is specific to each networking + * implementation+feature combination, except that the value {@code -1} + * always indicates failure. + * TODO: needs to go away + */ + public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + + /** + * @param enabled + */ + public void setDataEnable(boolean enabled) { + Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled); + } + + /** + * Check if private DNS route is set for the network + */ + public boolean isPrivateDnsRouteSet() { + return mPrivateDnsRouteSet.get(); + } + + /** + * Set a flag indicating private DNS route is set + */ + public void privateDnsRouteSet(boolean enabled) { + mPrivateDnsRouteSet.set(enabled); + } + + /** + * Fetch NetworkInfo for the network + */ + public synchronized NetworkInfo getNetworkInfo() { + return mNetworkInfo; + } + + /** + * Fetch LinkProperties for the network + */ + public synchronized LinkProperties getLinkProperties() { + return new LinkProperties(mLinkProperties); + } + + /** + * A capability is an Integer/String pair, the capabilities + * are defined in the class LinkSocket#Key. + * + * @return a copy of this connections capabilities, may be empty but never null. + */ + public LinkCapabilities getLinkCapabilities() { + return new LinkCapabilities(mLinkCapabilities); + } + + /** + * Fetch default gateway address for the network + */ + public int getDefaultGatewayAddr() { + return mDefaultGatewayAddr.get(); + } + + /** + * Check if default route is set + */ + public boolean isDefaultRouteSet() { + return mDefaultRouteSet.get(); + } + + /** + * Set a flag indicating default route is set for the network + */ + public void defaultRouteSet(boolean enabled) { + mDefaultRouteSet.set(enabled); + } + + /** + * Return the system properties name associated with the tcp buffer sizes + * for this network. + */ + public String getTcpBufferSizesPropName() { + return "net.tcp.buffersize.wifi"; + } +} diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index fcb4c23..b1552a8 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -24,6 +24,7 @@ import android.content.pm.PackageManager; import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.DummyDataStateTracker; +import android.net.EthernetDataTracker; import android.net.IConnectivityManager; import android.net.LinkProperties; import android.net.MobileDataStateTracker; @@ -420,6 +421,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance(); mNetTrackers[netType].startMonitoring(context, mHandler); break; + case ConnectivityManager.TYPE_ETHERNET: + mNetTrackers[netType] = EthernetDataTracker.getInstance(); + mNetTrackers[netType].startMonitoring(context, mHandler); + break; default: loge("Trying to create a DataStateTracker for an unknown radio type " + mNetAttributes[netType].mRadio); -- cgit v1.1