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