Merge "Re-hide onPreCheck and unhide NET_CAPABILITY_VALIDATED." into mnc-dev
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 96bf503..04a29aa 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -801,28 +801,6 @@
}
/**
- * Returns details about the Provisioning or currently active default data network. When
- * connected, this network is the default route for outgoing connections.
- * You should always check {@link NetworkInfo#isConnected()} before initiating
- * network traffic. This may return {@code null} when there is no default
- * network.
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
- *
- * @return a {@link NetworkInfo} object for the current default network
- * or {@code null} if no default network is currently active
- *
- * {@hide}
- */
- public NetworkInfo getProvisioningOrActiveNetworkInfo() {
- try {
- return mService.getProvisioningOrActiveNetworkInfo();
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
* Returns the IP information for the current default network.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
@@ -2007,24 +1985,6 @@
}
/**
- * Signal that the captive portal check on the indicated network
- * is complete and whether its a captive portal or not.
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
- *
- * @param info the {@link NetworkInfo} object for the networkType
- * in question.
- * @param isCaptivePortal true/false.
- * {@hide}
- */
- public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
- try {
- mService.captivePortalCheckCompleted(info, isCaptivePortal);
- } catch (RemoteException e) {
- }
- }
-
- /**
* Check mobile provisioning.
*
* @param suggestedTimeOutMs, timeout in milliseconds
@@ -2056,18 +2016,6 @@
}
/**
- * Get the mobile redirected provisioning url.
- * {@hide}
- */
- public String getMobileRedirectedProvisioningUrl() {
- try {
- return mService.getMobileRedirectedProvisioningUrl();
- } catch (RemoteException e) {
- }
- return null;
- }
-
- /**
* Set sign in error notification to visible or in visible
*
* @param visible
@@ -2515,7 +2463,7 @@
* Intent to reserve the network or it will be released shortly after the Intent
* is processed.
* <p>
- * If there is already an request for this Intent registered (with the equality of
+ * If there is already a request for this Intent registered (with the equality of
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
* <p>
@@ -2575,6 +2523,44 @@
}
/**
+ * Registers a PendingIntent to be sent when a network is available which satisfies the given
+ * {@link NetworkRequest}.
+ *
+ * This function behaves identically to the version that takes a NetworkCallback, but instead
+ * of {@link NetworkCallback} a {@link PendingIntent} is used. This means
+ * the request may outlive the calling application and get called back when a suitable
+ * network is found.
+ * <p>
+ * The operation is an Intent broadcast that goes to a broadcast receiver that
+ * you registered with {@link Context#registerReceiver} or through the
+ * <receiver> tag in an AndroidManifest.xml file
+ * <p>
+ * The operation Intent is delivered with two extras, a {@link Network} typed
+ * extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest}
+ * typed extra called {@link #EXTRA_NETWORK_REQUEST} containing
+ * the original requests parameters.
+ * <p>
+ * If there is already a request for this Intent registered (with the equality of
+ * two Intents defined by {@link Intent#filterEquals}), then it will be removed and
+ * replaced by this one, effectively releasing the previous {@link NetworkRequest}.
+ * <p>
+ * The request may be released normally by calling
+ * {@link #releaseNetworkRequest(android.app.PendingIntent)}.
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ * @param request {@link NetworkRequest} describing this request.
+ * @param operation Action to perform when the network is available (corresponds
+ * to the {@link NetworkCallback#onAvailable} call. Typically
+ * comes from {@link PendingIntent#getBroadcast}. Cannot be null.
+ */
+ public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
+ checkPendingIntent(operation);
+ try {
+ mService.pendingListenForNetwork(request.networkCapabilities, operation);
+ } catch (RemoteException e) {}
+ }
+
+ /**
* Requests bandwidth update for a given {@link Network} and returns whether the update request
* is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying
* network connection for updated bandwidth information. The caller will be notified via
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 89d23a2..29557bb 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -53,8 +53,6 @@
Network[] getAllNetworks();
NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId);
- NetworkInfo getProvisioningOrActiveNetworkInfo();
-
boolean isNetworkSupported(int networkType);
LinkProperties getActiveLinkProperties();
@@ -122,14 +120,10 @@
boolean updateLockdownVpn();
- void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
-
int checkMobileProvisioning(int suggestedTimeOutMs);
String getMobileProvisioningUrl();
- String getMobileRedirectedProvisioningUrl();
-
void setProvisioningNotificationVisible(boolean visible, int networkType, in String action);
void setAirplaneMode(boolean enable);
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 9628bae..fe69320 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -378,6 +378,9 @@
//
// The HANDLE_MAGIC value MUST be kept in sync with the corresponding
// value in the native/android/net.c NDK implementation.
+ if (netId == 0) {
+ return 0L; // make this zero condition obvious for debugging
+ }
final long HANDLE_MAGIC = 0xfacade;
return (((long) netId) << 32) | HANDLE_MAGIC;
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 393637e..af7a465 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -120,7 +120,6 @@
private String mExtraInfo;
private boolean mIsFailover;
private boolean mIsRoaming;
- private boolean mIsConnectedToProvisioningNetwork;
/**
* Indicates whether network connectivity is possible:
@@ -142,7 +141,6 @@
mState = State.UNKNOWN;
mIsAvailable = false; // until we're told otherwise, assume unavailable
mIsRoaming = false;
- mIsConnectedToProvisioningNetwork = false;
}
/** {@hide} */
@@ -160,7 +158,6 @@
mIsFailover = source.mIsFailover;
mIsRoaming = source.mIsRoaming;
mIsAvailable = source.mIsAvailable;
- mIsConnectedToProvisioningNetwork = source.mIsConnectedToProvisioningNetwork;
}
}
}
@@ -332,22 +329,6 @@
}
}
- /** {@hide} */
- @VisibleForTesting
- public boolean isConnectedToProvisioningNetwork() {
- synchronized (this) {
- return mIsConnectedToProvisioningNetwork;
- }
- }
-
- /** {@hide} */
- @VisibleForTesting
- public void setIsConnectedToProvisioningNetwork(boolean val) {
- synchronized (this) {
- mIsConnectedToProvisioningNetwork = val;
- }
- }
-
/**
* Reports the current coarse-grained state of the network.
* @return the coarse-grained state
@@ -431,8 +412,6 @@
append(", roaming: ").append(mIsRoaming).
append(", failover: ").append(mIsFailover).
append(", isAvailable: ").append(mIsAvailable).
- append(", isConnectedToProvisioningNetwork: ").
- append(mIsConnectedToProvisioningNetwork).
append("]");
return builder.toString();
}
@@ -461,7 +440,6 @@
dest.writeInt(mIsFailover ? 1 : 0);
dest.writeInt(mIsAvailable ? 1 : 0);
dest.writeInt(mIsRoaming ? 1 : 0);
- dest.writeInt(mIsConnectedToProvisioningNetwork ? 1 : 0);
dest.writeString(mReason);
dest.writeString(mExtraInfo);
}
@@ -484,7 +462,6 @@
netInfo.mIsFailover = in.readInt() != 0;
netInfo.mIsAvailable = in.readInt() != 0;
netInfo.mIsRoaming = in.readInt() != 0;
- netInfo.mIsConnectedToProvisioningNetwork = in.readInt() != 0;
netInfo.mReason = in.readString();
netInfo.mExtraInfo = in.readString();
return netInfo;
diff --git a/core/tests/coretests/src/android/net/NetworkTest.java b/core/tests/coretests/src/android/net/NetworkTest.java
index b0ecb04..74b6d98 100644
--- a/core/tests/coretests/src/android/net/NetworkTest.java
+++ b/core/tests/coretests/src/android/net/NetworkTest.java
@@ -16,11 +16,14 @@
package android.net;
+import static android.test.MoreAsserts.assertNotEqual;
+
import android.net.LocalServerSocket;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.Network;
import android.test.suitebuilder.annotation.SmallTest;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -29,6 +32,7 @@
import java.net.InetAddress;
import java.net.Inet6Address;
import java.net.SocketException;
+
import junit.framework.TestCase;
public class NetworkTest extends TestCase {
@@ -93,4 +97,50 @@
fail("SocketException not thrown");
} catch (SocketException expected) {}
}
+
+ @SmallTest
+ public void testZeroIsObviousForDebugging() {
+ Network zero = new Network(0);
+ assertEquals(0, zero.hashCode());
+ assertEquals(0, zero.getNetworkHandle());
+ assertEquals("0", zero.toString());
+ }
+
+ @SmallTest
+ public void testGetNetworkHandle() {
+ Network one = new Network(1);
+ Network two = new Network(2);
+ Network three = new Network(3);
+
+ // None of the hashcodes are zero.
+ assertNotEqual(0, one.hashCode());
+ assertNotEqual(0, two.hashCode());
+ assertNotEqual(0, three.hashCode());
+
+ // All the hashcodes are distinct.
+ assertNotEqual(one.hashCode(), two.hashCode());
+ assertNotEqual(one.hashCode(), three.hashCode());
+ assertNotEqual(two.hashCode(), three.hashCode());
+
+ // None of the handles are zero.
+ assertNotEqual(0, one.getNetworkHandle());
+ assertNotEqual(0, two.getNetworkHandle());
+ assertNotEqual(0, three.getNetworkHandle());
+
+ // All the handles are distinct.
+ assertNotEqual(one.getNetworkHandle(), two.getNetworkHandle());
+ assertNotEqual(one.getNetworkHandle(), three.getNetworkHandle());
+ assertNotEqual(two.getNetworkHandle(), three.getNetworkHandle());
+
+ // The handles are not equal to the hashcodes.
+ assertNotEqual(one.hashCode(), one.getNetworkHandle());
+ assertNotEqual(two.hashCode(), two.getNetworkHandle());
+ assertNotEqual(three.hashCode(), three.getNetworkHandle());
+
+ // Adjust as necessary to test an implementation's specific constants.
+ // When running with runtest, "adb logcat -s TestRunner" can be useful.
+ assertEquals(4311403230L, one.getNetworkHandle());
+ assertEquals(8606370526L, two.getNetworkHandle());
+ assertEquals(12901337822L, three.getNetworkHandle());
+ }
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9c6e16f..25d4d5e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -136,11 +136,13 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -324,7 +326,7 @@
/**
* used to add a network request with a pending intent
- * includes a NetworkRequestInfo
+ * obj = NetworkRequestInfo
*/
private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26;
@@ -354,6 +356,12 @@
*/
private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
+ /**
+ * used to add a network listener with a pending intent
+ * obj = NetworkRequestInfo
+ */
+ private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
+
/** Handler used for internal events. */
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -960,44 +968,6 @@
return nai != null ? nai.network : null;
}
- /**
- * Find the first Provisioning network.
- *
- * @return NetworkInfo or null if none.
- */
- private NetworkInfo getProvisioningNetworkInfo() {
- enforceAccessPermission();
-
- // Find the first Provisioning Network
- NetworkInfo provNi = null;
- for (NetworkInfo ni : getAllNetworkInfo()) {
- if (ni.isConnectedToProvisioningNetwork()) {
- provNi = ni;
- break;
- }
- }
- if (DBG) log("getProvisioningNetworkInfo: X provNi=" + provNi);
- return provNi;
- }
-
- /**
- * Find the first Provisioning network or the ActiveDefaultNetwork
- * if there is no Provisioning network
- *
- * @return NetworkInfo or null if none.
- */
- @Override
- public NetworkInfo getProvisioningOrActiveNetworkInfo() {
- enforceAccessPermission();
-
- NetworkInfo provNi = getProvisioningNetworkInfo();
- if (provNi == null) {
- provNi = getActiveNetworkInfo();
- }
- if (DBG) log("getProvisioningOrActiveNetworkInfo: X provNi=" + provNi);
- return provNi;
- }
-
public NetworkInfo getActiveNetworkInfoUnfiltered() {
enforceAccessPermission();
final int uid = Binder.getCallingUid();
@@ -1567,14 +1537,6 @@
}
};
- /** @hide */
- @Override
- public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
- enforceConnectivityInternalPermission();
- if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal);
-// mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal);
- }
-
/**
* Setup data activity tracking for the given network.
*
@@ -2112,15 +2074,6 @@
log(nai.name() + " got DISCONNECTED, was satisfying " + nai.networkRequests.size());
}
// A network agent has disconnected.
- if (nai.created) {
- // Tell netd to clean up the configuration for this network
- // (routing rules, DNS, etc).
- try {
- mNetd.removeNetwork(nai.network.netId);
- } catch (Exception e) {
- loge("Exception removing network: " + e);
- }
- }
// TODO - if we move the logic to the network agent (have them disconnect
// because they lost all their requests or because their score isn't good)
// then they would disconnect organically, report their new state and then
@@ -2139,8 +2092,9 @@
mNetworkAgentInfos.remove(msg.replyTo);
updateClat(null, nai.linkProperties, nai);
synchronized (mNetworkForNetId) {
+ // Remove the NetworkAgent, but don't mark the netId as
+ // available until we've told netd to delete it below.
mNetworkForNetId.remove(nai.network.netId);
- mNetIdInUse.delete(nai.network.netId);
}
// Since we've lost the network, go through all the requests that
// it was satisfying and see if any other factory can satisfy them.
@@ -2182,9 +2136,28 @@
rematchNetworkAndRequests(networkToActivate, NascentState.NOT_JUST_VALIDATED,
ReapUnvalidatedNetworks.DONT_REAP);
}
+ if (nai.created) {
+ // Tell netd to clean up the configuration for this network
+ // (routing rules, DNS, etc).
+ // This may be slow as it requires a lot of netd shelling out to ip and
+ // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it
+ // after we've rematched networks with requests which should make a potential
+ // fallback network the default or requested a new network from the
+ // NetworkFactories, so network traffic isn't interrupted for an unnecessarily
+ // long time.
+ try {
+ mNetd.removeNetwork(nai.network.netId);
+ } catch (Exception e) {
+ loge("Exception removing network: " + e);
+ }
+ }
+ synchronized (mNetworkForNetId) {
+ mNetIdInUse.delete(nai.network.netId);
+ }
+ } else {
+ NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
+ if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
}
- NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo);
- if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name);
}
// If this method proves to be too slow then we can maintain a separate
@@ -2229,7 +2202,9 @@
// Not setting bestNetwork here as a listening NetworkRequest may be
// satisfied by multiple Networks. Instead the request is added to
// each satisfying Network and notified about each.
- network.addRequest(nri.request);
+ if (!network.addRequest(nri.request)) {
+ Slog.wtf(TAG, "BUG: " + network.name() + " already has " + nri.request);
+ }
notifyNetworkCallback(network, nri);
} else if (bestNetwork == null ||
bestNetwork.getCurrentScore() < network.getCurrentScore()) {
@@ -2240,7 +2215,9 @@
if (bestNetwork != null) {
if (DBG) log("using " + bestNetwork.name());
unlinger(bestNetwork);
- bestNetwork.addRequest(nri.request);
+ if (!bestNetwork.addRequest(nri.request)) {
+ Slog.wtf(TAG, "BUG: " + bestNetwork.name() + " already has " + nri.request);
+ }
mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
notifyNetworkCallback(bestNetwork, nri);
if (nri.request.legacyType != TYPE_NONE) {
@@ -2524,7 +2501,8 @@
handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
break;
}
- case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: {
+ case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT:
+ case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: {
handleRegisterNetworkRequestWithIntent(msg);
break;
}
@@ -3289,7 +3267,6 @@
CharSequence title;
CharSequence details;
int icon;
- Notification notification = new Notification();
if (notifyType == NotificationType.NO_INTERNET &&
networkType == ConnectivityManager.TYPE_WIFI) {
title = r.getString(R.string.wifi_no_internet, 0);
@@ -3324,14 +3301,17 @@
return;
}
- notification.when = 0;
- notification.icon = icon;
- notification.flags = Notification.FLAG_AUTO_CANCEL;
- notification.tickerText = title;
- notification.color = mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color);
- notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
- notification.contentIntent = intent;
+ Notification notification = new Notification.Builder(mContext)
+ .setWhen(0)
+ .setSmallIcon(icon)
+ .setAutoCancel(true)
+ .setTicker(title)
+ .setColor(mContext.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(details)
+ .setContentIntent(intent)
+ .build();
try {
notificationManager.notify(NOTIFICATION_ID, id, notification);
@@ -3355,7 +3335,6 @@
* <?xml version="1.0" encoding="utf-8"?>
* <provisioningUrls>
* <provisioningUrl mcc="310" mnc="4">http://myserver.com/foo?mdn=%3$s&iccid=%1$s&imei=%2$s</provisioningUrl>
- * <redirectedUrl mcc="310" mnc="4">http://www.google.com</redirectedUrl>
* </provisioningUrls>
*/
private static final String PROVISIONING_URL_PATH =
@@ -3366,33 +3345,15 @@
private static final String TAG_PROVISIONING_URLS = "provisioningUrls";
/** XML tag for individual url */
private static final String TAG_PROVISIONING_URL = "provisioningUrl";
- /** XML tag for redirected url */
- private static final String TAG_REDIRECTED_URL = "redirectedUrl";
/** XML attribute for mcc */
private static final String ATTR_MCC = "mcc";
/** XML attribute for mnc */
private static final String ATTR_MNC = "mnc";
- private static final int REDIRECTED_PROVISIONING = 1;
- private static final int PROVISIONING = 2;
-
- private String getProvisioningUrlBaseFromFile(int type) {
+ private String getProvisioningUrlBaseFromFile() {
FileReader fileReader = null;
XmlPullParser parser = null;
Configuration config = mContext.getResources().getConfiguration();
- String tagType;
-
- switch (type) {
- case PROVISIONING:
- tagType = TAG_PROVISIONING_URL;
- break;
- case REDIRECTED_PROVISIONING:
- tagType = TAG_REDIRECTED_URL;
- break;
- default:
- throw new RuntimeException("getProvisioningUrlBaseFromFile: Unexpected parameter " +
- type);
- }
try {
fileReader = new FileReader(mProvisioningUrlFile);
@@ -3406,7 +3367,7 @@
String element = parser.getName();
if (element == null) break;
- if (element.equals(tagType)) {
+ if (element.equals(TAG_PROVISIONING_URL)) {
String mcc = parser.getAttributeValue(null, ATTR_MCC);
try {
if (mcc != null && Integer.parseInt(mcc) == config.mcc) {
@@ -3441,19 +3402,9 @@
}
@Override
- public String getMobileRedirectedProvisioningUrl() {
- enforceConnectivityInternalPermission();
- String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
- if (TextUtils.isEmpty(url)) {
- url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
- }
- return url;
- }
-
- @Override
public String getMobileProvisioningUrl() {
enforceConnectivityInternalPermission();
- String url = getProvisioningUrlBaseFromFile(PROVISIONING);
+ String url = getProvisioningUrlBaseFromFile();
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_provisioning_url);
log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
@@ -3760,6 +3711,18 @@
@Override
public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
PendingIntent operation) {
+ checkNotNull(operation, "PendingIntent cannot be null.");
+ if (!hasWifiNetworkListenPermission(networkCapabilities)) {
+ enforceAccessPermission();
+ }
+
+ NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
+ networkCapabilities), TYPE_NONE, nextNetworkRequestId());
+ if (DBG) log("pendingListenForNetwork for " + networkRequest + " to trigger " + operation);
+ NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
+ NetworkRequestInfo.LISTEN);
+
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
}
@Override
@@ -3993,10 +3956,52 @@
}
return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
}
+
+ // TODO: investigate moving this into LinkProperties, if only to make more accurate
+ // the isProvisioned() checks.
+ private static Collection<InetAddress> getLikelyReachableDnsServers(LinkProperties lp) {
+ final ArrayList<InetAddress> dnsServers = new ArrayList<InetAddress>();
+ final List<RouteInfo> allRoutes = lp.getAllRoutes();
+ for (InetAddress nameserver : lp.getDnsServers()) {
+ // If the LinkProperties doesn't include a route to the nameserver, ignore it.
+ final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, nameserver);
+ if (bestRoute == null) {
+ continue;
+ }
+
+ // TODO: better source address evaluation for destination addresses.
+ if (nameserver instanceof Inet4Address) {
+ if (!lp.hasIPv4Address()) {
+ continue;
+ }
+ } else if (nameserver instanceof Inet6Address) {
+ if (nameserver.isLinkLocalAddress()) {
+ if (((Inet6Address)nameserver).getScopeId() == 0) {
+ // For now, just make sure link-local DNS servers have
+ // scopedIds set, since DNS lookups will fail otherwise.
+ // TODO: verify the scopeId matches that of lp's interface.
+ continue;
+ }
+ } else {
+ if (bestRoute.isIPv6Default() && !lp.hasGlobalIPv6Address()) {
+ // TODO: reconsider all corner cases (disconnected ULA networks, ...).
+ continue;
+ }
+ }
+ }
+
+ dnsServers.add(nameserver);
+ }
+ return Collections.unmodifiableList(dnsServers);
+ }
+
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId,
boolean flush, boolean useDefaultDns) {
+ // TODO: consider comparing the getLikelyReachableDnsServers() lists, in case the
+ // route to a DNS server has been removed (only really applicable in special cases
+ // where there is no default route).
if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
- Collection<InetAddress> dnses = newLp.getDnsServers();
+ Collection<InetAddress> dnses = getLikelyReachableDnsServers(newLp);
if (dnses.size() == 0 && mDefaultDns != null && useDefaultDns) {
dnses = new ArrayList();
dnses.add(mDefaultDns);
@@ -4226,6 +4231,7 @@
// Find and migrate to this Network any NetworkRequests for
// which this network is now the best.
ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>();
+ ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>();
if (VDBG) log(" network has: " + newNetwork.networkCapabilities);
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
@@ -4244,7 +4250,7 @@
if (!nri.isRequest) {
// This is not a request, it's a callback listener.
// Add it to newNetwork regardless of score.
- newNetwork.addRequest(nri.request);
+ if (newNetwork.addRequest(nri.request)) addedRequests.add(nri);
continue;
}
@@ -4267,7 +4273,10 @@
}
unlinger(newNetwork);
mNetworkForRequestId.put(nri.request.requestId, newNetwork);
- newNetwork.addRequest(nri.request);
+ if (!newNetwork.addRequest(nri.request)) {
+ Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
+ }
+ addedRequests.add(nri);
keep = true;
// Tell NetworkFactories about the new score, so they can stop
// trying to connect if they know they cannot match it.
@@ -4310,7 +4319,7 @@
// do this after the default net is switched, but
// before LegacyTypeTracker sends legacy broadcasts
- notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
+ for (NetworkRequestInfo nri : addedRequests) notifyNetworkCallback(newNetwork, nri);
if (isNewDefault) {
// Maintain the illusion: since the legacy API only
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index eac748f..3bf1183 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -106,8 +106,16 @@
networkMisc = misc;
}
- public void addRequest(NetworkRequest networkRequest) {
+ /**
+ * Add {@code networkRequest} to this network as it's satisfied by this network.
+ * NOTE: This function must only be called on ConnectivityService's main thread.
+ * @return true if {@code networkRequest} was added or false if {@code networkRequest} was
+ * already present.
+ */
+ public boolean addRequest(NetworkRequest networkRequest) {
+ if (networkRequests.get(networkRequest.requestId) == networkRequest) return false;
networkRequests.put(networkRequest.requestId, networkRequest);
+ return true;
}
// Does this network satisfy request?
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index bb0a36f..712db09 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -134,6 +134,7 @@
private final NetworkInfo mNetworkInfo;
private final NetworkCapabilities mNetworkCapabilities;
private final Thread mThread;
+ private int mScore;
private NetworkAgent mNetworkAgent;
MockNetworkAgent(int transport) {
@@ -142,13 +143,12 @@
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addTransportType(transport);
- final int score;
switch (transport) {
case TRANSPORT_WIFI:
- score = 60;
+ mScore = 60;
break;
case TRANSPORT_CELLULAR:
- score = 50;
+ mScore = 50;
break;
default:
throw new UnsupportedOperationException("unimplemented network type");
@@ -159,7 +159,7 @@
Looper.prepare();
mNetworkAgent = new NetworkAgent(Looper.myLooper(), mServiceContext,
"Mock" + typeName, mNetworkInfo, mNetworkCapabilities,
- new LinkProperties(), score, new NetworkMisc()) {
+ new LinkProperties(), mScore, new NetworkMisc()) {
public void unwanted() {}
};
initComplete.open();
@@ -167,7 +167,12 @@
}
};
mThread.start();
- initComplete.block();
+ waitFor(initComplete);
+ }
+
+ public void adjustScore(int change) {
+ mScore += change;
+ mNetworkAgent.sendNetworkScore(mScore);
}
/**
@@ -209,7 +214,7 @@
if (validated) {
// Wait for network to validate.
- validatedCv.block();
+ waitFor(validatedCv);
mNetworkCapabilities.addCapability(NET_CAPABILITY_INTERNET);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
@@ -228,6 +233,10 @@
}
private static class MockNetworkFactory extends NetworkFactory {
+ final ConditionVariable mNetworkStartedCV = new ConditionVariable();
+ final ConditionVariable mNetworkStoppedCV = new ConditionVariable();
+ final ConditionVariable mNetworkRequestedCV = new ConditionVariable();
+ final ConditionVariable mNetworkReleasedCV = new ConditionVariable();
final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
public MockNetworkFactory(Looper looper, Context context, String logTag,
@@ -241,15 +250,51 @@
protected void startNetwork() {
mNetworkStarted.set(true);
+ mNetworkStartedCV.open();
}
protected void stopNetwork() {
mNetworkStarted.set(false);
+ mNetworkStoppedCV.open();
}
public boolean getMyStartRequested() {
return mNetworkStarted.get();
}
+
+ public ConditionVariable getNetworkStartedCV() {
+ mNetworkStartedCV.close();
+ return mNetworkStartedCV;
+ }
+
+ public ConditionVariable getNetworkStoppedCV() {
+ mNetworkStoppedCV.close();
+ return mNetworkStoppedCV;
+ }
+
+ protected void needNetworkFor(NetworkRequest networkRequest, int score) {
+ super.needNetworkFor(networkRequest, score);
+ mNetworkRequestedCV.open();
+ }
+
+ protected void releaseNetworkFor(NetworkRequest networkRequest) {
+ super.releaseNetworkFor(networkRequest);
+ mNetworkReleasedCV.open();
+ }
+
+ public ConditionVariable getNetworkRequestedCV() {
+ mNetworkRequestedCV.close();
+ return mNetworkRequestedCV;
+ }
+
+ public ConditionVariable getNetworkReleasedCV() {
+ mNetworkReleasedCV.close();
+ return mNetworkReleasedCV;
+ }
+
+ public void waitForNetworkRequests(final int count) {
+ waitFor(new Criteria() { public boolean get() { return count == getRequestCount(); } });
+ }
}
private class WrappedConnectivityService extends ConnectivityService {
@@ -286,6 +331,45 @@
}
}
+ private interface Criteria {
+ public boolean get();
+ }
+
+ /**
+ * Wait up to 500ms for {@code criteria.get()} to become true, polling.
+ * Fails if 500ms goes by before {@code criteria.get()} to become true.
+ */
+ static private void waitFor(Criteria criteria) {
+ int delays = 0;
+ while (!criteria.get()) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ }
+ if (++delays == 5) fail();
+ }
+ }
+
+ /**
+ * Wait up to 500ms for {@code conditonVariable} to open.
+ * Fails if 500ms goes by before {@code conditionVariable} opens.
+ */
+ static private void waitFor(ConditionVariable conditionVariable) {
+ assertTrue(conditionVariable.block(500));
+ }
+
+ /**
+ * This should only be used to verify that nothing happens, in other words that no unexpected
+ * changes occur. It should never be used to wait for a specific positive signal to occur.
+ */
+ private void shortSleep() {
+ // TODO: Instead of sleeping, instead wait for all message loops to idle.
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+ }
+
@Override
public void setUp() throws Exception {
super.setUp();
@@ -376,7 +460,7 @@
// Test bringing up validated cellular.
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(true);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertEquals(2, mCm.getAllNetworks().length);
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -386,7 +470,7 @@
// Test bringing up validated WiFi.
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.connect(true);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(2, mCm.getAllNetworks().length);
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -396,7 +480,7 @@
// Test cellular linger timeout.
try {
Thread.sleep(6000);
- } catch (Exception e) {
+ } catch (InterruptedException e) {
}
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(1, mCm.getAllNetworks().length);
@@ -404,7 +488,7 @@
// Test WiFi disconnect.
cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.disconnect();
- cv.block();
+ waitFor(cv);
verifyNoNetwork();
}
@@ -414,38 +498,32 @@
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.connect(false);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- }
+ shortSleep();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test cellular disconnect.
mCellNetworkAgent.disconnect();
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- }
+ shortSleep();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
cv = waitForConnectivityBroadcasts(2);
mCellNetworkAgent.connect(true);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
cv = waitForConnectivityBroadcasts(2);
mCellNetworkAgent.disconnect();
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
cv = waitForConnectivityBroadcasts(1);
mWiFiNetworkAgent.disconnect();
- cv.block();
+ waitFor(cv);
verifyNoNetwork();
}
@@ -455,52 +533,234 @@
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
ConditionVariable cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.connect(false);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.connect(false);
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.disconnect();
- cv.block();
+ waitFor(cv);
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.disconnect();
- cv.block();
+ waitFor(cv);
verifyNoNetwork();
}
@LargeTest
+ public void testCellularOutscoresWeakWifi() throws Exception {
+ // Test bringing up validated cellular.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ ConditionVariable cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent.connect(true);
+ waitFor(cv);
+ verifyActiveNetwork(TRANSPORT_CELLULAR);
+ // Test bringing up validated WiFi.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ cv = waitForConnectivityBroadcasts(2);
+ mWiFiNetworkAgent.connect(true);
+ waitFor(cv);
+ verifyActiveNetwork(TRANSPORT_WIFI);
+ // Test WiFi getting really weak.
+ cv = waitForConnectivityBroadcasts(2);
+ mWiFiNetworkAgent.adjustScore(-11);
+ waitFor(cv);
+ verifyActiveNetwork(TRANSPORT_CELLULAR);
+ // Test WiFi restoring signal strength.
+ cv = waitForConnectivityBroadcasts(2);
+ mWiFiNetworkAgent.adjustScore(11);
+ waitFor(cv);
+ verifyActiveNetwork(TRANSPORT_WIFI);
+ mCellNetworkAgent.disconnect();
+ mWiFiNetworkAgent.disconnect();
+ }
+
+ enum CallbackState {
+ NONE,
+ AVAILABLE,
+ LOSING,
+ LOST
+ }
+
+ private class TestNetworkCallback extends NetworkCallback {
+ private final ConditionVariable mConditionVariable = new ConditionVariable();
+ private CallbackState mLastCallback = CallbackState.NONE;
+
+ public void onAvailable(Network network) {
+ assertEquals(CallbackState.NONE, mLastCallback);
+ mLastCallback = CallbackState.AVAILABLE;
+ mConditionVariable.open();
+ }
+
+ public void onLosing(Network network, int maxMsToLive) {
+ assertEquals(CallbackState.NONE, mLastCallback);
+ mLastCallback = CallbackState.LOSING;
+ mConditionVariable.open();
+ }
+
+ public void onLost(Network network) {
+ assertEquals(CallbackState.NONE, mLastCallback);
+ mLastCallback = CallbackState.LOST;
+ mConditionVariable.open();
+ }
+
+ ConditionVariable getConditionVariable() {
+ mLastCallback = CallbackState.NONE;
+ mConditionVariable.close();
+ return mConditionVariable;
+ }
+
+ CallbackState getLastCallback() {
+ return mLastCallback;
+ }
+ }
+
+ @LargeTest
+ public void testStateChangeNetworkCallbacks() throws Exception {
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
+
+ // Test unvalidated networks
+ ConditionVariable cellCv = cellNetworkCallback.getConditionVariable();
+ ConditionVariable wifiCv = wifiNetworkCallback.getConditionVariable();
+ ConditionVariable cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(false);
+ waitFor(cellCv);
+ assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ waitFor(cv);
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ // This should not trigger spurious onAvailable() callbacks, b/21762680.
+ mCellNetworkAgent.adjustScore(-1);
+ shortSleep();
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ cv = waitForConnectivityBroadcasts(2);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ waitFor(wifiCv);
+ assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ waitFor(cv);
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ cv = waitForConnectivityBroadcasts(2);
+ mWiFiNetworkAgent.disconnect();
+ waitFor(wifiCv);
+ assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
+ waitFor(cv);
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent.disconnect();
+ waitFor(cellCv);
+ assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ waitFor(cv);
+
+ // Test validated networks
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ // Our method for faking successful validation generates an additional callback, so wait
+ // for broadcast instead.
+ cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ waitFor(cv);
+ waitFor(cellCv);
+ assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ // This should not trigger spurious onAvailable() callbacks, b/21762680.
+ mCellNetworkAgent.adjustScore(-1);
+ shortSleep();
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ // Our method for faking successful validation generates an additional callback, so wait
+ // for broadcast instead.
+ cv = waitForConnectivityBroadcasts(1);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ waitFor(cv);
+ waitFor(wifiCv);
+ assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback());
+ waitFor(cellCv);
+ assertEquals(CallbackState.LOSING, cellNetworkCallback.getLastCallback());
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ mWiFiNetworkAgent.disconnect();
+ waitFor(wifiCv);
+ assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback());
+
+ cellCv = cellNetworkCallback.getConditionVariable();
+ wifiCv = wifiNetworkCallback.getConditionVariable();
+ mCellNetworkAgent.disconnect();
+ waitFor(cellCv);
+ assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback());
+ assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback());
+ }
+
+ @LargeTest
public void testNetworkFactoryRequests() throws Exception {
NetworkCapabilities filter = new NetworkCapabilities();
filter.addCapability(NET_CAPABILITY_INTERNET);
final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests");
handlerThread.start();
- MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter);
testFactory.setScoreFilter(40);
+ ConditionVariable cv = testFactory.getNetworkStartedCV();
testFactory.register();
- try {
- Thread.sleep(500);
- } catch (Exception e) {}
+ waitFor(cv);
assertEquals(1, testFactory.getMyRequestCount());
assertEquals(true, testFactory.getMyStartRequested());
// now bring in a higher scored network
MockNetworkAgent testAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
- ConditionVariable cv = waitForConnectivityBroadcasts(1);
+ cv = waitForConnectivityBroadcasts(1);
+ ConditionVariable cvRelease = testFactory.getNetworkStoppedCV();
testAgent.connect(true);
- cv.block();
+ waitFor(cv);
// part of the bringup makes another network request and then releases it
// wait for the release
- try { Thread.sleep(500); } catch (Exception e) {}
- assertEquals(1, testFactory.getMyRequestCount());
+ waitFor(cvRelease);
assertEquals(false, testFactory.getMyStartRequested());
+ testFactory.waitForNetworkRequests(1);
// bring in a bunch of requests..
ConnectivityManager.NetworkCallback[] networkCallbacks =
@@ -511,27 +771,20 @@
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mCm.requestNetwork(builder.build(), networkCallbacks[i]);
}
-
- try {
- Thread.sleep(1000);
- } catch (Exception e) {}
- assertEquals(11, testFactory.getMyRequestCount());
+ testFactory.waitForNetworkRequests(11);
assertEquals(false, testFactory.getMyStartRequested());
// remove the requests
for (int i = 0; i < networkCallbacks.length; i++) {
mCm.unregisterNetworkCallback(networkCallbacks[i]);
}
- try {
- Thread.sleep(500);
- } catch (Exception e) {}
- assertEquals(1, testFactory.getMyRequestCount());
+ testFactory.waitForNetworkRequests(1);
assertEquals(false, testFactory.getMyStartRequested());
// drop the higher scored network
cv = waitForConnectivityBroadcasts(1);
testAgent.disconnect();
- cv.block();
+ waitFor(cv);
assertEquals(1, testFactory.getMyRequestCount());
assertEquals(true, testFactory.getMyStartRequested());
@@ -557,7 +810,7 @@
//
// cv = waitForConnectivityBroadcasts(1);
// mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
-// cv.block();
+// waitFor(cv);
//
// // verify that both routes were added
// int mobileNetId = mMobile.tracker.getNetwork().netId;
@@ -577,7 +830,7 @@
//
// cv = waitForConnectivityBroadcasts(1);
// mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
-// cv.block();
+// waitFor(cv);
//
// reset(mNetManager);
//
@@ -593,7 +846,7 @@
//
// cv = waitForConnectivityBroadcasts(1);
// mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget();
-// cv.block();
+// waitFor(cv);
//
// // verify that wifi routes added, and teardown requested
// int wifiNetId = mWifi.tracker.getNetwork().netId;
@@ -612,7 +865,7 @@
//
// cv = waitForConnectivityBroadcasts(1);
// mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
-// cv.block();
+// waitFor(cv);
//
// verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4));
// verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6));