[go: nahoru, domu]

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