summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/MobileDataStateTracker.java203
-rw-r--r--core/java/android/net/NetworkInfo.java8
-rw-r--r--core/java/android/net/NetworkStateTracker.java343
-rw-r--r--services/java/com/android/server/ConnectivityService.java209
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java124
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