From a7bd5947b6d6d5e58ce6b69ba01536a24b5b34a8 Mon Sep 17 00:00:00 2001 From: Rebecca Silberstein Date: Wed, 24 May 2017 08:54:28 -0700 Subject: [PATCH] WifiManagerTest: add LOHS tests Add new CTS tests for the LocalOnlyHotspot feature. This CL also creates a reusable method for confirming that wifi is enabled via the setWifiEnabled call. This should reduce flake in automated test runs by setting local variables before wifi is enabled instead of after the call. This change removes a race condition on confirming if wifi is enabled. Bug: 31466854 Test: ran new CTS tests Test: no new failures with 'run cts-dev --module CtsNetTestCases -t ran n android.net.wifi.cts.WifiManagerTest' Change-Id: Id119170fea742402dda10d83014d27b8dbc98e92 --- .../android/net/wifi/cts/WifiManagerTest.java | 175 +++++++++++++++++- 1 file changed, 169 insertions(+), 6 deletions(-) diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java index 33c184a317..cbf3e93e1d 100644 --- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java +++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java @@ -59,6 +59,7 @@ public class WifiManagerTest extends AndroidTestCase { private static MySync mMySync; private List mScanResults = null; private NetworkInfo mNetworkInfo; + private Object mLOHSLock = new Object(); // Please refer to WifiManager private static final int MIN_RSSI = -100; @@ -173,14 +174,25 @@ public class WifiManagerTest extends AndroidTestCase { private void setWifiEnabled(boolean enable) throws Exception { synchronized (mMySync) { - assertTrue(mWifiManager.setWifiEnabled(enable)); if (mWifiManager.isWifiEnabled() != enable) { + // the new state is different, we expect it to change mMySync.expectedState = STATE_WIFI_CHANGING; - long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; - int expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); - while (System.currentTimeMillis() < timeout - && mMySync.expectedState != expectedState) - mMySync.wait(WAIT_MSEC); + } else { + mMySync.expectedState = (enable ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); + } + // now trigger the change + assertTrue(mWifiManager.setWifiEnabled(enable)); + waitForExpectedWifiState(enable); + } + } + + private void waitForExpectedWifiState(boolean enabled) throws InterruptedException { + synchronized (mMySync) { + long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; + int expected = (enabled ? STATE_WIFI_ENABLED : STATE_WIFI_DISABLED); + while (System.currentTimeMillis() < timeout + && mMySync.expectedState != expected) { + mMySync.wait(WAIT_MSEC); } } } @@ -517,6 +529,13 @@ public class WifiManagerTest extends AndroidTestCase { } assertTrue(mWifiManager.isWifiEnabled()); + // give the test a chance to autoconnect + Thread.sleep(DURATION); + if (mNetworkInfo.getState() != NetworkInfo.State.CONNECTED) { + // this test requires a connectable network be configured + fail("This test requires a wifi network connection."); + } + // This will generate a distinct stack trace if the initial connection fails. connectWifi(); @@ -686,4 +705,148 @@ public class WifiManagerTest extends AndroidTestCase { // Passpoint build config |config_wifi_hotspot2_enabled| is disabled, so noop. } } + + public class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback { + Object hotspotLock; + WifiManager.LocalOnlyHotspotReservation reservation = null; + boolean onStartedCalled = false; + boolean onStoppedCalled = false; + boolean onFailedCalled = false; + int failureReason = -1; + + TestLocalOnlyHotspotCallback(Object lock) { + hotspotLock = lock; + } + + @Override + public void onStarted(WifiManager.LocalOnlyHotspotReservation r) { + synchronized (hotspotLock) { + reservation = r; + onStartedCalled = true; + hotspotLock.notify(); + } + } + + @Override + public void onStopped() { + synchronized (hotspotLock) { + onStoppedCalled = true; + hotspotLock.notify(); + } + } + + @Override + public void onFailed(int reason) { + synchronized (hotspotLock) { + onFailedCalled = true; + failureReason = reason; + hotspotLock.notify(); + } + } + } + + private TestLocalOnlyHotspotCallback startLocalOnlyHotspot() { + // Location mode must be enabled for this test + if (!isLocationEnabled()) { + fail("Please enable location for this test"); + } + + TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock); + synchronized (mLOHSLock) { + try { + mWifiManager.startLocalOnlyHotspot(callback, null); + // now wait for callback + mLOHSLock.wait(DURATION); + } catch (InterruptedException e) { + } + // check if we got the callback + assertTrue(callback.onStartedCalled); + assertNotNull(callback.reservation.getWifiConfiguration()); + assertFalse(callback.onFailedCalled); + assertFalse(callback.onStoppedCalled); + } + return callback; + } + + private void stopLocalOnlyHotspot(TestLocalOnlyHotspotCallback callback, boolean wifiEnabled) { + synchronized (mMySync) { + // we are expecting a new state + mMySync.expectedState = STATE_WIFI_CHANGING; + + // now shut down LocalOnlyHotspot + callback.reservation.close(); + + try { + waitForExpectedWifiState(wifiEnabled); + } catch (InterruptedException e) {} + } + } + + /** + * Verify that calls to startLocalOnlyHotspot succeed with proper permissions. + * + * Note: Location mode must be enabled for this test. + */ + public void testStartLocalOnlyHotspotSuccess() { + boolean wifiEnabled = mWifiManager.isWifiEnabled(); + + TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); + + // at this point, wifi should be off + assertFalse(mWifiManager.isWifiEnabled()); + + stopLocalOnlyHotspot(callback, wifiEnabled); + assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); + } + + /** + * Verify calls to setWifiEnabled from a non-settings app while softap mode is active do not + * exit softap mode. + * + * This test uses the LocalOnlyHotspot API to enter softap mode. This should also be true when + * tethering is started. + * Note: Location mode must be enabled for this test. + */ + public void testSetWifiEnabledByAppDoesNotStopHotspot() { + boolean wifiEnabled = mWifiManager.isWifiEnabled(); + + TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); + // at this point, wifi should be off + assertFalse(mWifiManager.isWifiEnabled()); + + // now we should fail to turn on wifi + assertFalse(mWifiManager.setWifiEnabled(true)); + + stopLocalOnlyHotspot(callback, wifiEnabled); + assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); + } + + /** + * Verify that applications can only have one registered LocalOnlyHotspot request at a time. + * + * Note: Location mode must be enabled for this test. + */ + public void testStartLocalOnlyHotspotSingleRequestByApps() { + boolean caughtException = false; + + boolean wifiEnabled = mWifiManager.isWifiEnabled(); + + TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); + + // at this point, wifi should be off + assertFalse(mWifiManager.isWifiEnabled()); + + // now make a second request - this should fail. + TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock); + try { + mWifiManager.startLocalOnlyHotspot(callback2, null); + } catch (IllegalStateException e) { + Log.d(TAG, "Caught the IllegalStateException we expected: called startLOHS twice"); + caughtException = true; + } + assertTrue(caughtException); + + stopLocalOnlyHotspot(callback, wifiEnabled); + assertEquals(wifiEnabled, mWifiManager.isWifiEnabled()); + } }