From 30311abb87da7f2d74d2b528730fa0755d1eea0d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 9 Jul 2021 16:15:58 +0900 Subject: [PATCH] Wait for next network in waitForAvailable Tests using CtsNetUtils.TestNetworkCallback would generally assume that waitForAvailable would return a non-null Network if onAvailable was called after it was registered. However this is not true if a network was available, then lost before waitForAvailable is called. This can typically happen if wifi was disconnected just before calling ensureWifiConnected (so wifi is being toggled). In case onUnavailable was called, always wait for the next onAvailable callback, so that waitForAvailable always waits for a network to be available. So: Old behavior: 1) registerNetworkCallback called 2) onAvailable called 3) onLost called 4) waitForAvailable called -> returns null immediately 5) onAvailable called -> unused New behavior: 1) registerNetworkCallback called 2) onAvailable called 3) onLost called 4) waitForAvailable called -> blocks 5) onAvailable called -> waitForAvailable returns the network Bug: 190913510 Test: atest CtsNetTestCases Change-Id: I6bde82ad787371ecffd6caa950b52d90a29ab20b --- .../android/net/cts/util/CtsNetUtils.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java index 103906a596..f5fab2fd12 100644 --- a/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java +++ b/tests/cts/net/util/java/android/net/cts/util/CtsNetUtils.java @@ -54,6 +54,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; +import android.os.ConditionVariable; import android.os.IBinder; import android.os.SystemClock; import android.system.Os; @@ -264,6 +265,9 @@ public final class CtsNetUtils { Log.w(TAG, "connect failed with " + error + "; waiting before retry"); SystemClock.sleep(WIFI_CONNECT_INTERVAL_MS); } + + fail("Failed to connect to " + config.SSID + + " after " + MAX_WIFI_CONNECT_RETRIES + "retries"); } private static class ConnectWifiListener implements WifiManager.ActionListener { @@ -696,16 +700,28 @@ public final class CtsNetUtils { * {@code onAvailable}. */ public static class TestNetworkCallback extends ConnectivityManager.NetworkCallback { - private final CountDownLatch mAvailableLatch = new CountDownLatch(1); + private final ConditionVariable mAvailableCv = new ConditionVariable(false); private final CountDownLatch mLostLatch = new CountDownLatch(1); private final CountDownLatch mUnavailableLatch = new CountDownLatch(1); public Network currentNetwork; public Network lastLostNetwork; + /** + * Wait for a network to be available. + * + * If onAvailable was previously called but was followed by onLost, this will wait for the + * next available network. + */ public Network waitForAvailable() throws InterruptedException { - return mAvailableLatch.await(CONNECTIVITY_CHANGE_TIMEOUT_SECS, TimeUnit.SECONDS) - ? currentNetwork : null; + final long timeoutMs = TimeUnit.SECONDS.toMillis(CONNECTIVITY_CHANGE_TIMEOUT_SECS); + while (mAvailableCv.block(timeoutMs)) { + final Network n = currentNetwork; + if (n != null) return n; + Log.w(TAG, "onAvailable called but network was lost before it could be returned." + + " Waiting for the next call to onAvailable."); + } + return null; } public Network waitForLost() throws InterruptedException { @@ -717,17 +733,17 @@ public final class CtsNetUtils { return mUnavailableLatch.await(2, TimeUnit.SECONDS); } - @Override public void onAvailable(Network network) { currentNetwork = network; - mAvailableLatch.countDown(); + mAvailableCv.open(); } @Override public void onLost(Network network) { lastLostNetwork = network; if (network.equals(currentNetwork)) { + mAvailableCv.close(); currentNetwork = null; } mLostLatch.countDown();