NetworkStateTracker.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/* 2 * Copyright (C) 2008 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 java.io.FileWriter; 20import java.io.IOException; 21 22import android.os.Handler; 23import android.os.Message; 24import android.os.SystemProperties; 25import android.content.Context; 26import android.text.TextUtils; 27import android.util.Config; 28import android.util.Log; 29 30/** 31 * Each subclass of this class keeps track of the state of connectivity 32 * of a network interface. All state information for a network should 33 * be kept in a Tracker class. This superclass manages the 34 * network-type-independent aspects of network state. 35 * 36 * {@hide} 37 */ 38public abstract class NetworkStateTracker extends Handler { 39 40 protected NetworkInfo mNetworkInfo; 41 protected Context mContext; 42 protected Handler mTarget; 43 private boolean mTeardownRequested; 44 45 private static boolean DBG = Config.LOGV; 46 private static final String TAG = "NetworkStateTracker"; 47 48 public static final int EVENT_STATE_CHANGED = 1; 49 public static final int EVENT_SCAN_RESULTS_AVAILABLE = 2; 50 /** 51 * arg1: 1 to show, 0 to hide 52 * arg2: ID of the notification 53 * obj: Notification (if showing) 54 */ 55 public static final int EVENT_NOTIFICATION_CHANGED = 3; 56 public static final int EVENT_CONFIGURATION_CHANGED = 4; 57 public static final int EVENT_ROAMING_CHANGED = 5; 58 public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6; 59 60 public NetworkStateTracker(Context context, 61 Handler target, 62 int networkType, 63 int subType, 64 String typeName, 65 String subtypeName) { 66 super(); 67 mContext = context; 68 mTarget = target; 69 mTeardownRequested = false; 70 this.mNetworkInfo = new NetworkInfo(networkType, subType, typeName, subtypeName); 71 } 72 73 public NetworkInfo getNetworkInfo() { 74 return mNetworkInfo; 75 } 76 77 /** 78 * Return the list of DNS servers associated with this network. 79 * @return a list of the IP addresses of the DNS servers available 80 * for the network. 81 */ 82 public abstract String[] getNameServers(); 83 84 /** 85 * Return the system properties name associated with the tcp buffer sizes 86 * for this network. 87 */ 88 public abstract String getTcpBufferSizesPropName(); 89 90 /** 91 * Return the IP addresses of the DNS servers available for this 92 * network interface. 93 * @param propertyNames the names of the system properties whose values 94 * give the IP addresses. Properties with no values are skipped. 95 * @return an array of {@code String}s containing the IP addresses 96 * of the DNS servers, in dot-notation. This may have fewer 97 * non-null entries than the list of names passed in, since 98 * some of the passed-in names may have empty values. 99 */ 100 static protected String[] getNameServerList(String[] propertyNames) { 101 String[] dnsAddresses = new String[propertyNames.length]; 102 int i, j; 103 104 for (i = 0, j = 0; i < propertyNames.length; i++) { 105 String value = SystemProperties.get(propertyNames[i]); 106 // The GSM layer sometimes sets a bogus DNS server address of 107 // 0.0.0.0 108 if (!TextUtils.isEmpty(value) && !TextUtils.equals(value, "0.0.0.0")) { 109 dnsAddresses[j++] = value; 110 } 111 } 112 return dnsAddresses; 113 } 114 115 /** 116 * Reads the network specific TCP buffer sizes from SystemProperties 117 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system 118 * wide use 119 */ 120 public void updateNetworkSettings() { 121 String key = getTcpBufferSizesPropName(); 122 String bufferSizes = SystemProperties.get(key); 123 124 if (bufferSizes.length() == 0) { 125 Log.e(TAG, key + " not found in system properties. Using defaults"); 126 127 // Setting to default values so we won't be stuck to previous values 128 key = "net.tcp.buffersize.default"; 129 bufferSizes = SystemProperties.get(key); 130 } 131 132 // Set values in kernel 133 if (bufferSizes.length() != 0) { 134 if (DBG) { 135 Log.v(TAG, "Setting TCP values: [" + bufferSizes 136 + "] which comes from [" + key + "]"); 137 } 138 setBufferSize(bufferSizes); 139 } 140 } 141 142 /** 143 * Release the wakelock, if any, that may be held while handling a 144 * disconnect operation. 145 */ 146 public void releaseWakeLock() { 147 } 148 149 /** 150 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] 151 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem 152 * 153 * @param bufferSizes in the format of "readMin, readInitial, readMax, 154 * writeMin, writeInitial, writeMax" 155 */ 156 private void setBufferSize(String bufferSizes) { 157 try { 158 String[] values = bufferSizes.split(","); 159 160 if (values.length == 6) { 161 final String prefix = "/sys/kernel/ipv4/tcp_"; 162 stringToFile(prefix + "rmem_min", values[0]); 163 stringToFile(prefix + "rmem_def", values[1]); 164 stringToFile(prefix + "rmem_max", values[2]); 165 stringToFile(prefix + "wmem_min", values[3]); 166 stringToFile(prefix + "wmem_def", values[4]); 167 stringToFile(prefix + "wmem_max", values[5]); 168 } else { 169 Log.e(TAG, "Invalid buffersize string: " + bufferSizes); 170 } 171 } catch (IOException e) { 172 Log.e(TAG, "Can't set tcp buffer sizes:" + e); 173 } 174 } 175 176 /** 177 * Writes string to file. Basically same as "echo -n $string > $filename" 178 * 179 * @param filename 180 * @param string 181 * @throws IOException 182 */ 183 private void stringToFile(String filename, String string) throws IOException { 184 FileWriter out = new FileWriter(filename); 185 try { 186 out.write(string); 187 } finally { 188 out.close(); 189 } 190 } 191 192 /** 193 * Record the detailed state of a network, and if it is a 194 * change from the previous state, send a notification to 195 * any listeners. 196 * @param state the new @{code DetailedState} 197 */ 198 public void setDetailedState(NetworkInfo.DetailedState state) { 199 setDetailedState(state, null, null); 200 } 201 202 /** 203 * Record the detailed state of a network, and if it is a 204 * change from the previous state, send a notification to 205 * any listeners. 206 * @param state the new @{code DetailedState} 207 * @param reason a {@code String} indicating a reason for the state change, 208 * if one was supplied. May be {@code null}. 209 * @param extraInfo optional {@code String} providing extra information about the state change 210 */ 211 public void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) { 212 if (state != mNetworkInfo.getDetailedState()) { 213 boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING); 214 String lastReason = mNetworkInfo.getReason(); 215 /* 216 * If a reason was supplied when the CONNECTING state was entered, and no 217 * reason was supplied for entering the CONNECTED state, then retain the 218 * reason that was supplied when going to CONNECTING. 219 */ 220 if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null 221 && lastReason != null) 222 reason = lastReason; 223 mNetworkInfo.setDetailedState(state, reason, extraInfo); 224 Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); 225 msg.sendToTarget(); 226 } 227 } 228 229 protected void setDetailedStateInternal(NetworkInfo.DetailedState state) { 230 mNetworkInfo.setDetailedState(state, null, null); 231 } 232 233 public void setTeardownRequested(boolean isRequested) { 234 mTeardownRequested = isRequested; 235 } 236 237 public boolean isTeardownRequested() { 238 return mTeardownRequested; 239 } 240 241 /** 242 * Send a notification that the results of a scan for network access 243 * points has completed, and results are available. 244 */ 245 protected void sendScanResultsAvailable() { 246 Message msg = mTarget.obtainMessage(EVENT_SCAN_RESULTS_AVAILABLE, mNetworkInfo); 247 msg.sendToTarget(); 248 } 249 250 /** 251 * Record the roaming status of the device, and if it is a change from the previous 252 * status, send a notification to any listeners. 253 * @param isRoaming {@code true} if the device is now roaming, {@code false} 254 * if it is no longer roaming. 255 */ 256 protected void setRoamingStatus(boolean isRoaming) { 257 if (isRoaming != mNetworkInfo.isRoaming()) { 258 mNetworkInfo.setRoaming(isRoaming); 259 Message msg = mTarget.obtainMessage(EVENT_ROAMING_CHANGED, mNetworkInfo); 260 msg.sendToTarget(); 261 } 262 } 263 264 protected void setSubtype(int subtype, String subtypeName) { 265 if (mNetworkInfo.isConnected()) { 266 int oldSubtype = mNetworkInfo.getSubtype(); 267 if (subtype != oldSubtype) { 268 mNetworkInfo.setSubtype(subtype, subtypeName); 269 Message msg = mTarget.obtainMessage( 270 EVENT_NETWORK_SUBTYPE_CHANGED, oldSubtype, 0, mNetworkInfo); 271 msg.sendToTarget(); 272 } 273 } 274 } 275 276 public abstract void startMonitoring(); 277 278 /** 279 * Disable connectivity to a network 280 * @return {@code true} if a teardown occurred, {@code false} if the 281 * teardown did not occur. 282 */ 283 public abstract boolean teardown(); 284 285 /** 286 * Reenable connectivity to a network after a {@link #teardown()}. 287 */ 288 public abstract boolean reconnect(); 289 290 /** 291 * Turn the wireless radio off for a network. 292 * @param turnOn {@code true} to turn the radio on, {@code false} 293 */ 294 public abstract boolean setRadio(boolean turnOn); 295 296 /** 297 * Returns an indication of whether this network is available for 298 * connections. A value of {@code false} means that some quasi-permanent 299 * condition prevents connectivity to this network. 300 */ 301 public abstract boolean isAvailable(); 302 303 /** 304 * Tells the underlying networking system that the caller wants to 305 * begin using the named feature. The interpretation of {@code feature} 306 * is completely up to each networking implementation. 307 * @param feature the name of the feature to be used 308 * @param callingPid the process ID of the process that is issuing this request 309 * @param callingUid the user ID of the process that is issuing this request 310 * @return an integer value representing the outcome of the request. 311 * The interpretation of this value is specific to each networking 312 * implementation+feature combination, except that the value {@code -1} 313 * always indicates failure. 314 */ 315 public abstract int startUsingNetworkFeature(String feature, int callingPid, int callingUid); 316 317 /** 318 * Tells the underlying networking system that the caller is finished 319 * using the named feature. The interpretation of {@code feature} 320 * is completely up to each networking implementation. 321 * @param feature the name of the feature that is no longer needed. 322 * @param callingPid the process ID of the process that is issuing this request 323 * @param callingUid the user ID of the process that is issuing this request 324 * @return an integer value representing the outcome of the request. 325 * The interpretation of this value is specific to each networking 326 * implementation+feature combination, except that the value {@code -1} 327 * always indicates failure. 328 */ 329 public abstract int stopUsingNetworkFeature(String feature, int callingPid, int callingUid); 330 331 /** 332 * Ensure that a network route exists to deliver traffic to the specified 333 * host via this network interface. 334 * @param hostAddress the IP address of the host to which the route is desired 335 * @return {@code true} on success, {@code false} on failure 336 */ 337 public boolean requestRouteToHost(int hostAddress) { 338 return false; 339 } 340 341 /** 342 * Interprets scan results. This will be called at a safe time for 343 * processing, and from a safe thread. 344 */ 345 public void interpretScanResultsAvailable() { 346 } 347 348} 349