Fail scan request if no channels are available

This fails scan request if no available channels could
be scanned for this request.
With this fix we can avoid the freezing of WifiScanner in
aformentioned case.

Bug: 67015387
Test: compile, unit test, integration test
Change-Id: I68654ce8d53104484c1559d8b0525585ab50b9e5
diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
index 12a0bde..ed25e0f 100644
--- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
+++ b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java
@@ -422,11 +422,22 @@
                 mPendingSingleScanEventHandler = null;
             }
 
-            if ((newScanSettings.backgroundScanActive || newScanSettings.singleScanActive)
-                    && !allFreqs.isEmpty()) {
-                pauseHwPnoScan();
-                Set<Integer> freqs = allFreqs.getScanFreqs();
-                boolean success = mWifiNative.scan(freqs, hiddenNetworkSSIDSet);
+            if (newScanSettings.backgroundScanActive || newScanSettings.singleScanActive) {
+                boolean success = false;
+                Set<Integer> freqs;
+                if (!allFreqs.isEmpty()) {
+                    pauseHwPnoScan();
+                    freqs = allFreqs.getScanFreqs();
+                    success = mWifiNative.scan(freqs, hiddenNetworkSSIDSet);
+                    if (!success) {
+                        Log.e(TAG, "Failed to start scan, freqs=" + freqs);
+                    }
+                } else {
+                    // There is a scan request but no available channels could be scanned for.
+                    // We regard it as a scan failure in this case.
+                    Log.e(TAG, "Failed to start scan because there is "
+                            + "no available channel to scan for");
+                }
                 if (success) {
                     // TODO handle scan timeout
                     if (DBG) {
@@ -439,7 +450,6 @@
                             mClock.getElapsedSinceBootMillis() + SCAN_TIMEOUT_MS,
                             TIMEOUT_ALARM_TAG, mScanTimeoutListener, mEventHandler);
                 } else {
-                    Log.e(TAG, "Failed to start scan, freqs=" + freqs);
                     // indicate scan failure async
                     mEventHandler.post(new Runnable() {
                             public void run() {
diff --git a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java b/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java
index ed7c582..d337cf1 100644
--- a/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/scanner/WificondScannerTest.java
@@ -32,6 +32,7 @@
 import com.android.server.wifi.ScanResults;
 import com.android.server.wifi.WifiMonitor;
 import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -56,6 +57,39 @@
                 mLooper.getLooper(), mClock);
     }
 
+    /**
+     * Test that WificondScannerImpl will not issue a scan and report scan failure
+     * when there is no channel to scan for.
+     */
+    @Test
+    public void singleScanNotIssuedIfNoAvailableChannels() {
+        // Use mocked ChannelHelper and ChannelCollection to simulate the scenario
+        // that no channel is available for this request.
+        ChannelHelper channelHelper = mock(ChannelHelper.class);
+        ChannelCollection channelCollection = mock(ChannelCollection.class);
+        when(channelHelper.createChannelCollection()).thenReturn(channelCollection);
+        when(channelCollection.isEmpty()).thenReturn(true);
+
+        mScanner = new WificondScannerImpl(mContext, mWifiNative, mWifiMonitor,
+                channelHelper, mLooper.getLooper(), mClock);
+
+        WifiNative.ScanSettings settings = new NativeScanSettingsBuilder()
+                .withBasePeriod(10000) // ms
+                .withMaxApPerScan(10)
+                .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
+                        WifiScanner.WIFI_BAND_5_GHZ)
+                .build();
+        WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
+        mScanner.startSingleScan(settings, eventHandler);
+
+        mLooper.dispatchAll();
+
+        // No scan is issued to WifiNative.
+        verify(mWifiNative, never()).scan(any(), any(Set.class));
+        // A scan failed event must be reported.
+        verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED);
+    }
+
     @Test
     public void backgroundScanSuccessSingleBucket() {
         WifiNative.ScanSettings settings = new NativeScanSettingsBuilder()