EthernetDataTracker.java revision c96a667162fab44a250503caccb770109a9cb69a
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 sIfaceMatch = ""; 67 private static String mIface = ""; 68 69 private static class InterfaceObserver extends INetworkManagementEventObserver.Stub { 70 private EthernetDataTracker mTracker; 71 72 InterfaceObserver(EthernetDataTracker tracker) { 73 super(); 74 mTracker = tracker; 75 } 76 77 public void interfaceLinkStatusChanged(String iface, boolean up) { 78 Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down")); 79 } 80 81 public void interfaceAdded(String iface) { 82 mTracker.interfaceAdded(iface); 83 } 84 85 public void interfaceRemoved(String iface) { 86 mTracker.interfaceRemoved(iface); 87 } 88 } 89 90 private EthernetDataTracker() { 91 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, ""); 92 mLinkProperties = new LinkProperties(); 93 mLinkCapabilities = new LinkCapabilities(); 94 95 mNetworkInfo.setIsAvailable(false); 96 setTeardownRequested(false); 97 } 98 99 private void interfaceAdded(String iface) { 100 if (!iface.matches(sIfaceMatch)) 101 return; 102 103 Log.d(TAG, "Adding " + iface); 104 105 synchronized(mIface) { 106 if(!mIface.isEmpty()) 107 return; 108 mIface = iface; 109 } 110 111 mNetworkInfo.setIsAvailable(true); 112 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); 113 msg.sendToTarget(); 114 115 runDhcp(); 116 } 117 118 private void interfaceRemoved(String iface) { 119 if (!iface.equals(mIface)) 120 return; 121 122 Log.d(TAG, "Removing " + iface); 123 124 NetworkUtils.stopDhcp(mIface); 125 126 mLinkProperties.clear(); 127 mNetworkInfo.setIsAvailable(false); 128 mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); 129 130 Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); 131 msg.sendToTarget(); 132 133 msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); 134 msg.sendToTarget(); 135 136 mIface = ""; 137 } 138 139 private void runDhcp() { 140 Thread dhcpThread = new Thread(new Runnable() { 141 public void run() { 142 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); 143 if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) { 144 Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); 145 return; 146 } 147 mLinkProperties = dhcpInfoInternal.makeLinkProperties(); 148 mLinkProperties.setInterfaceName(mIface); 149 150 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); 151 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); 152 msg.sendToTarget(); 153 } 154 }); 155 dhcpThread.start(); 156 } 157 158 public static synchronized EthernetDataTracker getInstance() { 159 if (sInstance == null) sInstance = new EthernetDataTracker(); 160 return sInstance; 161 } 162 163 public Object Clone() throws CloneNotSupportedException { 164 throw new CloneNotSupportedException(); 165 } 166 167 public void setTeardownRequested(boolean isRequested) { 168 mTeardownRequested.set(isRequested); 169 } 170 171 public boolean isTeardownRequested() { 172 return mTeardownRequested.get(); 173 } 174 175 /** 176 * Begin monitoring connectivity 177 */ 178 public void startMonitoring(Context context, Handler target) { 179 mContext = context; 180 mCsHandler = target; 181 182 // register for notifications from NetworkManagement Service 183 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 184 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 185 mInterfaceObserver = new InterfaceObserver(this); 186 try { 187 service.registerObserver(mInterfaceObserver); 188 } catch (RemoteException e) { 189 Log.e(TAG, "Could not register InterfaceObserver " + e); 190 } 191 192 // connect to an ethernet interface that already exists 193 sIfaceMatch = context.getResources().getString( 194 com.android.internal.R.string.config_ethernet_iface_regex); 195 try { 196 final String[] ifaces = service.listInterfaces(); 197 for (String iface : ifaces) { 198 if (iface.matches(sIfaceMatch)) { 199 mIface = iface; 200 reconnect(); 201 break; 202 } 203 } 204 } catch (RemoteException e) { 205 Log.e(TAG, "Could not get list of interfaces " + e); 206 } 207 } 208 209 /** 210 * Disable connectivity to a network 211 * TODO: do away with return value after making MobileDataStateTracker async 212 */ 213 public boolean teardown() { 214 mTeardownRequested.set(true); 215 NetworkUtils.stopDhcp(mIface); 216 return true; 217 } 218 219 /** 220 * Re-enable connectivity to a network after a {@link #teardown()}. 221 */ 222 public boolean reconnect() { 223 mTeardownRequested.set(false); 224 runDhcp(); 225 return true; 226 } 227 228 /** 229 * Turn the wireless radio off for a network. 230 * @param turnOn {@code true} to turn the radio on, {@code false} 231 */ 232 public boolean setRadio(boolean turnOn) { 233 return true; 234 } 235 236 /** 237 * @return true - If are we currently tethered with another device. 238 */ 239 public synchronized boolean isAvailable() { 240 return mNetworkInfo.isAvailable(); 241 } 242 243 /** 244 * Tells the underlying networking system that the caller wants to 245 * begin 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 to be used 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 startUsingNetworkFeature(String feature, int callingPid, int callingUid) { 257 return -1; 258 } 259 260 /** 261 * Tells the underlying networking system that the caller is finished 262 * using the named feature. The interpretation of {@code feature} 263 * is completely up to each networking implementation. 264 * @param feature the name of the feature that is no longer needed. 265 * @param callingPid the process ID of the process that is issuing this request 266 * @param callingUid the user ID of the process that is issuing this request 267 * @return an integer value representing the outcome of the request. 268 * The interpretation of this value is specific to each networking 269 * implementation+feature combination, except that the value {@code -1} 270 * always indicates failure. 271 * TODO: needs to go away 272 */ 273 public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { 274 return -1; 275 } 276 277 /** 278 * @param enabled 279 */ 280 public void setDataEnable(boolean enabled) { 281 Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled); 282 } 283 284 /** 285 * Check if private DNS route is set for the network 286 */ 287 public boolean isPrivateDnsRouteSet() { 288 return mPrivateDnsRouteSet.get(); 289 } 290 291 /** 292 * Set a flag indicating private DNS route is set 293 */ 294 public void privateDnsRouteSet(boolean enabled) { 295 mPrivateDnsRouteSet.set(enabled); 296 } 297 298 /** 299 * Fetch NetworkInfo for the network 300 */ 301 public synchronized NetworkInfo getNetworkInfo() { 302 return mNetworkInfo; 303 } 304 305 /** 306 * Fetch LinkProperties for the network 307 */ 308 public synchronized LinkProperties getLinkProperties() { 309 return new LinkProperties(mLinkProperties); 310 } 311 312 /** 313 * A capability is an Integer/String pair, the capabilities 314 * are defined in the class LinkSocket#Key. 315 * 316 * @return a copy of this connections capabilities, may be empty but never null. 317 */ 318 public LinkCapabilities getLinkCapabilities() { 319 return new LinkCapabilities(mLinkCapabilities); 320 } 321 322 /** 323 * Fetch default gateway address for the network 324 */ 325 public int getDefaultGatewayAddr() { 326 return mDefaultGatewayAddr.get(); 327 } 328 329 /** 330 * Check if default route is set 331 */ 332 public boolean isDefaultRouteSet() { 333 return mDefaultRouteSet.get(); 334 } 335 336 /** 337 * Set a flag indicating default route is set for the network 338 */ 339 public void defaultRouteSet(boolean enabled) { 340 mDefaultRouteSet.set(enabled); 341 } 342 343 /** 344 * Return the system properties name associated with the tcp buffer sizes 345 * for this network. 346 */ 347 public String getTcpBufferSizesPropName() { 348 return "net.tcp.buffersize.wifi"; 349 } 350 351 public void setDependencyMet(boolean met) { 352 // not supported on this network 353 } 354} 355