EthernetDataTracker.java revision 08c39c6a11f728e113811a6a85c109cfc80ce28e
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 17package android.net; 18 19import android.content.Context; 20import android.net.ConnectivityManager; 21import android.net.DhcpInfoInternal; 22import android.net.LinkAddress; 23import android.net.LinkCapabilities; 24import android.net.LinkProperties; 25import android.net.NetworkInfo; 26import android.net.NetworkInfo.DetailedState; 27import android.net.NetworkStateTracker; 28import android.net.NetworkUtils; 29import android.os.Handler; 30import android.os.IBinder; 31import android.os.INetworkManagementService; 32import android.os.Message; 33import android.os.RemoteException; 34import android.os.ServiceManager; 35import android.util.Log; 36 37import java.net.InetAddress; 38import java.util.concurrent.atomic.AtomicBoolean; 39import java.util.concurrent.atomic.AtomicInteger; 40 41/** 42 * This class tracks the data connection associated with Ethernet 43 * This is a singleton class and an instance will be created by 44 * ConnectivityService. 45 * @hide 46 */ 47public class EthernetDataTracker implements NetworkStateTracker { 48 private static final String NETWORKTYPE = "ETHERNET"; 49 private static final String TAG = "Ethernet"; 50 51 private AtomicBoolean mTeardownRequested = new AtomicBoolean(false); 52 private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false); 53 private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); 54 private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false); 55 56 private LinkProperties mLinkProperties; 57 private LinkCapabilities mLinkCapabilities; 58 private NetworkInfo mNetworkInfo; 59 private InterfaceObserver mInterfaceObserver; 60 61 /* For sending events to connectivity service handler */ 62 private Handler mCsHandler; 63 private Context mContext; 64 65 private static EthernetDataTracker sInstance; 66 private static String mIface = ""; 67 68 private static class InterfaceObserver extends INetworkManagementEventObserver.Stub { 69 private EthernetDataTracker mTracker; 70 71 InterfaceObserver(EthernetDataTracker tracker) { 72 super(); 73 mTracker = tracker; 74 } 75 76 public void interfaceLinkStatusChanged(String iface, boolean up) { 77 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down")); 78 } 79 80 public void interfaceAdded(String iface) { 81 mTracker.interfaceAdded(iface); 82 } 83 84 public void interfaceRemoved(String iface) { 85 mTracker.interfaceRemoved(iface); 86 } 87 } 88 89 private EthernetDataTracker() { 90 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, ""); 91 mLinkProperties = new LinkProperties(); 92 mLinkCapabilities = new LinkCapabilities(); 93 94 mNetworkInfo.setIsAvailable(false); 95 setTeardownRequested(false); 96 } 97 98 private void interfaceAdded(String iface) { 99 if (!iface.matches("eth\\d")) 100 return; 101 102 Log.d(TAG, "Adding " + iface); 103 104 synchronized(mIface) { 105 if(!mIface.isEmpty()) 106 return; 107 mIface = iface; 108 } 109 110 mNetworkInfo.setIsAvailable(true); 111 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); 112 msg.sendToTarget(); 113 114 runDhcp(); 115 } 116 117 private void interfaceRemoved(String iface) { 118 if (!iface.equals(mIface)) 119 return; 120 121 Log.d(TAG, "Removing " + iface); 122 123 NetworkUtils.stopDhcp(mIface); 124 125 mLinkProperties.clear(); 126 mNetworkInfo.setIsAvailable(false); 127 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 128 129 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); 130 msg.sendToTarget(); 131 132 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); 133 msg.sendToTarget(); 134 135 mIface = ""; 136 } 137 138 private void runDhcp() { 139 Thread dhcpThread = new Thread(new Runnable() { 140 public void run() { 141 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); 142 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) { 143 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); 144 return; 145 } 146 mLinkProperties = dhcpInfoInternal.makeLinkProperties(); 147 mLinkProperties.setInterfaceName(mIface); 148 149 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 150 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); 151 msg.sendToTarget(); 152 } 153 }); 154 dhcpThread.start(); 155 } 156 157 public static synchronized EthernetDataTracker getInstance() { 158 if (sInstance == null) sInstance = new EthernetDataTracker(); 159 return sInstance; 160 } 161 162 public Object Clone() throws CloneNotSupportedException { 163 throw new CloneNotSupportedException(); 164 } 165 166 public void setTeardownRequested(boolean isRequested) { 167 mTeardownRequested.set(isRequested); 168 } 169 170 public boolean isTeardownRequested() { 171 return mTeardownRequested.get(); 172 } 173 174 /** 175 * Begin monitoring connectivity 176 */ 177 public void startMonitoring(Context context, Handler target) { 178 mContext = context; 179 mCsHandler = target; 180 181 // register for notifications from NetworkManagement Service 182 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 183 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 184 mInterfaceObserver = new InterfaceObserver(this); 185 try { 186 service.registerObserver(mInterfaceObserver); 187 } catch (RemoteException e) { 188 Log.e(TAG, "Could not register InterfaceObserver " + e); 189 } 190 } 191 192 /** 193 * Disable connectivity to a network 194 * TODO: do away with return value after making MobileDataStateTracker async 195 */ 196 public boolean teardown() { 197 mTeardownRequested.set(true); 198 NetworkUtils.stopDhcp(mIface); 199 return true; 200 } 201 202 /** 203 * Re-enable connectivity to a network after a {@link #teardown()}. 204 */ 205 public boolean reconnect() { 206 mTeardownRequested.set(false); 207 runDhcp(); 208 return true; 209 } 210 211 /** 212 * Turn the wireless radio off for a network. 213 * @param turnOn {@code true} to turn the radio on, {@code false} 214 */ 215 public boolean setRadio(boolean turnOn) { 216 return true; 217 } 218 219 /** 220 * @return true - If are we currently tethered with another device. 221 */ 222 public synchronized boolean isAvailable() { 223 return mNetworkInfo.isAvailable(); 224 } 225 226 /** 227 * Tells the underlying networking system that the caller wants to 228 * begin using the named feature. The interpretation of {@code feature} 229 * is completely up to each networking implementation. 230 * @param feature the name of the feature to be used 231 * @param callingPid the process ID of the process that is issuing this request 232 * @param callingUid the user ID of the process that is issuing this request 233 * @return an integer value representing the outcome of the request. 234 * The interpretation of this value is specific to each networking 235 * implementation+feature combination, except that the value {@code -1} 236 * always indicates failure. 237 * TODO: needs to go away 238 */ 239 public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { 240 return -1; 241 } 242 243 /** 244 * Tells the underlying networking system that the caller is finished 245 * using the named feature. The interpretation of {@code feature} 246 * is completely up to each networking implementation. 247 * @param feature the name of the feature that is no longer needed. 248 * @param callingPid the process ID of the process that is issuing this request 249 * @param callingUid the user ID of the process that is issuing this request 250 * @return an integer value representing the outcome of the request. 251 * The interpretation of this value is specific to each networking 252 * implementation+feature combination, except that the value {@code -1} 253 * always indicates failure. 254 * TODO: needs to go away 255 */ 256 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { 257 return -1; 258 } 259 260 /** 261 * @param enabled 262 */ 263 public void setDataEnable(boolean enabled) { 264 Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled); 265 } 266 267 /** 268 * Check if private DNS route is set for the network 269 */ 270 public boolean isPrivateDnsRouteSet() { 271 return mPrivateDnsRouteSet.get(); 272 } 273 274 /** 275 * Set a flag indicating private DNS route is set 276 */ 277 public void privateDnsRouteSet(boolean enabled) { 278 mPrivateDnsRouteSet.set(enabled); 279 } 280 281 /** 282 * Fetch NetworkInfo for the network 283 */ 284 public synchronized NetworkInfo getNetworkInfo() { 285 return mNetworkInfo; 286 } 287 288 /** 289 * Fetch LinkProperties for the network 290 */ 291 public synchronized LinkProperties getLinkProperties() { 292 return new LinkProperties(mLinkProperties); 293 } 294 295 /** 296 * A capability is an Integer/String pair, the capabilities 297 * are defined in the class LinkSocket#Key. 298 * 299 * @return a copy of this connections capabilities, may be empty but never null. 300 */ 301 public LinkCapabilities getLinkCapabilities() { 302 return new LinkCapabilities(mLinkCapabilities); 303 } 304 305 /** 306 * Fetch default gateway address for the network 307 */ 308 public int getDefaultGatewayAddr() { 309 return mDefaultGatewayAddr.get(); 310 } 311 312 /** 313 * Check if default route is set 314 */ 315 public boolean isDefaultRouteSet() { 316 return mDefaultRouteSet.get(); 317 } 318 319 /** 320 * Set a flag indicating default route is set for the network 321 */ 322 public void defaultRouteSet(boolean enabled) { 323 mDefaultRouteSet.set(enabled); 324 } 325 326 /** 327 * Return the system properties name associated with the tcp buffer sizes 328 * for this network. 329 */ 330 public String getTcpBufferSizesPropName() { 331 return "net.tcp.buffersize.wifi"; 332 } 333} 334