From 72024817b555c872ef21cfbcca3b33851a406d29 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 26 Apr 2018 13:33:00 -0700 Subject: WifiScanningServiceImpl: Ignore duplicate scan available Receiving duplicate SCAN_AVAILABLE broadcast currently puts WifiScanner in a weird state. This is what happens: a) WifiBackgroundScanStateMachine is already in StartedState. b) WifiBackgroundScanStateMachine receives another CMD_DRIVER_LOADED message. c) CMD_DRIVER_LOADED is handled in the DefaultState which creates a new mScannerImpl instance. d) Handling of CMD_DRIVER_LOADED also asks the WifiBackgroundScanStateMachine to transition to StartedState. e) This causes WifiBackgroundScanStateMachine to transition out of StartedState and back into StartedState. (This transition to the same state should probably have been ignored by the base StateMachine class) f) In the above transition, exit() of StartedState invokes mScannerImpl.cleanup(). So, we end up with a new mScannerImpl instance on which we invoked mScannerImpl.cleanup() and hence no more scans work. Note: We may still need to debug why WSM is sending out back to back scan available notification. But, we should fix the handling in WifiScanner regardless. Bug: 78549365 Test: Unit tests Test: Ran WifiManager ACTS tests locally Test: Toggled wifi a bunch of times and ensured scanning still works. Change-Id: I2cf606ecf2d2d261d3354be30135c4ec93f278ff --- .../wifi/scanner/WifiScanningServiceTest.java | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) (limited to 'tests') diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java index 08eca85f7..85f1bede0 100644 --- a/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java +++ b/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java @@ -497,6 +497,23 @@ public class WifiScanningServiceTest { assertDumpContainsRequestLog("addBackgroundScanRequest", 192); } + /** + * Verifies that duplicate SCAN_AVAILABLE broadcast with |WIFI_STATE_ENABLED| is ignored. + */ + @Test + public void duplicateScanAvailableBroadcastIsIgnored() throws RemoteException { + startServiceAndLoadDriver(); + + // Send scan available again. + TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext, + WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + + // Ensure we didn't create scanner instance twice. + verify(mWifiScannerImplFactory, times(1)) + .create(any(), any(), any()); + } + @Test public void disconnectClientAfterStartingWifi() throws Exception { mWifiScanningServiceImpl.startService(); @@ -2293,4 +2310,117 @@ public class WifiScanningServiceTest { messenger.send(message); verify(mFrameworkFacade, never()).makeWifiAsyncChannel(anyString()); } + + /** + * Verifies that background scan works after duplicate SCAN_AVAILABLE broadcast with + * |WIFI_STATE_ENABLED|. + */ + @Test + public void backgroundScanAfterDuplicateScanAvailableBroadcast() throws RemoteException { + startServiceAndLoadDriver(); + + // Send scan available again. + TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext, + WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + + // Ensure we didn't create scanner instance twice. + verify(mWifiScannerImplFactory, times(1)) + .create(any(), any(), any()); + + Handler handler = mock(Handler.class); + BidirectionalAsyncChannel controlChannel = connectChannel(handler); + InOrder order = inOrder(handler); + when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class), + any(WifiNative.ScanEventHandler.class))).thenReturn(true); + sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null); + mLooper.dispatchAll(); + verifySuccessfulResponse(order, handler, 192); + assertDumpContainsRequestLog("addBackgroundScanRequest", 192); + } + + /** + * Verifies that single scan works after duplicate SCAN_AVAILABLE broadcast with + * |WIFI_STATE_ENABLED|. + */ + @Test + public void singleScanScanAfterDuplicateScanAvailableBroadcast() throws RemoteException { + startServiceAndLoadDriver(); + + // Send scan available again. + TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext, + WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + + // Ensure we didn't create scanner instance twice. + verify(mWifiScannerImplFactory, times(1)) + .create(any(), any(), any()); + + Handler handler = mock(Handler.class); + BidirectionalAsyncChannel controlChannel = connectChannel(handler); + InOrder order = inOrder(handler, mWifiScannerImpl); + + int requestId = 12; + WorkSource workSource = new WorkSource(2292); + WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400, 5150, 5175), + 0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN); + ScanResults results = ScanResults.create(0, true, 2400, 5150, 5175); + + when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class), + any(WifiNative.ScanEventHandler.class))).thenReturn(true); + + sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource); + + mLooper.dispatchAll(); + WifiNative.ScanEventHandler eventHandler = + verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings)); + verifySuccessfulResponse(order, handler, requestId); + verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource)); + + when(mWifiScannerImpl.getLatestSingleScanResults()) + .thenReturn(results.getRawScanData()); + eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); + + mLooper.dispatchAll(); + verifyScanResultsReceived(order, handler, requestId, results.getScanData()); + verifySingleScanCompletedReceived(order, handler, requestId); + verifyNoMoreInteractions(handler); + verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource)); + assertDumpContainsRequestLog("addSingleScanRequest", requestId); + assertDumpContainsCallbackLog("singleScanResults", requestId, + "results=" + results.getScanData().getResults().length); + } + + /** + * Verifies that pno scan works after duplicate SCAN_AVAILABLE broadcast with + * |WIFI_STATE_ENABLED|. + */ + @Test + public void hwPnoScanScanAfterDuplicateScanAvailableBroadcast() throws Exception { + startServiceAndLoadDriver(); + + // Send scan available again. + TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext, + WifiManager.WIFI_STATE_ENABLED); + mLooper.dispatchAll(); + + // Ensure we didn't create scanner instance twice. + verify(mWifiScannerImplFactory, times(1)) + .create(any(), any(), any()); + + Handler handler = mock(Handler.class); + BidirectionalAsyncChannel controlChannel = connectChannel(handler); + InOrder order = inOrder(handler, mWifiScannerImpl); + int requestId = 12; + + ScanResults scanResults = createScanResultsForPno(); + Pair scanSettings = + createScanSettingsForHwPno(); + Pair pnoSettings = + createPnoSettings(scanResults); + + sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first); + expectHwPnoScan(order, handler, requestId, pnoSettings.second, scanResults); + verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults()); + } } -- cgit v1.2.3