WifiScanningServiceTest.java revision 59298c7cfffdf856e32879ec967fe27c7e977a49
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi.scanner;
18
19import static com.android.server.wifi.ScanTestUtil.*;
20
21import static org.junit.Assert.*;
22import static org.mockito.Mockito.*;
23
24import android.content.BroadcastReceiver;
25import android.content.Context;
26import android.content.IntentFilter;
27import android.net.wifi.ScanResult;
28import android.net.wifi.WifiManager;
29import android.net.wifi.WifiScanner;
30import android.os.Bundle;
31import android.os.Handler;
32import android.os.Looper;
33import android.os.Message;
34import android.os.WorkSource;
35import android.test.suitebuilder.annotation.SmallTest;
36import android.util.Pair;
37
38import com.android.internal.app.IBatteryStats;
39import com.android.internal.util.Protocol;
40import com.android.server.wifi.BidirectionalAsyncChannel;
41import com.android.server.wifi.MockAlarmManager;
42import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
43import com.android.server.wifi.MockLooper;
44import com.android.server.wifi.ScanResults;
45import com.android.server.wifi.TestUtil;
46import com.android.server.wifi.WifiInjector;
47import com.android.server.wifi.WifiMetrics;
48import com.android.server.wifi.WifiMetricsProto;
49import com.android.server.wifi.WifiNative;
50
51import org.junit.After;
52import org.junit.Before;
53import org.junit.Test;
54import org.mockito.ArgumentCaptor;
55import org.mockito.InOrder;
56import org.mockito.Mock;
57import org.mockito.MockitoAnnotations;
58import org.mockito.internal.matchers.CapturingMatcher;
59
60import java.io.FileDescriptor;
61import java.io.PrintWriter;
62import java.io.StringWriter;
63import java.util.ArrayList;
64import java.util.Arrays;
65import java.util.Collections;
66import java.util.regex.Pattern;
67
68/**
69 * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}.
70 */
71@SmallTest
72public class WifiScanningServiceTest {
73    public static final String TAG = "WifiScanningServiceTest";
74
75    @Mock Context mContext;
76    MockAlarmManager mAlarmManager;
77    @Mock WifiScannerImpl mWifiScannerImpl;
78    @Mock WifiScannerImpl.WifiScannerImplFactory mWifiScannerImplFactory;
79    @Mock IBatteryStats mBatteryStats;
80    @Mock WifiInjector mWifiInjector;
81    WifiMetrics mWifiMetrics;
82    MockLooper mLooper;
83    WifiScanningServiceImpl mWifiScanningServiceImpl;
84
85
86    @Before
87    public void setUp() throws Exception {
88        MockitoAnnotations.initMocks(this);
89
90        mAlarmManager = new MockAlarmManager();
91        when(mContext.getSystemService(Context.ALARM_SERVICE))
92                .thenReturn(mAlarmManager.getAlarmManager());
93        mWifiMetrics = new WifiMetrics();
94
95        ChannelHelper channelHelper = new PresetKnownBandsChannelHelper(
96                new int[]{2400, 2450},
97                new int[]{5150, 5175},
98                new int[]{5600, 5650, 5660});
99
100        mLooper = new MockLooper();
101        when(mWifiScannerImplFactory.create(any(Context.class), any(Looper.class)))
102                .thenReturn(mWifiScannerImpl);
103        when(mWifiScannerImpl.getChannelHelper()).thenReturn(channelHelper);
104        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
105        mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(),
106                mWifiScannerImplFactory, mBatteryStats, mWifiInjector);
107    }
108
109    @After
110    public void cleanup() {
111        validateMockitoUsage();
112    }
113
114    /**
115     * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts
116     * this is initialized by calling startServiceAndLoadDriver
117     */
118    BroadcastReceiver mBroadcastReceiver;
119
120    private WifiScanner.ScanSettings generateValidScanSettings() {
121        return createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20,
122                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
123    }
124
125    private BidirectionalAsyncChannel connectChannel(Handler handler) {
126        BidirectionalAsyncChannel controlChannel = new BidirectionalAsyncChannel();
127        controlChannel.connect(mLooper.getLooper(), mWifiScanningServiceImpl.getMessenger(),
128                handler);
129        mLooper.dispatchAll();
130        controlChannel.assertConnected();
131        return controlChannel;
132    }
133
134    private Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) {
135        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
136        order.verify(handler).handleMessage(messageCaptor.capture());
137        return messageCaptor.getValue();
138    }
139
140    private Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler,
141            final int what) {
142        CapturingMatcher<Message> messageMatcher = new CapturingMatcher<Message>() {
143            public boolean matches(Object argument) {
144                Message message = (Message) argument;
145                return message.what == what;
146            }
147        };
148        order.verify(handler).handleMessage(argThat(messageMatcher));
149        return messageMatcher.getLastValue();
150    }
151
152    private void verifyScanResultsRecieved(InOrder order, Handler handler, int listenerId,
153            WifiScanner.ScanData... expected) {
154        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
155                WifiScanner.CMD_SCAN_RESULT);
156        assertScanResultsMessage(listenerId, expected, scanResultMessage);
157    }
158
159    private void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected,
160            Message scanResultMessage) {
161        assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what);
162        assertEquals("listenerId", listenerId, scanResultMessage.arg2);
163        assertScanDatasEquals(expected,
164                ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults());
165    }
166
167    private void verifySingleScanCompletedRecieved(InOrder order, Handler handler, int listenerId) {
168        Message completedMessage = verifyHandleMessageAndGetMessage(order, handler,
169                WifiScanner.CMD_SINGLE_SCAN_COMPLETED);
170        assertSingleScanCompletedMessage(listenerId, completedMessage);
171    }
172
173    private void assertSingleScanCompletedMessage(int listenerId, Message completedMessage) {
174        assertEquals("what", WifiScanner.CMD_SINGLE_SCAN_COMPLETED, completedMessage.what);
175        assertEquals("listenerId", listenerId, completedMessage.arg2);
176    }
177
178    private void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel,
179            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
180        Bundle scanParams = new Bundle();
181        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
182        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
183        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0,
184                        scanRequestId, scanParams));
185    }
186
187    private void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel,
188            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
189        Bundle scanParams = new Bundle();
190        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
191        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
192        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0,
193                        scanRequestId, scanParams));
194    }
195
196    private void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) {
197        Message response = verifyHandleMessageAndGetMessage(order, handler);
198        assertSuccessfulResponse(arg2, response);
199    }
200
201    private void assertSuccessfulResponse(int arg2, Message response) {
202        if (response.what == WifiScanner.CMD_OP_FAILED) {
203            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
204            fail("response indicates failure, reason=" + result.reason
205                    + ", description=" + result.description);
206        } else {
207            assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
208            assertEquals("response.arg2", arg2, response.arg2);
209        }
210    }
211
212    private void verifyFailedResponse(InOrder order, Handler handler, int arg2,
213            int expectedErrorReason, String expectedErrorDescription) {
214        Message response = verifyHandleMessageAndGetMessage(order, handler);
215        assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response);
216    }
217
218    private void assertFailedResponse(int arg2, int expectedErrorReason,
219            String expectedErrorDescription, Message response) {
220        if (response.what == WifiScanner.CMD_OP_SUCCEEDED) {
221            fail("response indicates success");
222        } else {
223            assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
224            assertEquals("response.arg2", arg2, response.arg2);
225            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
226            assertEquals("response.obj.reason",
227                    expectedErrorReason, result.reason);
228            assertEquals("response.obj.description",
229                    expectedErrorDescription, result.description);
230        }
231    }
232
233    private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order,
234            WifiNative.ScanSettings expected) {
235        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
236                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
237        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
238                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
239        order.verify(mWifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(),
240                scanEventHandlerCaptor.capture());
241        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
242        return scanEventHandlerCaptor.getValue();
243    }
244
245    private WifiNative.ScanEventHandler verifyStartBackgroundScan(InOrder order,
246            WifiNative.ScanSettings expected) {
247        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
248                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
249        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
250                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
251        order.verify(mWifiScannerImpl).startBatchedScan(scanSettingsCaptor.capture(),
252                scanEventHandlerCaptor.capture());
253        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
254        return scanEventHandlerCaptor.getValue();
255    }
256
257    private static final int MAX_AP_PER_SCAN = 16;
258    private void startServiceAndLoadDriver() {
259        mWifiScanningServiceImpl.startService();
260        when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
261                .thenAnswer(new AnswerWithArguments() {
262                        public boolean answer(WifiNative.ScanCapabilities capabilities) {
263                            capabilities.max_scan_cache_size = Integer.MAX_VALUE;
264                            capabilities.max_scan_buckets = 8;
265                            capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
266                            capabilities.max_rssi_sample_size = 8;
267                            capabilities.max_scan_reporting_threshold = 10;
268                            capabilities.max_hotlist_bssids = 0;
269                            capabilities.max_significant_wifi_change_aps = 0;
270                            return true;
271                        }
272                    });
273        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
274                ArgumentCaptor.forClass(BroadcastReceiver.class);
275        verify(mContext)
276                .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
277        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
278        TestUtil.sendWifiScanAvailable(broadcastReceiverCaptor.getValue(), mContext,
279                WifiManager.WIFI_STATE_ENABLED);
280        mLooper.dispatchAll();
281    }
282
283    private String dumpService() {
284        StringWriter stringWriter = new StringWriter();
285        mWifiScanningServiceImpl.dump(new FileDescriptor(), new PrintWriter(stringWriter),
286                new String[0]);
287        return stringWriter.toString();
288    }
289
290    private void assertDumpContainsRequestLog(String type, int id) {
291        String serviceDump = dumpService();
292        Pattern logLineRegex = Pattern.compile("^.+" + type + ": ClientInfo\\[uid=\\d+\\],Id=" +
293                id + ".*$", Pattern.MULTILINE);
294        assertTrue("dump did not contain log with type=" + type + ", id=" + id +
295                ": " + serviceDump + "\n",
296                logLineRegex.matcher(serviceDump).find());
297   }
298
299    private void assertDumpContainsCallbackLog(String callback, int id, String extra) {
300        String serviceDump = dumpService();
301        String extraPattern = extra == null ? "" : "," + extra;
302        Pattern logLineRegex = Pattern.compile("^.+" + callback + ": ClientInfo\\[uid=\\d+\\],Id=" +
303                id + extraPattern + "$", Pattern.MULTILINE);
304        assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id +
305                ", extra=" + extra + ": " + serviceDump + "\n",
306                logLineRegex.matcher(serviceDump).find());
307   }
308
309    @Test
310    public void construct() throws Exception {
311        verifyNoMoreInteractions(mWifiScannerImpl, mWifiScannerImpl,
312                mWifiScannerImplFactory, mBatteryStats);
313        dumpService(); // make sure this succeeds
314    }
315
316    @Test
317    public void startService() throws Exception {
318        mWifiScanningServiceImpl.startService();
319        verifyNoMoreInteractions(mWifiScannerImplFactory);
320
321        Handler handler = mock(Handler.class);
322        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
323        InOrder order = inOrder(handler);
324        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
325        mLooper.dispatchAll();
326        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
327    }
328
329    @Test
330    public void loadDriver() throws Exception {
331        startServiceAndLoadDriver();
332        verify(mWifiScannerImplFactory, times(1)).create(any(Context.class), any(Looper.class));
333
334        Handler handler = mock(Handler.class);
335        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
336        InOrder order = inOrder(handler);
337        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
338                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
339        sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null);
340        mLooper.dispatchAll();
341        verifySuccessfulResponse(order, handler, 192);
342        assertDumpContainsRequestLog("addBackgroundScanRequest", 192);
343    }
344
345    @Test
346    public void sendInvalidCommand() throws Exception {
347        startServiceAndLoadDriver();
348
349        Handler handler = mock(Handler.class);
350        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
351        InOrder order = inOrder(handler, mWifiScannerImpl);
352        controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
353        mLooper.dispatchAll();
354        verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
355                "Invalid request");
356    }
357
358    private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
359            WifiNative.ScanSettings nativeSettings, ScanResults results) {
360        int requestId = 12;
361        startServiceAndLoadDriver();
362
363        Handler handler = mock(Handler.class);
364        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
365        InOrder order = inOrder(handler, mWifiScannerImpl);
366
367        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
368                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
369
370        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
371
372        mLooper.dispatchAll();
373        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
374        verifySuccessfulResponse(order, handler, requestId);
375
376        when(mWifiScannerImpl.getLatestSingleScanResults())
377                .thenReturn(results.getScanData());
378        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
379
380        mLooper.dispatchAll();
381        verifyScanResultsRecieved(order, handler, requestId, results.getScanData());
382        verifySingleScanCompletedRecieved(order, handler, requestId);
383        verifyNoMoreInteractions(handler);
384        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
385        assertDumpContainsCallbackLog("singleScanResults", requestId,
386                "results=" + results.getRawScanResults().length);
387    }
388
389    /**
390     * Do a single scan for a band and verify that it is successful.
391     */
392    @Test
393    public void sendSingleScanBandRequest() throws Exception {
394        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
395                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
396        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
397                ScanResults.create(0, 2400, 5150, 5175));
398    }
399
400    /**
401     * Do a single scan for a list of channels and verify that it is successful.
402     */
403    @Test
404    public void sendSingleScanChannelsRequest() throws Exception {
405        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
406                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
407        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
408                ScanResults.create(0, 2400, 5150, 5175));
409    }
410
411    /**
412     * Do a single scan, which the hardware fails to start, and verify that a failure response is
413     * delivered.
414     */
415    @Test
416    public void sendSingleScanRequestWhichFailsToStart() throws Exception {
417        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
418                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
419        int requestId = 33;
420
421        startServiceAndLoadDriver();
422
423        Handler handler = mock(Handler.class);
424        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
425        InOrder order = inOrder(handler, mWifiScannerImpl);
426
427        // scan fails
428        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
429                        any(WifiNative.ScanEventHandler.class))).thenReturn(false);
430
431        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
432
433        mLooper.dispatchAll();
434        // Scan is successfully queue, but then fails to execute
435        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
436        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
437        assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
438        assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
439                "Failed to start single scan", messageCaptor.getAllValues().get(1));
440
441        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
442        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
443        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
444    }
445
446    /**
447     * Do a single scan, which successfully starts, but fails partway through and verify that a
448     * failure response is delivered.
449     */
450    @Test
451    public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
452        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
453                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
454        int requestId = 33;
455
456        startServiceAndLoadDriver();
457
458        Handler handler = mock(Handler.class);
459        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
460        InOrder order = inOrder(handler, mWifiScannerImpl);
461
462        // successful start
463        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
464                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
465
466        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
467
468        // Scan is successfully queue
469        mLooper.dispatchAll();
470        WifiNative.ScanEventHandler eventHandler =
471                verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
472        verifySuccessfulResponse(order, handler, requestId);
473
474        // but then fails to execute
475        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED);
476        mLooper.dispatchAll();
477        verifyFailedResponse(order, handler, requestId,
478                WifiScanner.REASON_UNSPECIFIED, "Scan failed");
479        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
480        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
481    }
482
483    // TODO Add more single scan tests
484    // * disable wifi while scanning
485    // * disable wifi while scanning with pending scan
486
487    /**
488     * Send a single scan request and then a second one after the first completes.
489     */
490    @Test
491    public void sendSingleScanRequestAfterPreviousCompletes() {
492        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
493                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
494        int requestId1 = 12;
495        ScanResults results1 = ScanResults.create(0, 2400);
496
497
498        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
499                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
500        int requestId2 = 13;
501        ScanResults results2 = ScanResults.create(0, 2450);
502
503
504        startServiceAndLoadDriver();
505
506        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
507                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
508
509        Handler handler = mock(Handler.class);
510        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
511        InOrder order = inOrder(handler, mWifiScannerImpl);
512
513        // Run scan 1
514        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
515
516        mLooper.dispatchAll();
517        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
518                computeSingleScanNativeSettings(requestSettings1));
519        verifySuccessfulResponse(order, handler, requestId1);
520
521        // dispatch scan 1 results
522        when(mWifiScannerImpl.getLatestSingleScanResults())
523                .thenReturn(results1.getScanData());
524        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
525
526        mLooper.dispatchAll();
527        verifyScanResultsRecieved(order, handler, requestId1, results1.getScanData());
528        verifySingleScanCompletedRecieved(order, handler, requestId1);
529
530        // Run scan 2
531        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
532
533        mLooper.dispatchAll();
534        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
535                computeSingleScanNativeSettings(requestSettings2));
536        verifySuccessfulResponse(order, handler, requestId2);
537
538        // dispatch scan 2 results
539        when(mWifiScannerImpl.getLatestSingleScanResults())
540                .thenReturn(results2.getScanData());
541        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
542
543        mLooper.dispatchAll();
544        verifyScanResultsRecieved(order, handler, requestId2, results2.getScanData());
545        verifySingleScanCompletedRecieved(order, handler, requestId2);
546    }
547
548    /**
549     * Send a single scan request and then a second one before the first completes.
550     * Verify that both are scheduled and succeed.
551     */
552    @Test
553    public void sendSingleScanRequestWhilePreviousScanRunning() {
554        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
555                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
556        int requestId1 = 12;
557        ScanResults results1 = ScanResults.create(0, 2400);
558
559        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
560                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
561        int requestId2 = 13;
562        ScanResults results2 = ScanResults.create(0, 2450);
563
564
565        startServiceAndLoadDriver();
566
567        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
568                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
569
570        Handler handler = mock(Handler.class);
571        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
572        InOrder handlerOrder = inOrder(handler);
573        InOrder nativeOrder = inOrder(mWifiScannerImpl);
574
575        // Run scan 1
576        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
577
578        mLooper.dispatchAll();
579        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
580                computeSingleScanNativeSettings(requestSettings1));
581        verifySuccessfulResponse(handlerOrder, handler, requestId1);
582
583        // Queue scan 2 (will not run because previous is in progress)
584        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
585        mLooper.dispatchAll();
586        verifySuccessfulResponse(handlerOrder, handler, requestId2);
587
588        // dispatch scan 1 results
589        when(mWifiScannerImpl.getLatestSingleScanResults())
590                .thenReturn(results1.getScanData());
591        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
592
593        mLooper.dispatchAll();
594        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
595        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
596
597        // now that the first scan completed we expect the second one to start
598        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
599                computeSingleScanNativeSettings(requestSettings2));
600
601        // dispatch scan 2 results
602        when(mWifiScannerImpl.getLatestSingleScanResults())
603                .thenReturn(results2.getScanData());
604        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
605
606        mLooper.dispatchAll();
607        verifyScanResultsRecieved(handlerOrder, handler, requestId2, results2.getScanData());
608        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId2);
609        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
610        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
611    }
612
613
614    /**
615     * Send a single scan request and then two more before the first completes.
616     * Verify that the first completes and the second two are merged.
617     */
618    @Test
619    public void sendMultipleSingleScanRequestWhilePreviousScanRunning() {
620        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
621                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
622        int requestId1 = 12;
623        ScanResults results1 = ScanResults.create(0, 2400);
624
625        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
626                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
627        int requestId2 = 13;
628        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
629
630        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
631                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
632        int requestId3 = 15;
633        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
634
635        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
636                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
637        ScanResults results2and3 = ScanResults.merge(results2, results3);
638
639
640        startServiceAndLoadDriver();
641
642        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
643                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
644
645        Handler handler = mock(Handler.class);
646        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
647        InOrder handlerOrder = inOrder(handler);
648        InOrder nativeOrder = inOrder(mWifiScannerImpl);
649
650        // Run scan 1
651        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
652
653        mLooper.dispatchAll();
654        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
655                computeSingleScanNativeSettings(requestSettings1));
656        verifySuccessfulResponse(handlerOrder, handler, requestId1);
657
658        // Queue scan 2 (will not run because previous is in progress)
659        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
660        mLooper.dispatchAll();
661        verifySuccessfulResponse(handlerOrder, handler, requestId2);
662
663        // Queue scan 3 (will not run because previous is in progress)
664        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, null);
665        mLooper.dispatchAll();
666        verifySuccessfulResponse(handlerOrder, handler, requestId3);
667
668        // dispatch scan 1 results
669        when(mWifiScannerImpl.getLatestSingleScanResults())
670                .thenReturn(results1.getScanData());
671        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
672
673        mLooper.dispatchAll();
674        verifyScanResultsRecieved(handlerOrder, handler, requestId1, results1.getScanData());
675        verifySingleScanCompletedRecieved(handlerOrder, handler, requestId1);
676
677        // now that the first scan completed we expect the second and third ones to start
678        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
679                nativeSettings2and3);
680
681        // dispatch scan 2 and 3 results
682        when(mWifiScannerImpl.getLatestSingleScanResults())
683                .thenReturn(results2and3.getScanData());
684        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
685
686        mLooper.dispatchAll();
687
688        // unfortunatally the order that these events are dispatched is dependant on the order which
689        // they are iterated through internally
690        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
691        handlerOrder.verify(handler, times(4)).handleMessage(messageCaptor.capture());
692        int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
693        assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId3,
694                firstListenerId == requestId2 || firstListenerId == requestId3);
695        if (firstListenerId == requestId2) {
696            assertScanResultsMessage(requestId2,
697                    new WifiScanner.ScanData[] {results2.getScanData()},
698                    messageCaptor.getAllValues().get(0));
699            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1));
700            assertScanResultsMessage(requestId3,
701                    new WifiScanner.ScanData[] {results3.getScanData()},
702                    messageCaptor.getAllValues().get(2));
703            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(3));
704        } else {
705            assertScanResultsMessage(requestId3,
706                    new WifiScanner.ScanData[] {results3.getScanData()},
707                    messageCaptor.getAllValues().get(0));
708            assertSingleScanCompletedMessage(requestId3, messageCaptor.getAllValues().get(1));
709            assertScanResultsMessage(requestId2,
710                    new WifiScanner.ScanData[] {results2.getScanData()},
711                    messageCaptor.getAllValues().get(2));
712            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3));
713        }
714        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
715        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
716
717        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
718        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
719        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
720        assertDumpContainsCallbackLog("singleScanResults", requestId1,
721                "results=" + results1.getRawScanResults().length);
722        assertDumpContainsCallbackLog("singleScanResults", requestId2,
723                "results=" + results2.getRawScanResults().length);
724        assertDumpContainsCallbackLog("singleScanResults", requestId3,
725                "results=" + results3.getRawScanResults().length);
726    }
727
728    private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
729            WifiNative.ScanSettings nativeSettings) {
730        startServiceAndLoadDriver();
731
732        Handler handler = mock(Handler.class);
733        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
734        InOrder order = inOrder(handler, mWifiScannerImpl);
735
736        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
737                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
738
739        sendBackgroundScanRequest(controlChannel, 12, requestSettings, null);
740        mLooper.dispatchAll();
741        verifyStartBackgroundScan(order, nativeSettings);
742        verifySuccessfulResponse(order, handler, 12);
743        verifyNoMoreInteractions(handler);
744        assertDumpContainsRequestLog("addBackgroundScanRequest", 12);
745    }
746
747    /**
748     * Do a background scan for a band and verify that it is successful.
749     */
750    @Test
751    public void sendBackgroundScanBandRequest() throws Exception {
752        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 20000,
753                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
754        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
755                .withBasePeriod(20000)
756                .withMaxApPerScan(MAX_AP_PER_SCAN)
757                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
758                .addBucketWithBand(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
759                        WifiScanner.WIFI_BAND_BOTH)
760                .build();
761        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
762        assertEquals(mWifiMetrics.getBackgroundScanCount(), 1);
763    }
764
765    /**
766     * Do a background scan for a list of channels and verify that it is successful.
767     */
768    @Test
769    public void sendBackgroundScanChannelsRequest() throws Exception {
770        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 20000,
771                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
772        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
773                .withBasePeriod(20000)
774                .withMaxApPerScan(MAX_AP_PER_SCAN)
775                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
776                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
777                .build();
778        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
779    }
780
781    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno()
782            throws Exception {
783        WifiScanner.ScanSettings requestSettings = createRequest(
784                channelsToSpec(0, 2400, 5150, 5175), 20000, 0, 20,
785                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
786        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
787                .withBasePeriod(20000)
788                .withMaxApPerScan(MAX_AP_PER_SCAN)
789                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
790                .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
791                        0, 2400, 5150, 5175)
792                .build();
793        return Pair.create(requestSettings, nativeSettings);
794    }
795
796    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForSwPno()
797            throws Exception {
798        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> settingsPair =
799                createScanSettingsForHwPno();
800
801        WifiScanner.ScanSettings requestSettings = settingsPair.first;
802        WifiNative.ScanSettings nativeSettings = settingsPair.second;
803        // reportEvents field is overridden for SW PNO
804        for (int i = 0; i < nativeSettings.buckets.length; i++) {
805            nativeSettings.buckets[i].report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
806                    | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
807        }
808        return Pair.create(requestSettings, nativeSettings);
809    }
810
811    private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings(
812            ScanResults results)
813            throws Exception {
814        WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings();
815        requestPnoSettings.networkList =
816                new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length];
817        int i = 0;
818        for (ScanResult scanResult : results.getRawScanResults()) {
819            requestPnoSettings.networkList[i++] =
820                    new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID);
821        }
822
823        WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings();
824        nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi;
825        nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi;
826        nativePnoSettings.initialScoreMax = requestPnoSettings.initialScoreMax;
827        nativePnoSettings.currentConnectionBonus = requestPnoSettings.currentConnectionBonus;
828        nativePnoSettings.sameNetworkBonus = requestPnoSettings.sameNetworkBonus;
829        nativePnoSettings.secureBonus = requestPnoSettings.secureBonus;
830        nativePnoSettings.band5GHzBonus = requestPnoSettings.band5GHzBonus;
831        nativePnoSettings.isConnected = requestPnoSettings.isConnected;
832        nativePnoSettings.networkList =
833                new WifiNative.PnoNetwork[requestPnoSettings.networkList.length];
834        for (i = 0; i < requestPnoSettings.networkList.length; i++) {
835            nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork();
836            nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid;
837            nativePnoSettings.networkList[i].networkId =
838                    requestPnoSettings.networkList[i].networkId;
839            nativePnoSettings.networkList[i].priority = requestPnoSettings.networkList[i].priority;
840            nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags;
841            nativePnoSettings.networkList[i].auth_bit_field =
842                    requestPnoSettings.networkList[i].authBitField;
843        }
844        return Pair.create(requestPnoSettings, nativePnoSettings);
845    }
846
847    private ScanResults createScanResultsForPno() {
848        return ScanResults.create(0, 2400, 5150, 5175);
849    }
850
851    private ScanResults createScanResultsForPnoWithNoIE() {
852        return ScanResults.createWithNoIE(0, 2400, 5150, 5175);
853    }
854
855    private WifiNative.PnoEventHandler verifyHwPno(InOrder order,
856            WifiNative.PnoSettings expected) {
857        ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor =
858                ArgumentCaptor.forClass(WifiNative.PnoSettings.class);
859        ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor =
860                ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class);
861        order.verify(mWifiScannerImpl).setHwPnoList(pnoSettingsCaptor.capture(),
862                pnoEventHandlerCaptor.capture());
863        assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue());
864        return pnoEventHandlerCaptor.getValue();
865    }
866
867    private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel,
868            int scanRequestId, WifiScanner.ScanSettings scanSettings,
869            WifiScanner.PnoSettings pnoSettings) {
870        Bundle pnoParams = new Bundle();
871        scanSettings.isPnoScan = true;
872        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
873        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
874        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0,
875                scanRequestId, pnoParams));
876    }
877
878    private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected,
879            Message networkFoundMessage) {
880        assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what);
881        assertEquals("listenerId", listenerId, networkFoundMessage.arg2);
882        assertScanResultsEquals(expected,
883                ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults());
884    }
885
886    private void verifyPnoNetworkFoundRecieved(InOrder order, Handler handler, int listenerId,
887            ScanResult[] expected) {
888        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
889                WifiScanner.CMD_PNO_NETWORK_FOUND);
890        assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage);
891    }
892
893    private void expectSuccessfulBackgroundScan(InOrder order,
894            WifiNative.ScanSettings nativeSettings, ScanResults results) {
895        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
896                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
897        mLooper.dispatchAll();
898        WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings);
899        WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
900        scanDatas[0] = results.getScanData();
901        for (ScanResult fullScanResult : results.getRawScanResults()) {
902            eventHandler.onFullScanResult(fullScanResult, 0);
903        }
904        when(mWifiScannerImpl.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas);
905        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
906        mLooper.dispatchAll();
907    }
908
909    private void expectHwPnoScanWithNoBackgroundScan(InOrder order, Handler handler, int requestId,
910            WifiNative.PnoSettings nativeSettings, ScanResults results) {
911        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
912        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(false);
913
914        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
915                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
916        mLooper.dispatchAll();
917        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativeSettings);
918        verifySuccessfulResponse(order, handler, requestId);
919        eventHandler.onPnoNetworkFound(results.getRawScanResults());
920        mLooper.dispatchAll();
921    }
922
923    private void expectHwPnoScanWithBackgroundScan(InOrder order, Handler handler, int requestId,
924            WifiNative.ScanSettings nativeScanSettings,
925            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
926        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
927        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
928
929        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
930                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
931        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
932                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
933        mLooper.dispatchAll();
934        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativePnoSettings);
935        verifySuccessfulResponse(order, handler, requestId);
936        verifyStartBackgroundScan(order, nativeScanSettings);
937        eventHandler.onPnoNetworkFound(results.getRawScanResults());
938        mLooper.dispatchAll();
939    }
940
941    private void expectHwPnoScanWithBackgroundScanWithNoIE(InOrder order, Handler handler,
942            int requestId, WifiNative.ScanSettings nativeBackgroundScanSettings,
943            WifiNative.ScanSettings nativeSingleScanSettings,
944            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
945        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
946                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
947
948        expectHwPnoScanWithBackgroundScan(order, handler, requestId, nativeBackgroundScanSettings,
949                nativePnoSettings, results);
950        WifiNative.ScanEventHandler eventHandler =
951                verifyStartSingleScan(order, nativeSingleScanSettings);
952        when(mWifiScannerImpl.getLatestSingleScanResults()).thenReturn(results.getScanData());
953        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
954        mLooper.dispatchAll();
955    }
956    private void expectSwPnoScan(InOrder order, WifiNative.ScanSettings nativeScanSettings,
957            ScanResults results) {
958        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(false);
959        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
960
961        expectSuccessfulBackgroundScan(order, nativeScanSettings, results);
962    }
963
964    /**
965     * Tests Supplicant PNO scan when the PNO scan results contain IE info. This ensures that the
966     * PNO scan results are plumbed back to the client as a PNO network found event.
967     */
968    @Test
969    public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception {
970        startServiceAndLoadDriver();
971        Handler handler = mock(Handler.class);
972        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
973        InOrder order = inOrder(handler, mWifiScannerImpl);
974        int requestId = 12;
975
976        ScanResults scanResults = createScanResultsForPno();
977        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
978                createScanSettingsForHwPno();
979        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
980                createPnoSettings(scanResults);
981
982        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
983        expectHwPnoScanWithNoBackgroundScan(order, handler, requestId, pnoSettings.second,
984                scanResults);
985        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
986    }
987
988    /**
989     * Tests Hal ePNO scan when the PNO scan results contain IE info. This ensures that the
990     * PNO scan results are plumbed back to the client as a PNO network found event.
991     */
992    @Test
993    public void testSuccessfulHwPnoScanWithBackgroundScan() throws Exception {
994        startServiceAndLoadDriver();
995        Handler handler = mock(Handler.class);
996        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
997        InOrder order = inOrder(handler, mWifiScannerImpl);
998        int requestId = 12;
999
1000        ScanResults scanResults = createScanResultsForPno();
1001        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1002                createScanSettingsForHwPno();
1003        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1004                createPnoSettings(scanResults);
1005
1006        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1007        expectHwPnoScanWithBackgroundScan(order, handler, requestId, scanSettings.second,
1008                pnoSettings.second, scanResults);
1009        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1010    }
1011
1012    /**
1013     * Tests Hal ePNO scan when the PNO scan results don't contain IE info. This ensures that the
1014     * single scan results are plumbed back to the client as a PNO network found event.
1015     */
1016    @Test
1017    public void testSuccessfulHwPnoScanWithBackgroundScanWithNoIE() throws Exception {
1018        startServiceAndLoadDriver();
1019        Handler handler = mock(Handler.class);
1020        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1021        InOrder order = inOrder(handler, mWifiScannerImpl);
1022        int requestId = 12;
1023
1024        ScanResults scanResults = createScanResultsForPnoWithNoIE();
1025        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1026                createScanSettingsForHwPno();
1027        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1028                createPnoSettings(scanResults);
1029
1030        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1031        expectHwPnoScanWithBackgroundScanWithNoIE(order, handler, requestId, scanSettings.second,
1032                computeSingleScanNativeSettings(scanSettings.first), pnoSettings.second,
1033                scanResults);
1034
1035        ArrayList<ScanResult> sortScanList =
1036                new ArrayList<ScanResult>(Arrays.asList(scanResults.getRawScanResults()));
1037        Collections.sort(sortScanList, WifiScannerImpl.SCAN_RESULT_SORT_COMPARATOR);
1038        verifyPnoNetworkFoundRecieved(order, handler, requestId,
1039                sortScanList.toArray(new ScanResult[sortScanList.size()]));
1040    }
1041
1042    /**
1043     * Tests SW PNO scan. This ensures that the background scan results are plumbed back to the
1044     * client as a PNO network found event.
1045     */
1046    @Test
1047    public void testSuccessfulSwPnoScan() throws Exception {
1048        startServiceAndLoadDriver();
1049        Handler handler = mock(Handler.class);
1050        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1051        InOrder order = inOrder(handler, mWifiScannerImpl);
1052        int requestId = 12;
1053
1054        ScanResults scanResults = createScanResultsForPno();
1055        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1056                createScanSettingsForSwPno();
1057        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1058                createPnoSettings(scanResults);
1059
1060        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1061        expectSwPnoScan(order, scanSettings.second, scanResults);
1062        verifyPnoNetworkFoundRecieved(order, handler, requestId, scanResults.getRawScanResults());
1063    }
1064}
1065