/* * 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"; } public void setDependencyMet(boolean met) { // not supported on this network } }