diff options
| -rw-r--r-- | core/java/android/net/MobileDataStateTracker.java | 203 | ||||
| -rw-r--r-- | core/java/android/net/NetworkInfo.java | 8 | ||||
| -rw-r--r-- | core/java/android/net/NetworkStateTracker.java | 343 | ||||
| -rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 209 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/WifiStateTracker.java | 124 |
5 files changed, 569 insertions, 318 deletions
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index ce6d613..5fd5315 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -22,11 +22,13 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.RemoteException; import android.os.Handler; +import android.os.Message; import android.os.ServiceManager; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyIntents; import android.net.NetworkInfo.DetailedState; +import android.net.NetworkInfo; import android.telephony.TelephonyManager; import android.util.Log; import android.text.TextUtils; @@ -38,7 +40,7 @@ import android.text.TextUtils; * * {@hide} */ -public class MobileDataStateTracker extends NetworkStateTracker { +public class MobileDataStateTracker implements NetworkStateTracker { private static final String TAG = "MobileDataStateTracker"; private static final boolean DBG = true; @@ -48,6 +50,15 @@ public class MobileDataStateTracker extends NetworkStateTracker { private String mApnType; private BroadcastReceiver mStateReceiver; + private static String[] sDnsPropNames; + private NetworkInfo mNetworkInfo; + private boolean mTeardownRequested = false; + private Handler mTarget; + private Context mContext; + private String mInterfaceName; + private boolean mPrivateDnsRouteSet = false; + private int mDefaultGatewayAddr = 0; + private boolean mDefaultRouteSet = false; /** * Create a new MobileDataStateTracker @@ -58,14 +69,16 @@ public class MobileDataStateTracker extends NetworkStateTracker { * @param tag the name of this network */ public MobileDataStateTracker(Context context, Handler target, int netType, String tag) { - super(context, target, netType, + mTarget = target; + mContext = context; + mNetworkInfo = new NetworkInfo(netType, TelephonyManager.getDefault().getNetworkType(), tag, TelephonyManager.getDefault().getNetworkTypeName()); mApnType = networkTypeToApnType(netType); mPhoneService = null; - mDnsPropNames = new String[] { + sDnsPropNames = new String[] { "net.rmnet0.dns1", "net.rmnet0.dns2", "net.eth0.dns1", @@ -80,6 +93,53 @@ public class MobileDataStateTracker extends NetworkStateTracker { } /** + * Return the IP addresses of the DNS servers available for the mobile data + * network interface. + * @return a list of DNS addresses, with no holes. + */ + public String[] getDnsPropNames() { + return sDnsPropNames; + } + + /** + * Return the name of our network interface. + * @return the name of our interface. + */ + public String getInterfaceName() { + return mInterfaceName; + } + + public boolean isPrivateDnsRouteSet() { + return mPrivateDnsRouteSet; + } + + public void privateDnsRouteSet(boolean enabled) { + mPrivateDnsRouteSet = enabled; + } + + public NetworkInfo getNetworkInfo() { + return mNetworkInfo; + } + + public int getDefaultGatewayAddr() { + return mDefaultGatewayAddr; + } + + public boolean isDefaultRouteSet() { + return mDefaultRouteSet; + } + + public void defaultRouteSet(boolean enabled) { + mDefaultRouteSet = enabled; + } + + /** + * This is not implemented. + */ + public void releaseWakeLock() { + } + + /** * Begin monitoring mobile data connectivity. */ public void startMonitoring() { @@ -93,6 +153,32 @@ public class MobileDataStateTracker extends NetworkStateTracker { mMobileDataState = Phone.DataState.DISCONNECTED; } + /** + * Record the roaming status of the device, and if it is a change from the previous + * status, send a notification to any listeners. + * @param isRoaming {@code true} if the device is now roaming, {@code false} + * if it is no longer roaming. + */ + private void setRoamingStatus(boolean isRoaming) { + if (isRoaming != mNetworkInfo.isRoaming()) { + mNetworkInfo.setRoaming(isRoaming); + Message msg = mTarget.obtainMessage(EVENT_ROAMING_CHANGED, mNetworkInfo); + msg.sendToTarget(); + } + } + + private void setSubtype(int subtype, String subtypeName) { + if (mNetworkInfo.isConnected()) { + int oldSubtype = mNetworkInfo.getSubtype(); + if (subtype != oldSubtype) { + mNetworkInfo.setSubtype(subtype, subtypeName); + Message msg = mTarget.obtainMessage( + EVENT_NETWORK_SUBTYPE_CHANGED, oldSubtype, 0, mNetworkInfo); + msg.sendToTarget(); + } + } + } + private class MobileDataStateReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { synchronized(this) { @@ -260,13 +346,63 @@ public class MobileDataStateTracker extends NetworkStateTracker { * mobile data connections. * TODO - make async and return nothing? */ - @Override public boolean teardown() { setTeardownRequested(true); return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED); } /** + * Record the detailed state of a network, and if it is a + * change from the previous state, send a notification to + * any listeners. + * @param state the new @{code DetailedState} + */ + private void setDetailedState(NetworkInfo.DetailedState state) { + setDetailedState(state, null, null); + } + + /** + * Record the detailed state of a network, and if it is a + * change from the previous state, send a notification to + * any listeners. + * @param state the new @{code DetailedState} + * @param reason a {@code String} indicating a reason for the state change, + * if one was supplied. May be {@code null}. + * @param extraInfo optional {@code String} providing extra information about the state change + */ + private void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) { + if (DBG) Log.d(TAG, "setDetailed state, old =" + + mNetworkInfo.getDetailedState() + " and new state=" + state); + if (state != mNetworkInfo.getDetailedState()) { + boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING); + String lastReason = mNetworkInfo.getReason(); + /* + * If a reason was supplied when the CONNECTING state was entered, and no + * reason was supplied for entering the CONNECTED state, then retain the + * reason that was supplied when going to CONNECTING. + */ + if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null + && lastReason != null) + reason = lastReason; + mNetworkInfo.setDetailedState(state, reason, extraInfo); + Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); + msg.sendToTarget(); + } + } + + private void setDetailedStateInternal(NetworkInfo.DetailedState state) { + mNetworkInfo.setDetailedState(state, null, null); + } + + public void setTeardownRequested(boolean isRequested) { + mTeardownRequested = isRequested; + } + + public boolean isTeardownRequested() { + return mTeardownRequested; + } + + /** * Re-enable mobile data connectivity after a {@link #teardown()}. * TODO - make async and always get a notification? */ @@ -322,23 +458,50 @@ public class MobileDataStateTracker extends NetworkStateTracker { } /** - * Ensure that a network route exists to deliver traffic to the specified - * host via the mobile data network. - * @param hostAddress the IP address of the host to which the route is desired, - * in network byte order. - * @return {@code true} on success, {@code false} on failure + * Tells the phone sub-system that the caller wants to + * begin using the named feature. The only supported features at + * this time are {@code Phone.FEATURE_ENABLE_MMS}, which allows an application + * to specify that it wants to send and/or receive MMS data, and + * {@code Phone.FEATURE_ENABLE_SUPL}, which is used for Assisted GPS. + * @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 feature-specific. + * specific, except that the value {@code -1} + * always indicates failure. For {@code Phone.FEATURE_ENABLE_MMS}, + * the other possible return values are + * <ul> + * <li>{@code Phone.APN_ALREADY_ACTIVE}</li> + * <li>{@code Phone.APN_REQUEST_STARTED}</li> + * <li>{@code Phone.APN_TYPE_NOT_AVAILABLE}</li> + * <li>{@code Phone.APN_REQUEST_FAILED}</li> + * </ul> */ - @Override - public boolean requestRouteToHost(int hostAddress) { - if (DBG) { - Log.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress) + - " for " + mApnType + "(" + mInterfaceName + ")"); - } - if (mInterfaceName != null && hostAddress != -1) { - return NetworkUtils.addHostRoute(mInterfaceName, hostAddress) == 0; - } else { - return false; - } + public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + + /** + * Tells the phone sub-system that the caller is finished + * using the named feature. The only supported feature at + * this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application + * to specify that it wants to send and/or receive MMS data. + * @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 feature-specific, except that + * the value {@code -1} always indicates failure. + */ + public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + + /** + * This is not supported. + */ + public void interpretScanResultsAvailable() { } @Override diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index 649cb8c..21f711c 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -121,7 +121,10 @@ public class NetworkInfo implements Parcelable { */ public NetworkInfo(int type) {} - NetworkInfo(int type, int subtype, String typeName, String subtypeName) { + /** + * @hide + */ + public NetworkInfo(int type, int subtype, String typeName, String subtypeName) { if (!ConnectivityManager.isNetworkTypeValid(type)) { throw new IllegalArgumentException("Invalid network type: " + type); } @@ -281,8 +284,9 @@ public class NetworkInfo implements Parcelable { * if one was supplied. May be {@code null}. * @param extraInfo an optional {@code String} providing addditional network state * information passed up from the lower networking layers. + * @hide */ - void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { + public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { this.mDetailedState = detailedState; this.mState = stateMap.get(detailedState); this.mReason = reason; diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java index 2992646..d5bcfcd 100644 --- a/core/java/android/net/NetworkStateTracker.java +++ b/core/java/android/net/NetworkStateTracker.java @@ -16,40 +16,15 @@ package android.net; -import java.io.FileWriter; -import java.io.IOException; - -import android.os.Handler; -import android.os.Message; -import android.os.SystemProperties; -import android.content.Context; -import android.text.TextUtils; -import android.util.Config; -import android.util.Log; - - /** - * Each subclass of this class keeps track of the state of connectivity - * of a network interface. All state information for a network should - * be kept in a Tracker class. This superclass manages the - * network-type-independent aspects of network state. + * Interface for connectivity service to act on a network interface. + * All state information for a network should be kept in a Tracker class. + * This interface defines network-type-independent functions that should + * be implemented by the Tracker class. * * {@hide} */ -public abstract class NetworkStateTracker extends Handler { - - protected NetworkInfo mNetworkInfo; - protected Context mContext; - protected Handler mTarget; - protected String mInterfaceName; - protected String[] mDnsPropNames; - private boolean mPrivateDnsRouteSet; - protected int mDefaultGatewayAddr; - private boolean mDefaultRouteSet; - private boolean mTeardownRequested; - - private static boolean DBG = true; - private static final String TAG = "NetworkStateTracker"; +public interface NetworkStateTracker { public static final int EVENT_STATE_CHANGED = 1; public static final int EVENT_SCAN_RESULTS_AVAILABLE = 2; @@ -64,322 +39,128 @@ public abstract class NetworkStateTracker extends Handler { public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6; public static final int EVENT_RESTORE_DEFAULT_NETWORK = 7; - public NetworkStateTracker(Context context, - Handler target, - int networkType, - int subType, - String typeName, - String subtypeName) { - super(); - mContext = context; - mTarget = target; - mTeardownRequested = false; - - this.mNetworkInfo = new NetworkInfo(networkType, subType, typeName, subtypeName); - } - - public NetworkInfo getNetworkInfo() { - return mNetworkInfo; - } + /** + * Fetch NetworkInfo for the network + */ + public NetworkInfo getNetworkInfo(); /** * Return the system properties name associated with the tcp buffer sizes * for this network. */ - public abstract String getTcpBufferSizesPropName(); + public String getTcpBufferSizesPropName(); /** - * Return the IP addresses of the DNS servers available for the mobile data - * network interface. - * @return a list of DNS addresses, with no holes. + * Return the DNS property names for this network. */ - public String[] getNameServers() { - return getNameServerList(mDnsPropNames); - } + public String[] getDnsPropNames(); /** - * Return the IP addresses of the DNS servers available for this - * network interface. - * @param propertyNames the names of the system properties whose values - * give the IP addresses. Properties with no values are skipped. - * @return an array of {@code String}s containing the IP addresses - * of the DNS servers, in dot-notation. This may have fewer - * non-null entries than the list of names passed in, since - * some of the passed-in names may have empty values. + * Fetch interface name of the interface */ - static protected String[] getNameServerList(String[] propertyNames) { - String[] dnsAddresses = new String[propertyNames.length]; - int i, j; - - for (i = 0, j = 0; i < propertyNames.length; i++) { - String value = SystemProperties.get(propertyNames[i]); - // The GSM layer sometimes sets a bogus DNS server address of - // 0.0.0.0 - if (!TextUtils.isEmpty(value) && !TextUtils.equals(value, "0.0.0.0")) { - dnsAddresses[j++] = value; - } - } - return dnsAddresses; - } - - public void addPrivateDnsRoutes() { - if (DBG) { - Log.d(TAG, "addPrivateDnsRoutes for " + this + - "(" + mInterfaceName + ") - mPrivateDnsRouteSet = "+mPrivateDnsRouteSet); - } - if (mInterfaceName != null && !mPrivateDnsRouteSet) { - for (String addrString : getNameServers()) { - int addr = NetworkUtils.lookupHost(addrString); - if (addr != -1 && addr != 0) { - if (DBG) Log.d(TAG, " adding "+addrString+" ("+addr+")"); - NetworkUtils.addHostRoute(mInterfaceName, addr); - } - } - mPrivateDnsRouteSet = true; - } - } - - public void removePrivateDnsRoutes() { - // TODO - we should do this explicitly but the NetUtils api doesnt - // support this yet - must remove all. No worse than before - if (mInterfaceName != null && mPrivateDnsRouteSet) { - if (DBG) { - Log.d(TAG, "removePrivateDnsRoutes for " + mNetworkInfo.getTypeName() + - " (" + mInterfaceName + ")"); - } - NetworkUtils.removeHostRoutes(mInterfaceName); - mPrivateDnsRouteSet = false; - } - } - - public void addDefaultRoute() { - if ((mInterfaceName != null) && (mDefaultGatewayAddr != 0) && - mDefaultRouteSet == false) { - if (DBG) { - Log.d(TAG, "addDefaultRoute for " + mNetworkInfo.getTypeName() + - " (" + mInterfaceName + "), GatewayAddr=" + mDefaultGatewayAddr); - } - NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr); - mDefaultRouteSet = true; - } - } - - public void removeDefaultRoute() { - if (mInterfaceName != null && mDefaultRouteSet == true) { - if (DBG) { - Log.d(TAG, "removeDefaultRoute for " + mNetworkInfo.getTypeName() + " (" + - mInterfaceName + ")"); - } - NetworkUtils.removeDefaultRoute(mInterfaceName); - mDefaultRouteSet = false; - } - } + public String getInterfaceName(); /** - * Reads the network specific TCP buffer sizes from SystemProperties - * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system - * wide use + * Check if private DNS route is set for the network */ - public void updateNetworkSettings() { - String key = getTcpBufferSizesPropName(); - String bufferSizes = SystemProperties.get(key); - - if (bufferSizes.length() == 0) { - Log.e(TAG, key + " not found in system properties. Using defaults"); - - // Setting to default values so we won't be stuck to previous values - key = "net.tcp.buffersize.default"; - bufferSizes = SystemProperties.get(key); - } - - // Set values in kernel - if (bufferSizes.length() != 0) { - if (DBG) { - Log.v(TAG, "Setting TCP values: [" + bufferSizes - + "] which comes from [" + key + "]"); - } - setBufferSize(bufferSizes); - } - } + public boolean isPrivateDnsRouteSet(); /** - * Release the wakelock, if any, that may be held while handling a - * disconnect operation. + * Set a flag indicating private DNS route is set */ - public void releaseWakeLock() { - } + public void privateDnsRouteSet(boolean enabled); /** - * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] - * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem - * - * @param bufferSizes in the format of "readMin, readInitial, readMax, - * writeMin, writeInitial, writeMax" + * Fetch default gateway address for the network */ - private void setBufferSize(String bufferSizes) { - try { - String[] values = bufferSizes.split(","); - - if (values.length == 6) { - final String prefix = "/sys/kernel/ipv4/tcp_"; - stringToFile(prefix + "rmem_min", values[0]); - stringToFile(prefix + "rmem_def", values[1]); - stringToFile(prefix + "rmem_max", values[2]); - stringToFile(prefix + "wmem_min", values[3]); - stringToFile(prefix + "wmem_def", values[4]); - stringToFile(prefix + "wmem_max", values[5]); - } else { - Log.e(TAG, "Invalid buffersize string: " + bufferSizes); - } - } catch (IOException e) { - Log.e(TAG, "Can't set tcp buffer sizes:" + e); - } - } + public int getDefaultGatewayAddr(); /** - * Writes string to file. Basically same as "echo -n $string > $filename" - * - * @param filename - * @param string - * @throws IOException + * Check if default route is set */ - private void stringToFile(String filename, String string) throws IOException { - FileWriter out = new FileWriter(filename); - try { - out.write(string); - } finally { - out.close(); - } - } + public boolean isDefaultRouteSet(); /** - * Record the detailed state of a network, and if it is a - * change from the previous state, send a notification to - * any listeners. - * @param state the new @{code DetailedState} + * Set a flag indicating default route is set for the network */ - public void setDetailedState(NetworkInfo.DetailedState state) { - setDetailedState(state, null, null); - } + public void defaultRouteSet(boolean enabled); /** - * Record the detailed state of a network, and if it is a - * change from the previous state, send a notification to - * any listeners. - * @param state the new @{code DetailedState} - * @param reason a {@code String} indicating a reason for the state change, - * if one was supplied. May be {@code null}. - * @param extraInfo optional {@code String} providing extra information about the state change + * Indicate tear down requested from connectivity */ - public void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) { - if (DBG) Log.d(TAG, "setDetailed state, old ="+mNetworkInfo.getDetailedState()+" and new state="+state); - if (state != mNetworkInfo.getDetailedState()) { - boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING); - String lastReason = mNetworkInfo.getReason(); - /* - * If a reason was supplied when the CONNECTING state was entered, and no - * reason was supplied for entering the CONNECTED state, then retain the - * reason that was supplied when going to CONNECTING. - */ - if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null - && lastReason != null) - reason = lastReason; - mNetworkInfo.setDetailedState(state, reason, extraInfo); - Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); - msg.sendToTarget(); - } - } - - protected void setDetailedStateInternal(NetworkInfo.DetailedState state) { - mNetworkInfo.setDetailedState(state, null, null); - } + public void setTeardownRequested(boolean isRequested); - public void setTeardownRequested(boolean isRequested) { - mTeardownRequested = isRequested; - } - - public boolean isTeardownRequested() { - return mTeardownRequested; - } - /** - * Send a notification that the results of a scan for network access - * points has completed, and results are available. + * Check if tear down was requested */ - protected void sendScanResultsAvailable() { - Message msg = mTarget.obtainMessage(EVENT_SCAN_RESULTS_AVAILABLE, mNetworkInfo); - msg.sendToTarget(); - } + public boolean isTeardownRequested(); /** - * Record the roaming status of the device, and if it is a change from the previous - * status, send a notification to any listeners. - * @param isRoaming {@code true} if the device is now roaming, {@code false} - * if it is no longer roaming. + * Release the wakelock, if any, that may be held while handling a + * disconnect operation. */ - protected void setRoamingStatus(boolean isRoaming) { - if (isRoaming != mNetworkInfo.isRoaming()) { - mNetworkInfo.setRoaming(isRoaming); - Message msg = mTarget.obtainMessage(EVENT_ROAMING_CHANGED, mNetworkInfo); - msg.sendToTarget(); - } - } - - protected void setSubtype(int subtype, String subtypeName) { - if (mNetworkInfo.isConnected()) { - int oldSubtype = mNetworkInfo.getSubtype(); - if (subtype != oldSubtype) { - mNetworkInfo.setSubtype(subtype, subtypeName); - Message msg = mTarget.obtainMessage( - EVENT_NETWORK_SUBTYPE_CHANGED, oldSubtype, 0, mNetworkInfo); - msg.sendToTarget(); - } - } - } + public void releaseWakeLock(); - public abstract void startMonitoring(); + public void startMonitoring(); /** * Disable connectivity to a network * @return {@code true} if a teardown occurred, {@code false} if the * teardown did not occur. */ - public abstract boolean teardown(); + public boolean teardown(); /** * Reenable connectivity to a network after a {@link #teardown()}. * @return {@code true} if we're connected or expect to be connected */ - public abstract boolean reconnect(); + public boolean reconnect(); /** * Turn the wireless radio off for a network. * @param turnOn {@code true} to turn the radio on, {@code false} */ - public abstract boolean setRadio(boolean turnOn); + public boolean setRadio(boolean turnOn); /** * Returns an indication of whether this network is available for * connections. A value of {@code false} means that some quasi-permanent * condition prevents connectivity to this network. */ - public abstract boolean isAvailable(); + public boolean 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. + */ + public int startUsingNetworkFeature(String feature, int callingPid, int callingUid); /** - * Ensure that a network route exists to deliver traffic to the specified - * host via this network interface. - * @param hostAddress the IP address of the host to which the route is desired - * @return {@code true} on success, {@code false} on failure + * 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. */ - public boolean requestRouteToHost(int hostAddress) { - return false; - } + public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid); /** * Interprets scan results. This will be called at a safe time for * processing, and from a safe thread. */ - public void interpretScanResultsAvailable() { - } + public void interpretScanResultsAvailable(); } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 1ec8d0a..33df76c 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -28,6 +28,7 @@ import android.net.MobileDataStateTracker; import android.net.NetworkInfo; import android.net.NetworkStateTracker; import android.net.wifi.WifiStateTracker; +import android.net.NetworkUtils; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -46,6 +47,8 @@ import com.android.internal.telephony.Phone; import com.android.server.connectivity.Tethering; import java.io.FileDescriptor; +import java.io.FileWriter; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -743,7 +746,32 @@ public class ConnectivityService extends IConnectivityManager.Stub { } return false; } - return tracker.requestRouteToHost(hostAddress); + return addHostRoute(tracker, hostAddress); + } + + /** + * Ensure that a network route exists to deliver traffic to the specified + * host via the mobile data network. + * @param hostAddress the IP address of the host to which the route is desired, + * in network byte order. + * @return {@code true} on success, {@code false} on failure + */ + private boolean addHostRoute(NetworkStateTracker nt, int hostAddress) { + if (nt.getNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI) { + return false; + } + + String interfaceName = nt.getInterfaceName(); + + if (DBG) { + Slog.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress) + + "(" + interfaceName + ")"); + } + if (interfaceName != null && hostAddress != -1) { + return NetworkUtils.addHostRoute(interfaceName, hostAddress) == 0; + } else { + return false; + } } /** @@ -1133,7 +1161,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mActiveDefaultNetwork = type; } thisNet.setTeardownRequested(false); - thisNet.updateNetworkSettings(); + updateNetworkSettings(thisNet); handleConnectivityChange(); sendConnectedBroadcast(info); } @@ -1183,20 +1211,185 @@ public class ConnectivityService extends IConnectivityManager.Stub { for (int netType : mPriorityList) { if (mNetTrackers[netType].getNetworkInfo().isConnected()) { if (mNetAttributes[netType].isDefault()) { - mNetTrackers[netType].addDefaultRoute(); + addDefaultRoute(mNetTrackers[netType]); } else { - mNetTrackers[netType].addPrivateDnsRoutes(); + addPrivateDnsRoutes(mNetTrackers[netType]); } } else { if (mNetAttributes[netType].isDefault()) { - mNetTrackers[netType].removeDefaultRoute(); + removeDefaultRoute(mNetTrackers[netType]); } else { - mNetTrackers[netType].removePrivateDnsRoutes(); + removePrivateDnsRoutes(mNetTrackers[netType]); } } } } + private void addPrivateDnsRoutes(NetworkStateTracker nt) { + String interfaceName = nt.getInterfaceName(); + boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); + + if (DBG) { + Slog.d(TAG, "addPrivateDnsRoutes for " + nt + + "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet); + } + String[] dnsList = getNameServerList(nt.getDnsPropNames()); + if (interfaceName != null && !privateDnsRouteSet) { + for (String addrString : dnsList) { + int addr = NetworkUtils.lookupHost(addrString); + if (addr != -1 && addr != 0) { + if (DBG) Slog.d(TAG, " adding "+addrString+" ("+addr+")"); + NetworkUtils.addHostRoute(interfaceName, addr); + } + } + nt.privateDnsRouteSet(true); + } + } + + private void removePrivateDnsRoutes(NetworkStateTracker nt) { + // TODO - we should do this explicitly but the NetUtils api doesnt + // support this yet - must remove all. No worse than before + String interfaceName = nt.getInterfaceName(); + boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); + if (interfaceName != null && privateDnsRouteSet) { + if (DBG) { + Slog.d(TAG, "removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() + + " (" + interfaceName + ")"); + } + NetworkUtils.removeHostRoutes(interfaceName); + nt.privateDnsRouteSet(false); + } + } + + /** + * Return the IP addresses of the DNS servers available for this + * network interface. + * @param propertyNames the names of the system properties whose values + * give the IP addresses. Properties with no values are skipped. + * @return an array of {@code String}s containing the IP addresses + * of the DNS servers, in dot-notation. This may have fewer + * non-null entries than the list of names passed in, since + * some of the passed-in names may have empty values. + */ + String[] getNameServerList(String[] propertyNames) { + String[] dnsAddresses = new String[propertyNames.length]; + int i, j; + + for (i = 0, j = 0; i < propertyNames.length; i++) { + String value = SystemProperties.get(propertyNames[i]); + // The GSM layer sometimes sets a bogus DNS server address of + // 0.0.0.0 + if (!TextUtils.isEmpty(value) && !TextUtils.equals(value, "0.0.0.0")) { + dnsAddresses[j++] = value; + } + } + return dnsAddresses; + } + + private void addDefaultRoute(NetworkStateTracker nt) { + String interfaceName = nt.getInterfaceName(); + int defaultGatewayAddr = nt.getDefaultGatewayAddr(); + boolean defaultRouteSet = nt.isDefaultRouteSet(); + NetworkInfo networkInfo = nt.getNetworkInfo(); + + if ((interfaceName != null) && (defaultGatewayAddr != 0) && + defaultRouteSet == false) { + if (DBG) { + Slog.d(TAG, "addDefaultRoute for " + networkInfo.getTypeName() + + " (" + interfaceName + "), GatewayAddr=" + defaultGatewayAddr); + } + NetworkUtils.setDefaultRoute(interfaceName, defaultGatewayAddr); + nt.defaultRouteSet(true); + } + } + + + public void removeDefaultRoute(NetworkStateTracker nt) { + String interfaceName = nt.getInterfaceName(); + boolean defaultRouteSet = nt.isDefaultRouteSet(); + NetworkInfo networkInfo = nt.getNetworkInfo(); + + if (interfaceName != null && defaultRouteSet == true) { + if (DBG) { + Slog.d(TAG, "removeDefaultRoute for " + networkInfo.getTypeName() + " (" + + interfaceName + ")"); + } + NetworkUtils.removeDefaultRoute(interfaceName); + nt.defaultRouteSet(false); + } + } + + /** + * Reads the network specific TCP buffer sizes from SystemProperties + * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system + * wide use + */ + public void updateNetworkSettings(NetworkStateTracker nt) { + String key = nt.getTcpBufferSizesPropName(); + String bufferSizes = SystemProperties.get(key); + + if (bufferSizes.length() == 0) { + Slog.e(TAG, key + " not found in system properties. Using defaults"); + + // Setting to default values so we won't be stuck to previous values + key = "net.tcp.buffersize.default"; + bufferSizes = SystemProperties.get(key); + } + + // Set values in kernel + if (bufferSizes.length() != 0) { + if (DBG) { + Slog.v(TAG, "Setting TCP values: [" + bufferSizes + + "] which comes from [" + key + "]"); + } + setBufferSize(bufferSizes); + } + } + + /** + * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] + * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem + * + * @param bufferSizes in the format of "readMin, readInitial, readMax, + * writeMin, writeInitial, writeMax" + */ + private void setBufferSize(String bufferSizes) { + try { + String[] values = bufferSizes.split(","); + + if (values.length == 6) { + final String prefix = "/sys/kernel/ipv4/tcp_"; + stringToFile(prefix + "rmem_min", values[0]); + stringToFile(prefix + "rmem_def", values[1]); + stringToFile(prefix + "rmem_max", values[2]); + stringToFile(prefix + "wmem_min", values[3]); + stringToFile(prefix + "wmem_def", values[4]); + stringToFile(prefix + "wmem_max", values[5]); + } else { + Slog.e(TAG, "Invalid buffersize string: " + bufferSizes); + } + } catch (IOException e) { + Slog.e(TAG, "Can't set tcp buffer sizes:" + e); + } + } + + /** + * Writes string to file. Basically same as "echo -n $string > $filename" + * + * @param filename + * @param string + * @throws IOException + */ + private void stringToFile(String filename, String string) throws IOException { + FileWriter out = new FileWriter(filename); + try { + out.write(string); + } finally { + out.close(); + } + } + + /** * Adjust the per-process dns entries (net.dns<x>.<pid>) based * on the highest priority active net which this process requested. @@ -1216,7 +1409,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { for (int j=0; j<pids.size(); j++) { Integer pid = (Integer)pids.get(j); if (pid.intValue() == myPid) { - String[] dnsList = nt.getNameServers(); + String[] dnsList = getNameServerList(nt.getDnsPropNames()); writePidDns(dnsList, myPid); if (doBump) { bumpDns(); @@ -1270,7 +1463,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { NetworkStateTracker nt = mNetTrackers[netType]; if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { - String[] dnsList = nt.getNameServers(); + String[] dnsList = getNameServerList(nt.getDnsPropNames()); if (mNetAttributes[netType].isDefault()) { int j = 1; for (String dns : dnsList) { diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 364cc16..76f6387 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -66,7 +66,7 @@ import java.util.concurrent.atomic.AtomicInteger; * * @hide */ -public class WifiStateTracker extends NetworkStateTracker { +public class WifiStateTracker extends Handler implements NetworkStateTracker { private static final boolean LOCAL_LOGD = Config.LOGD || false; @@ -197,6 +197,8 @@ public class WifiStateTracker extends NetworkStateTracker { private boolean mHaveIpAddress; private boolean mObtainingIpAddress; private boolean mTornDownByConnMgr; + private NetworkInfo mNetworkInfo; + private boolean mTeardownRequested = false; /** * A DISCONNECT event has been received, but processing it * is being deferred. @@ -314,6 +316,11 @@ public class WifiStateTracker extends NetworkStateTracker { private static String LS = System.getProperty("line.separator"); private static String[] sDnsPropNames; + private Handler mTarget; + private Context mContext; + private boolean mPrivateDnsRouteSet = false; + private int mDefaultGatewayAddr = 0; + private boolean mDefaultRouteSet = false; /** * A structure for supplying information about a supplicant state @@ -349,8 +356,9 @@ public class WifiStateTracker extends NetworkStateTracker { } public WifiStateTracker(Context context, Handler target) { - super(context, target, ConnectivityManager.TYPE_WIFI, 0, "WIFI", ""); - + mTarget = target; + mContext = context; + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", ""); mWifiInfo = new WifiInfo(); mWifiMonitor = new WifiMonitor(this); mHaveIpAddress = false; @@ -406,6 +414,57 @@ public class WifiStateTracker extends NetworkStateTracker { } /** + * Record the detailed state of a network, and if it is a + * change from the previous state, send a notification to + * any listeners. + * @param state the new @{code DetailedState} + */ + private void setDetailedState(NetworkInfo.DetailedState state) { + setDetailedState(state, null, null); + } + + /** + * Record the detailed state of a network, and if it is a + * change from the previous state, send a notification to + * any listeners. + * @param state the new @{code DetailedState} + * @param reason a {@code String} indicating a reason for the state change, + * if one was supplied. May be {@code null}. + * @param extraInfo optional {@code String} providing extra information about the state change + */ + private void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) { + if (LOCAL_LOGD) Log.d(TAG, "setDetailed state, old =" + + mNetworkInfo.getDetailedState() + " and new state=" + state); + if (state != mNetworkInfo.getDetailedState()) { + boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING); + String lastReason = mNetworkInfo.getReason(); + /* + * If a reason was supplied when the CONNECTING state was entered, and no + * reason was supplied for entering the CONNECTED state, then retain the + * reason that was supplied when going to CONNECTING. + */ + if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null + && lastReason != null) + reason = lastReason; + mNetworkInfo.setDetailedState(state, reason, extraInfo); + Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); + msg.sendToTarget(); + } + } + + private void setDetailedStateInternal(NetworkInfo.DetailedState state) { + mNetworkInfo.setDetailedState(state, null, null); + } + + public void setTeardownRequested(boolean isRequested) { + mTeardownRequested = isRequested; + } + + public boolean isTeardownRequested() { + return mTeardownRequested; + } + + /** * Helper method: sets the boolean indicating that the connection * manager asked the network to be torn down (and so only the connection * manager can set it up again). @@ -422,8 +481,8 @@ public class WifiStateTracker extends NetworkStateTracker { * network interface. * @return a list of DNS addresses, with no holes. */ - public String[] getNameServers() { - return getNameServerList(sDnsPropNames); + public String[] getDnsPropNames() { + return sDnsPropNames; } /** @@ -434,6 +493,30 @@ public class WifiStateTracker extends NetworkStateTracker { return mInterfaceName; } + public boolean isPrivateDnsRouteSet() { + return mPrivateDnsRouteSet; + } + + public void privateDnsRouteSet(boolean enabled) { + mPrivateDnsRouteSet = enabled; + } + + public NetworkInfo getNetworkInfo() { + return mNetworkInfo; + } + + public int getDefaultGatewayAddr() { + return mDefaultGatewayAddr; + } + + public boolean isDefaultRouteSet() { + return mDefaultRouteSet; + } + + public void defaultRouteSet(boolean enabled) { + mDefaultRouteSet = enabled; + } + /** * Return the system properties name associated with the tcp buffer sizes * for this network. @@ -692,7 +775,6 @@ public class WifiStateTracker extends NetworkStateTracker { * messages in the asynchronous call * from ConnectivityService */ - @Override public void releaseWakeLock() { } @@ -2051,7 +2133,26 @@ public class WifiStateTracker extends NetworkStateTracker { return mWM.setWifiEnabled(turnOn); } - @Override + /** + * {@inheritDoc} + * There are currently no Wi-Fi-specific features supported. + * @param feature the name of the feature + * @return {@code -1} indicating failure, always + */ + public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + + /** + * {@inheritDoc} + * There are currently no Wi-Fi-specific features supported. + * @param feature the name of the feature + * @return {@code -1} indicating failure, always + */ + public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) { + return -1; + } + public void interpretScanResultsAvailable() { // If we shouldn't place a notification on available networks, then @@ -2097,6 +2198,15 @@ public class WifiStateTracker extends NetworkStateTracker { } /** + * Send a notification that the results of a scan for network access + * points has completed, and results are available. + */ + private void sendScanResultsAvailable() { + Message msg = mTarget.obtainMessage(EVENT_SCAN_RESULTS_AVAILABLE, mNetworkInfo); + msg.sendToTarget(); + } + + /** * Display or don't display a notification that there are open Wi-Fi networks. * @param visible {@code true} if notification should be visible, {@code false} otherwise * @param numNetworks the number networks seen |
