[go: nahoru, domu]

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