blob: 55850c90ca32f99cc8ce06f983b17508d0f2b1ba [file] [log] [blame]
/*
* 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
}
}