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.*;
20import static com.android.server.wifi.scanner.WifiScanningServiceImpl.WifiSingleScanStateMachine
21        .CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS;
22
23import static org.junit.Assert.*;
24import static org.mockito.Mockito.*;
25
26import android.app.test.MockAnswerUtil.AnswerWithArguments;
27import android.app.test.TestAlarmManager;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.net.wifi.ScanResult;
33import android.net.wifi.WifiManager;
34import android.net.wifi.WifiScanner;
35import android.os.Binder;
36import android.os.Bundle;
37import android.os.Handler;
38import android.os.Message;
39import android.os.RemoteException;
40import android.os.UserHandle;
41import android.os.WorkSource;
42import android.os.test.TestLooper;
43import android.test.suitebuilder.annotation.SmallTest;
44import android.util.Pair;
45
46import com.android.internal.app.IBatteryStats;
47import com.android.internal.util.AsyncChannel;
48import com.android.internal.util.Protocol;
49import com.android.internal.util.test.BidirectionalAsyncChannel;
50import com.android.server.wifi.Clock;
51import com.android.server.wifi.FakeWifiLog;
52import com.android.server.wifi.FrameworkFacade;
53import com.android.server.wifi.ScanResults;
54import com.android.server.wifi.TestUtil;
55import com.android.server.wifi.WifiInjector;
56import com.android.server.wifi.WifiMetrics;
57import com.android.server.wifi.WifiNative;
58import com.android.server.wifi.nano.WifiMetricsProto;
59import com.android.server.wifi.util.WifiAsyncChannel;
60
61import org.junit.After;
62import org.junit.Before;
63import org.junit.Test;
64import org.mockito.ArgumentCaptor;
65import org.mockito.InOrder;
66import org.mockito.Mock;
67import org.mockito.MockitoAnnotations;
68import org.mockito.Spy;
69import org.mockito.compat.CapturingMatcher;
70
71import java.io.FileDescriptor;
72import java.io.PrintWriter;
73import java.io.StringWriter;
74import java.util.ArrayList;
75import java.util.Arrays;
76import java.util.Collections;
77import java.util.List;
78import java.util.regex.Pattern;
79
80/**
81 * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}.
82 */
83@SmallTest
84public class WifiScanningServiceTest {
85    public static final String TAG = "WifiScanningServiceTest";
86
87    private static final int TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES = 8;
88
89    @Mock Context mContext;
90    TestAlarmManager mAlarmManager;
91    @Mock WifiScannerImpl mWifiScannerImpl;
92    @Mock WifiScannerImpl.WifiScannerImplFactory mWifiScannerImplFactory;
93    @Mock IBatteryStats mBatteryStats;
94    @Mock WifiInjector mWifiInjector;
95    @Mock FrameworkFacade mFrameworkFacade;
96    @Mock Clock mClock;
97    @Spy FakeWifiLog mLog;
98    WifiMetrics mWifiMetrics;
99    TestLooper mLooper;
100    WifiScanningServiceImpl mWifiScanningServiceImpl;
101
102
103    @Before
104    public void setUp() throws Exception {
105        MockitoAnnotations.initMocks(this);
106
107        mAlarmManager = new TestAlarmManager();
108        when(mContext.getSystemService(Context.ALARM_SERVICE))
109                .thenReturn(mAlarmManager.getAlarmManager());
110
111        ChannelHelper channelHelper = new PresetKnownBandsChannelHelper(
112                new int[]{2400, 2450},
113                new int[]{5150, 5175},
114                new int[]{5600, 5650, 5660});
115
116        mLooper = new TestLooper();
117        mWifiMetrics = new WifiMetrics(mClock, mLooper.getLooper());
118        when(mWifiScannerImplFactory
119                .create(any(), any(), any()))
120                .thenReturn(mWifiScannerImpl);
121        when(mWifiScannerImpl.getChannelHelper()).thenReturn(channelHelper);
122        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
123        when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
124        WifiAsyncChannel mWifiAsyncChannel = new WifiAsyncChannel("ScanningServiceTest");
125        mWifiAsyncChannel.setWifiLog(mLog);
126        when(mFrameworkFacade.makeWifiAsyncChannel(anyString())).thenReturn(mWifiAsyncChannel);
127        when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade);
128        when(mWifiInjector.getClock()).thenReturn(mClock);
129        mWifiScanningServiceImpl = new WifiScanningServiceImpl(mContext, mLooper.getLooper(),
130                mWifiScannerImplFactory, mBatteryStats, mWifiInjector);
131    }
132
133    @After
134    public void cleanup() {
135        validateMockitoUsage();
136    }
137
138    /**
139     * Internal BroadcastReceiver that WifiScanningServiceImpl uses to listen for broadcasts
140     * this is initialized by calling startServiceAndLoadDriver
141     */
142    BroadcastReceiver mBroadcastReceiver;
143
144    private WifiScanner.ScanSettings generateValidScanSettings() {
145        return createRequest(WifiScanner.WIFI_BAND_BOTH, 30000, 0, 20,
146                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
147    }
148
149    private BidirectionalAsyncChannel connectChannel(Handler handler) {
150        BidirectionalAsyncChannel controlChannel = new BidirectionalAsyncChannel();
151        controlChannel.connect(mLooper.getLooper(), mWifiScanningServiceImpl.getMessenger(),
152                handler);
153        mLooper.dispatchAll();
154        controlChannel.assertConnected();
155        return controlChannel;
156    }
157
158    private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler) {
159        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
160        order.verify(handler).handleMessage(messageCaptor.capture());
161        return messageCaptor.getValue();
162    }
163
164    private static Message verifyHandleMessageAndGetMessage(InOrder order, Handler handler,
165            final int what) {
166        CapturingMatcher<Message> messageMatcher = new CapturingMatcher<Message>() {
167            public boolean matchesObject(Object argument) {
168                Message message = (Message) argument;
169                return message.what == what;
170            }
171        };
172        order.verify(handler).handleMessage(argThat(messageMatcher));
173        return messageMatcher.getLastValue();
174    }
175
176    private static void verifyScanResultsReceived(InOrder order, Handler handler, int listenerId,
177            WifiScanner.ScanData... expected) {
178        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
179                WifiScanner.CMD_SCAN_RESULT);
180        assertScanResultsMessage(listenerId, expected, scanResultMessage);
181    }
182
183    private static void assertScanResultsMessage(int listenerId, WifiScanner.ScanData[] expected,
184            Message scanResultMessage) {
185        assertEquals("what", WifiScanner.CMD_SCAN_RESULT, scanResultMessage.what);
186        assertEquals("listenerId", listenerId, scanResultMessage.arg2);
187        assertScanDatasEquals(expected,
188                ((WifiScanner.ParcelableScanData) scanResultMessage.obj).getResults());
189    }
190
191    private static void verifySingleScanCompletedReceived(InOrder order, Handler handler,
192            int listenerId) {
193        Message completedMessage = verifyHandleMessageAndGetMessage(order, handler,
194                WifiScanner.CMD_SINGLE_SCAN_COMPLETED);
195        assertSingleScanCompletedMessage(listenerId, completedMessage);
196    }
197
198    private static void assertSingleScanCompletedMessage(int listenerId, Message completedMessage) {
199        assertEquals("what", WifiScanner.CMD_SINGLE_SCAN_COMPLETED, completedMessage.what);
200        assertEquals("listenerId", listenerId, completedMessage.arg2);
201    }
202
203    private static void sendBackgroundScanRequest(BidirectionalAsyncChannel controlChannel,
204            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
205        Bundle scanParams = new Bundle();
206        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
207        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
208        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_BACKGROUND_SCAN, 0,
209                        scanRequestId, scanParams));
210    }
211
212    private static void sendSingleScanRequest(BidirectionalAsyncChannel controlChannel,
213            int scanRequestId, WifiScanner.ScanSettings settings, WorkSource workSource) {
214        Bundle scanParams = new Bundle();
215        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
216        scanParams.putParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
217        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_SINGLE_SCAN, 0,
218                        scanRequestId, scanParams));
219    }
220
221    private static void registerScanListener(BidirectionalAsyncChannel controlChannel,
222            int listenerRequestId) {
223        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_REGISTER_SCAN_LISTENER, 0,
224                        listenerRequestId, null));
225    }
226
227    private static void deregisterScanListener(BidirectionalAsyncChannel controlChannel,
228            int listenerRequestId) {
229        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_DEREGISTER_SCAN_LISTENER, 0,
230                        listenerRequestId, null));
231    }
232
233    private static void verifySuccessfulResponse(InOrder order, Handler handler, int arg2) {
234        Message response = verifyHandleMessageAndGetMessage(order, handler);
235        assertSuccessfulResponse(arg2, response);
236    }
237
238    private static void assertSuccessfulResponse(int arg2, Message response) {
239        if (response.what == WifiScanner.CMD_OP_FAILED) {
240            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
241            fail("response indicates failure, reason=" + result.reason
242                    + ", description=" + result.description);
243        } else {
244            assertEquals("response.what", WifiScanner.CMD_OP_SUCCEEDED, response.what);
245            assertEquals("response.arg2", arg2, response.arg2);
246        }
247    }
248
249    /**
250     * If multiple results are expected for a single hardware scan then the order that they are
251     * dispatched is dependant on the order which they are iterated through internally. This
252     * function validates that the order is either one way or the other. A scan listener can
253     * optionally be provided as well and will be checked after the after the single scan requests.
254     */
255    private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler,
256            int requestId1, ScanResults results1, int requestId2, ScanResults results2,
257            int listenerRequestId, ScanResults listenerResults) {
258        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
259        handlerOrder.verify(handler, times(listenerResults == null ? 4 : 5))
260                .handleMessage(messageCaptor.capture());
261        int firstListenerId = messageCaptor.getAllValues().get(0).arg2;
262        assertTrue(firstListenerId + " was neither " + requestId2 + " nor " + requestId1,
263                firstListenerId == requestId2 || firstListenerId == requestId1);
264        if (firstListenerId == requestId2) {
265            assertScanResultsMessage(requestId2,
266                    new WifiScanner.ScanData[] {results2.getScanData()},
267                    messageCaptor.getAllValues().get(0));
268            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(1));
269            assertScanResultsMessage(requestId1,
270                    new WifiScanner.ScanData[] {results1.getScanData()},
271                    messageCaptor.getAllValues().get(2));
272            assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(3));
273            if (listenerResults != null) {
274                assertScanResultsMessage(listenerRequestId,
275                        new WifiScanner.ScanData[] {listenerResults.getScanData()},
276                        messageCaptor.getAllValues().get(4));
277            }
278        } else {
279            assertScanResultsMessage(requestId1,
280                    new WifiScanner.ScanData[] {results1.getScanData()},
281                    messageCaptor.getAllValues().get(0));
282            assertSingleScanCompletedMessage(requestId1, messageCaptor.getAllValues().get(1));
283            assertScanResultsMessage(requestId2,
284                    new WifiScanner.ScanData[] {results2.getScanData()},
285                    messageCaptor.getAllValues().get(2));
286            assertSingleScanCompletedMessage(requestId2, messageCaptor.getAllValues().get(3));
287            if (listenerResults != null) {
288                assertScanResultsMessage(listenerRequestId,
289                        new WifiScanner.ScanData[] {listenerResults.getScanData()},
290                        messageCaptor.getAllValues().get(4));
291            }
292        }
293    }
294
295    private static void verifyMultipleSingleScanResults(InOrder handlerOrder, Handler handler,
296            int requestId1, ScanResults results1, int requestId2, ScanResults results2) {
297        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2,
298                results2, -1, null);
299    }
300
301    private static void verifyFailedResponse(InOrder order, Handler handler, int arg2,
302            int expectedErrorReason, String expectedErrorDescription) {
303        Message response = verifyHandleMessageAndGetMessage(order, handler);
304        assertFailedResponse(arg2, expectedErrorReason, expectedErrorDescription, response);
305    }
306
307    private static void assertFailedResponse(int arg2, int expectedErrorReason,
308            String expectedErrorDescription, Message response) {
309        if (response.what == WifiScanner.CMD_OP_SUCCEEDED) {
310            fail("response indicates success");
311        } else {
312            assertEquals("response.what", WifiScanner.CMD_OP_FAILED, response.what);
313            assertEquals("response.arg2", arg2, response.arg2);
314            WifiScanner.OperationResult result = (WifiScanner.OperationResult) response.obj;
315            assertEquals("response.obj.reason",
316                    expectedErrorReason, result.reason);
317            assertEquals("response.obj.description",
318                    expectedErrorDescription, result.description);
319        }
320    }
321
322    private WifiNative.ScanEventHandler verifyStartSingleScan(InOrder order,
323            WifiNative.ScanSettings expected) {
324        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
325                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
326        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
327                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
328        order.verify(mWifiScannerImpl).startSingleScan(scanSettingsCaptor.capture(),
329                scanEventHandlerCaptor.capture());
330        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
331        return scanEventHandlerCaptor.getValue();
332    }
333
334    private WifiNative.ScanEventHandler verifyStartBackgroundScan(InOrder order,
335            WifiNative.ScanSettings expected) {
336        ArgumentCaptor<WifiNative.ScanSettings> scanSettingsCaptor =
337                ArgumentCaptor.forClass(WifiNative.ScanSettings.class);
338        ArgumentCaptor<WifiNative.ScanEventHandler> scanEventHandlerCaptor =
339                ArgumentCaptor.forClass(WifiNative.ScanEventHandler.class);
340        order.verify(mWifiScannerImpl).startBatchedScan(scanSettingsCaptor.capture(),
341                scanEventHandlerCaptor.capture());
342        assertNativeScanSettingsEquals(expected, scanSettingsCaptor.getValue());
343        return scanEventHandlerCaptor.getValue();
344    }
345
346    private static final int MAX_AP_PER_SCAN = 16;
347    private void startServiceAndLoadDriver() {
348        mWifiScanningServiceImpl.startService();
349        setupAndLoadDriver(TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES);
350    }
351
352    private void setupAndLoadDriver(int max_scan_buckets) {
353        when(mWifiScannerImpl.getScanCapabilities(any(WifiNative.ScanCapabilities.class)))
354                .thenAnswer(new AnswerWithArguments() {
355                        public boolean answer(WifiNative.ScanCapabilities capabilities) {
356                            capabilities.max_scan_cache_size = Integer.MAX_VALUE;
357                            capabilities.max_scan_buckets = max_scan_buckets;
358                            capabilities.max_ap_cache_per_scan = MAX_AP_PER_SCAN;
359                            capabilities.max_rssi_sample_size = 8;
360                            capabilities.max_scan_reporting_threshold = 10;
361                            return true;
362                        }
363                    });
364        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
365                ArgumentCaptor.forClass(BroadcastReceiver.class);
366        verify(mContext)
367                .registerReceiver(broadcastReceiverCaptor.capture(), any(IntentFilter.class));
368        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
369        TestUtil.sendWifiScanAvailable(broadcastReceiverCaptor.getValue(), mContext,
370                WifiManager.WIFI_STATE_ENABLED);
371        mLooper.dispatchAll();
372    }
373
374    private String dumpService() {
375        StringWriter stringWriter = new StringWriter();
376        mWifiScanningServiceImpl.dump(new FileDescriptor(), new PrintWriter(stringWriter),
377                new String[0]);
378        return stringWriter.toString();
379    }
380
381    private void assertDumpContainsRequestLog(String type, int id) {
382        String serviceDump = dumpService();
383        Pattern logLineRegex = Pattern.compile("^.+" + type
384                + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id
385                + ".*$", Pattern.MULTILINE);
386        assertTrue("dump did not contain log with type=" + type + ", id=" + id +
387                ": " + serviceDump + "\n",
388                logLineRegex.matcher(serviceDump).find());
389    }
390
391    private void assertDumpContainsCallbackLog(String callback, int id, String extra) {
392        String serviceDump = dumpService();
393        String extraPattern = extra == null ? "" : "," + extra;
394        Pattern logLineRegex = Pattern.compile("^.+" + callback
395                + ": ClientInfo\\[uid=\\d+,android\\.os\\.Messenger@[a-f0-9]+\\],Id=" + id
396                + extraPattern + "$", Pattern.MULTILINE);
397        assertTrue("dump did not contain callback log with callback=" + callback + ", id=" + id +
398                ", extra=" + extra + ": " + serviceDump + "\n",
399                logLineRegex.matcher(serviceDump).find());
400    }
401
402    @Test
403    public void construct() throws Exception {
404        verifyNoMoreInteractions(mWifiScannerImpl, mWifiScannerImpl,
405                mWifiScannerImplFactory, mBatteryStats);
406        dumpService(); // make sure this succeeds
407    }
408
409    @Test
410    public void startService() throws Exception {
411        mWifiScanningServiceImpl.startService();
412        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
413        verifyNoMoreInteractions(mWifiScannerImplFactory);
414
415        Handler handler = mock(Handler.class);
416        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
417        InOrder order = inOrder(handler);
418        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
419        mLooper.dispatchAll();
420        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
421    }
422
423    @Test
424    public void disconnectClientBeforeWifiEnabled() throws Exception {
425        mWifiScanningServiceImpl.startService();
426        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
427        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
428        mLooper.dispatchAll();
429
430        controlChannel.disconnect();
431        mLooper.dispatchAll();
432    }
433
434    @Test
435    public void loadDriver() throws Exception {
436        startServiceAndLoadDriver();
437        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
438        verify(mWifiScannerImplFactory, times(1))
439                .create(any(), any(), any());
440
441        Handler handler = mock(Handler.class);
442        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
443        InOrder order = inOrder(handler);
444        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
445                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
446        sendBackgroundScanRequest(controlChannel, 192, generateValidScanSettings(), null);
447        mLooper.dispatchAll();
448        verifySuccessfulResponse(order, handler, 192);
449        assertDumpContainsRequestLog("addBackgroundScanRequest", 192);
450    }
451
452    @Test
453    public void disconnectClientAfterStartingWifi() throws Exception {
454        mWifiScanningServiceImpl.startService();
455        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
456        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
457        mLooper.dispatchAll();
458
459        setupAndLoadDriver(TEST_MAX_SCAN_BUCKETS_IN_CAPABILITIES);
460
461        controlChannel.disconnect();
462        mLooper.dispatchAll();
463    }
464
465    @Test
466    public void connectAndDisconnectClientAfterStartingWifi() throws Exception {
467        startServiceAndLoadDriver();
468        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
469
470        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
471        mLooper.dispatchAll();
472        controlChannel.disconnect();
473        mLooper.dispatchAll();
474    }
475
476    @Test
477    public void sendInvalidCommand() throws Exception {
478        startServiceAndLoadDriver();
479        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
480
481        Handler handler = mock(Handler.class);
482        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
483        InOrder order = inOrder(handler, mWifiScannerImpl);
484        controlChannel.sendMessage(Message.obtain(null, Protocol.BASE_WIFI_MANAGER));
485        mLooper.dispatchAll();
486        verifyFailedResponse(order, handler, 0, WifiScanner.REASON_INVALID_REQUEST,
487                "Invalid request");
488    }
489
490    @Test
491    public void rejectBackgroundScanRequestWhenHalReturnsInvalidCapabilities() throws Exception {
492        mWifiScanningServiceImpl.startService();
493        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
494
495        setupAndLoadDriver(0);
496
497        Handler handler = mock(Handler.class);
498        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
499        InOrder order = inOrder(handler);
500        sendBackgroundScanRequest(controlChannel, 122, generateValidScanSettings(), null);
501        mLooper.dispatchAll();
502        verifyFailedResponse(order, handler, 122, WifiScanner.REASON_UNSPECIFIED, "not available");
503    }
504
505    private void doSuccessfulSingleScan(WifiScanner.ScanSettings requestSettings,
506            WifiNative.ScanSettings nativeSettings, ScanResults results) throws RemoteException {
507        int requestId = 12;
508        WorkSource workSource = new WorkSource(2292);
509        startServiceAndLoadDriver();
510        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
511
512        Handler handler = mock(Handler.class);
513        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
514        InOrder order = inOrder(handler, mWifiScannerImpl);
515
516        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
517                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
518
519        sendSingleScanRequest(controlChannel, requestId, requestSettings, workSource);
520
521        mLooper.dispatchAll();
522        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
523        verifySuccessfulResponse(order, handler, requestId);
524        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
525
526        when(mWifiScannerImpl.getLatestSingleScanResults())
527                .thenReturn(results.getRawScanData());
528        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
529
530        mLooper.dispatchAll();
531        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
532        verifySingleScanCompletedReceived(order, handler, requestId);
533        if (results.getScanData().isAllChannelsScanned()) {
534            verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
535        } else {
536            verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
537        }
538        verifyNoMoreInteractions(handler);
539        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
540        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
541        assertDumpContainsCallbackLog("singleScanResults", requestId,
542                "results=" + results.getScanData().getResults().length);
543    }
544
545    /**
546     * Do a single scan for a band and verify that it is successful.
547     */
548    @Test
549    public void sendSingleScanBandRequest() throws Exception {
550        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
551                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
552        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
553                ScanResults.create(0, true, 2400, 5150, 5175));
554    }
555
556    /**
557     * Do a single scan for a list of channels and verify that it is successful.
558     */
559    @Test
560    public void sendSingleScanChannelsRequest() throws Exception {
561        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400, 5150, 5175),
562                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
563        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
564                ScanResults.create(0, 2400, 5150, 5175));
565    }
566
567    /**
568     * Do a single scan for a list of all channels and verify that it is successful.
569     */
570    @Test
571    public void sendSingleScanAllChannelsRequest() throws Exception {
572        WifiScanner.ScanSettings requestSettings = createRequest(
573                channelsToSpec(2400, 2450, 5150, 5175, 5600, 5650, 5660),
574                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
575        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
576                ScanResults.create(0, true, 2400, 5150, 5175));
577    }
578
579    /**
580     * Do a single scan with no results and verify that it is successful.
581     */
582    @Test
583    public void sendSingleScanRequestWithNoResults() throws Exception {
584        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
585                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
586        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
587                ScanResults.create(0, new int[0]));
588    }
589
590    /**
591     * Do a single scan with results that do not match the requested scan and verify that it is
592     * still successful (and returns no results).
593     */
594    @Test
595    public void sendSingleScanRequestWithBadRawResults() throws Exception {
596        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0,
597                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
598        // Create a set of scan results that has results not matching the request settings, but is
599        // limited to zero results for the expected results.
600        ScanResults results = ScanResults.createOverflowing(0, 0,
601                ScanResults.generateNativeResults(0, 5150, 5171));
602        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
603                results);
604    }
605
606    /**
607     * Do a single scan, which the hardware fails to start, and verify that a failure response is
608     * delivered.
609     */
610    @Test
611    public void sendSingleScanRequestWhichFailsToStart() throws Exception {
612        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
613                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
614        int requestId = 33;
615
616        startServiceAndLoadDriver();
617        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
618
619        Handler handler = mock(Handler.class);
620        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
621        InOrder order = inOrder(handler, mWifiScannerImpl);
622
623        // scan fails
624        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
625                        any(WifiNative.ScanEventHandler.class))).thenReturn(false);
626
627        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
628
629        mLooper.dispatchAll();
630        // Scan is successfully queue, but then fails to execute
631        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
632        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
633        assertSuccessfulResponse(requestId, messageCaptor.getAllValues().get(0));
634        assertFailedResponse(requestId, WifiScanner.REASON_UNSPECIFIED,
635                "Failed to start single scan", messageCaptor.getAllValues().get(1));
636        verifyNoMoreInteractions(mBatteryStats);
637
638        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
639        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
640        assertDumpContainsRequestLog("addSingleScanRequest", requestId);
641    }
642
643    /**
644     * Do a single scan, which successfully starts, but fails partway through and verify that a
645     * failure response is delivered.
646     */
647    @Test
648    public void sendSingleScanRequestWhichFailsAfterStart() throws Exception {
649        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
650                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
651        int requestId = 33;
652        WorkSource workSource = new WorkSource(Binder.getCallingUid()); // don't explicitly set
653
654        startServiceAndLoadDriver();
655        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
656
657        Handler handler = mock(Handler.class);
658        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
659        InOrder order = inOrder(handler, mWifiScannerImpl);
660
661        // successful start
662        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
663                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
664
665        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
666
667        // Scan is successfully queue
668        mLooper.dispatchAll();
669        WifiNative.ScanEventHandler eventHandler =
670                verifyStartSingleScan(order, computeSingleScanNativeSettings(requestSettings));
671        verifySuccessfulResponse(order, handler, requestId);
672        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource));
673
674        // but then fails to execute
675        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_FAILED);
676        mLooper.dispatchAll();
677        verifyFailedResponse(order, handler, requestId,
678                WifiScanner.REASON_UNSPECIFIED, "Scan failed");
679        assertDumpContainsCallbackLog("singleScanFailed", requestId,
680                "reason=" + WifiScanner.REASON_UNSPECIFIED + ", Scan failed");
681        assertEquals(mWifiMetrics.getOneshotScanCount(), 1);
682        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_UNKNOWN), 1);
683        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource));
684        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
685    }
686
687    /**
688     * Send a single scan request and then disable Wi-Fi before it completes
689     */
690    @Test
691    public void sendSingleScanRequestThenDisableWifi() {
692        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(2400), 0,
693                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
694        int requestId = 2293;
695
696        startServiceAndLoadDriver();
697        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
698
699        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
700                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
701
702        Handler handler = mock(Handler.class);
703        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
704        InOrder order = inOrder(handler, mWifiScannerImpl);
705
706        // Run scan 1
707        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
708        mLooper.dispatchAll();
709        verifySuccessfulResponse(order, handler, requestId);
710
711        // disable wifi
712        TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext,
713                WifiManager.WIFI_STATE_DISABLED);
714
715        // validate failed response
716        mLooper.dispatchAll();
717        verifyFailedResponse(order, handler, requestId, WifiScanner.REASON_UNSPECIFIED,
718                "Scan was interrupted");
719        verifyNoMoreInteractions(handler);
720    }
721
722    /**
723     * Send a single scan request, schedule a second pending scan and disable Wi-Fi before the first
724     * scan completes.
725     */
726    @Test
727    public void sendSingleScanAndPendingScanAndListenerThenDisableWifi() {
728        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
729                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
730        int requestId1 = 2293;
731
732        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450), 0,
733                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
734        int requestId2 = 2294;
735
736        int listenerRequestId = 2295;
737
738        startServiceAndLoadDriver();
739        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
740
741        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
742                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
743
744        Handler handler = mock(Handler.class);
745        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
746        InOrder order = inOrder(handler, mWifiScannerImpl);
747
748        // Request scan 1
749        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
750        mLooper.dispatchAll();
751        verifySuccessfulResponse(order, handler, requestId1);
752
753        // Request scan 2
754        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
755        mLooper.dispatchAll();
756        verifySuccessfulResponse(order, handler, requestId2);
757
758        // Setup scan listener
759        registerScanListener(controlChannel, listenerRequestId);
760        mLooper.dispatchAll();
761        verifySuccessfulResponse(order, handler, listenerRequestId);
762
763        // disable wifi
764        TestUtil.sendWifiScanAvailable(mBroadcastReceiver, mContext,
765                WifiManager.WIFI_STATE_DISABLED);
766
767        // validate failed response
768        mLooper.dispatchAll();
769        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
770        order.verify(handler, times(2)).handleMessage(messageCaptor.capture());
771        assertFailedResponse(requestId1, WifiScanner.REASON_UNSPECIFIED,
772                "Scan was interrupted", messageCaptor.getAllValues().get(0));
773        assertFailedResponse(requestId2, WifiScanner.REASON_UNSPECIFIED,
774                "Scan was interrupted", messageCaptor.getAllValues().get(1));
775        // No additional callbacks for scan listener
776        verifyNoMoreInteractions(handler);
777    }
778
779    /**
780     * Send a single scan request and then a second one after the first completes.
781     */
782    @Test
783    public void sendSingleScanRequestAfterPreviousCompletes() {
784        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
785                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
786        int requestId1 = 12;
787        ScanResults results1 = ScanResults.create(0, true, 2400);
788
789
790        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
791                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
792        int requestId2 = 13;
793        ScanResults results2 = ScanResults.create(0, true, 2450);
794
795
796        startServiceAndLoadDriver();
797        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
798
799        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
800                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
801
802        Handler handler = mock(Handler.class);
803        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
804        InOrder order = inOrder(handler, mWifiScannerImpl, mContext);
805
806        // Run scan 1
807        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
808
809        mLooper.dispatchAll();
810        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
811                computeSingleScanNativeSettings(requestSettings1));
812        verifySuccessfulResponse(order, handler, requestId1);
813
814        // dispatch scan 1 results
815        when(mWifiScannerImpl.getLatestSingleScanResults())
816                .thenReturn(results1.getScanData());
817        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
818
819        mLooper.dispatchAll();
820        // Note: The order of the following verification calls looks out of order if you compare to
821        // the source code of WifiScanningServiceImpl WifiSingleScanStateMachine.reportScanResults.
822        // This is due to the fact that verifyScanResultsReceived and
823        // verifySingleScanCompletedReceived require an additional call to handle the message that
824        // is created in reportScanResults.  This handling is done in the two verify*Received calls
825        // that is run AFTER the reportScanResults method in WifiScanningServiceImpl completes.
826        order.verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
827        verifyScanResultsReceived(order, handler, requestId1, results1.getScanData());
828        verifySingleScanCompletedReceived(order, handler, requestId1);
829
830        // Run scan 2
831        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
832
833        mLooper.dispatchAll();
834        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
835                computeSingleScanNativeSettings(requestSettings2));
836        verifySuccessfulResponse(order, handler, requestId2);
837
838        // dispatch scan 2 results
839        when(mWifiScannerImpl.getLatestSingleScanResults())
840                .thenReturn(results2.getScanData());
841        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
842
843        mLooper.dispatchAll();
844        order.verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
845        verifyScanResultsReceived(order, handler, requestId2, results2.getScanData());
846        verifySingleScanCompletedReceived(order, handler, requestId2);
847    }
848
849    /**
850     * Send a single scan request and then a second one not satisfied by the first before the first
851     * completes. Verify that both are scheduled and succeed.
852     */
853    @Test
854    public void sendSingleScanRequestWhilePreviousScanRunning() {
855        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
856                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
857        int requestId1 = 12;
858        ScanResults results1 = ScanResults.create(0, true, 2400);
859
860        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
861                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
862        int requestId2 = 13;
863        ScanResults results2 = ScanResults.create(0, true, 2450);
864
865
866        startServiceAndLoadDriver();
867        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
868
869        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
870                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
871
872        Handler handler = mock(Handler.class);
873        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
874        InOrder handlerOrder = inOrder(handler);
875        InOrder nativeOrder = inOrder(mWifiScannerImpl);
876
877        // Run scan 1
878        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
879
880        mLooper.dispatchAll();
881        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
882                computeSingleScanNativeSettings(requestSettings1));
883        verifySuccessfulResponse(handlerOrder, handler, requestId1);
884
885        // Queue scan 2 (will not run because previous is in progress)
886        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
887        mLooper.dispatchAll();
888        verifySuccessfulResponse(handlerOrder, handler, requestId2);
889
890        // dispatch scan 1 results
891        when(mWifiScannerImpl.getLatestSingleScanResults())
892                .thenReturn(results1.getScanData());
893        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
894
895        mLooper.dispatchAll();
896        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
897        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
898        verify(mContext).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
899
900        // now that the first scan completed we expect the second one to start
901        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
902                computeSingleScanNativeSettings(requestSettings2));
903
904        // dispatch scan 2 results
905        when(mWifiScannerImpl.getLatestSingleScanResults())
906                .thenReturn(results2.getScanData());
907        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
908
909        mLooper.dispatchAll();
910        verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData());
911        verifySingleScanCompletedReceived(handlerOrder, handler, requestId2);
912        verify(mContext, times(2)).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
913        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
914        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
915    }
916
917
918    /**
919     * Send a single scan request and then two more before the first completes. Neither are
920     * satisfied by the first scan. Verify that the first completes and the second two are merged.
921     */
922    @Test
923    public void sendMultipleSingleScanRequestWhilePreviousScanRunning() throws RemoteException {
924        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
925                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
926        int requestId1 = 12;
927        WorkSource workSource1 = new WorkSource(1121);
928        ScanResults results1 = ScanResults.create(0, false, 2400);
929
930        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
931                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
932        int requestId2 = 13;
933        WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set
934        ScanResults results2 = ScanResults.create(0, false, 2450, 5175, 2450);
935
936        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
937                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
938        int requestId3 = 15;
939        WorkSource workSource3 = new WorkSource(2292);
940        ScanResults results3 = ScanResults.create(0, false, 5150, 5150, 5150, 5150);
941
942        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
943                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
944        ScanResults results2and3 = ScanResults.merge(results2, results3);
945        WorkSource workSource2and3 = new WorkSource();
946        workSource2and3.add(workSource2);
947        workSource2and3.add(workSource3);
948
949
950        startServiceAndLoadDriver();
951        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
952
953        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
954                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
955
956        Handler handler = mock(Handler.class);
957        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
958        InOrder handlerOrder = inOrder(handler);
959        InOrder nativeOrder = inOrder(mWifiScannerImpl);
960
961        // Run scan 1
962        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1);
963
964        mLooper.dispatchAll();
965        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
966                computeSingleScanNativeSettings(requestSettings1));
967        verifySuccessfulResponse(handlerOrder, handler, requestId1);
968        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource1));
969
970
971        // Queue scan 2 (will not run because previous is in progress)
972        // uses uid of calling process
973        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
974        mLooper.dispatchAll();
975        verifySuccessfulResponse(handlerOrder, handler, requestId2);
976
977        // Queue scan 3 (will not run because previous is in progress)
978        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3);
979        mLooper.dispatchAll();
980        verifySuccessfulResponse(handlerOrder, handler, requestId3);
981
982        // dispatch scan 1 results
983        when(mWifiScannerImpl.getLatestSingleScanResults())
984                .thenReturn(results1.getScanData());
985        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
986
987        mLooper.dispatchAll();
988        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
989        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
990        verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
991        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource1));
992        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource2and3));
993
994        // now that the first scan completed we expect the second and third ones to start
995        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
996                nativeSettings2and3);
997
998        // dispatch scan 2 and 3 results
999        when(mWifiScannerImpl.getLatestSingleScanResults())
1000                .thenReturn(results2and3.getScanData());
1001        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1002
1003        mLooper.dispatchAll();
1004
1005        verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3,
1006                results3);
1007        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
1008        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
1009
1010        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource2and3));
1011
1012        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
1013        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
1014        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
1015        assertDumpContainsCallbackLog("singleScanResults", requestId1,
1016                "results=" + results1.getRawScanResults().length);
1017        assertDumpContainsCallbackLog("singleScanResults", requestId2,
1018                "results=" + results2.getRawScanResults().length);
1019        assertDumpContainsCallbackLog("singleScanResults", requestId3,
1020                "results=" + results3.getRawScanResults().length);
1021    }
1022
1023
1024    /**
1025     * Send a single scan request and then a second one satisfied by the first before the first
1026     * completes. Verify that only one scan is scheduled.
1027     */
1028    @Test
1029    public void sendSingleScanRequestWhilePreviousScanRunningAndMergeIntoFirstScan() {
1030        // Split by frequency to make it easier to determine which results each request is expecting
1031        ScanResults results24GHz = ScanResults.create(0, 2400, 2400, 2400, 2450);
1032        ScanResults results5GHz = ScanResults.create(0, 5150, 5150, 5175);
1033        ScanResults resultsBoth = ScanResults.merge(results24GHz, results5GHz);
1034
1035        WifiScanner.ScanSettings requestSettings1 = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1036                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1037        int requestId1 = 12;
1038        ScanResults results1 = resultsBoth;
1039
1040        WifiScanner.ScanSettings requestSettings2 = createRequest(WifiScanner.WIFI_BAND_24_GHZ, 0,
1041                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1042        int requestId2 = 13;
1043        ScanResults results2 = results24GHz;
1044
1045
1046        startServiceAndLoadDriver();
1047        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1048
1049        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1050                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1051
1052        Handler handler = mock(Handler.class);
1053        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1054        InOrder handlerOrder = inOrder(handler);
1055        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1056
1057        // Run scan 1
1058        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
1059
1060        mLooper.dispatchAll();
1061        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(nativeOrder,
1062                computeSingleScanNativeSettings(requestSettings1));
1063        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1064
1065        // Queue scan 2 (will be folded into ongoing scan)
1066        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1067        mLooper.dispatchAll();
1068        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1069
1070        // dispatch scan 1 results
1071        when(mWifiScannerImpl.getLatestSingleScanResults())
1072                .thenReturn(resultsBoth.getScanData());
1073        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1074
1075        mLooper.dispatchAll();
1076        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId2,
1077                results2);
1078
1079        assertEquals(mWifiMetrics.getOneshotScanCount(), 2);
1080        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 2);
1081    }
1082
1083    /**
1084     * Send a single scan request and then two more before the first completes, one of which is
1085     * satisfied by the first scan. Verify that the first two complete together the second scan is
1086     * just for the other scan.
1087     */
1088    @Test
1089    public void sendMultipleSingleScanRequestWhilePreviousScanRunningAndMergeOneIntoFirstScan()
1090          throws RemoteException {
1091        // Split by frequency to make it easier to determine which results each request is expecting
1092        ScanResults results2400 = ScanResults.create(0, 2400, 2400, 2400);
1093        ScanResults results2450 = ScanResults.create(0, 2450);
1094        ScanResults results1and3 = ScanResults.merge(results2400, results2450);
1095
1096        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400, 2450), 0,
1097                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1098        int requestId1 = 12;
1099        WorkSource workSource1 = new WorkSource(1121);
1100        ScanResults results1 = results1and3;
1101
1102        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
1103                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1104        int requestId2 = 13;
1105        WorkSource workSource2 = new WorkSource(Binder.getCallingUid()); // don't explicitly set
1106        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
1107
1108        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(2400), 0,
1109                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1110        int requestId3 = 15;
1111        WorkSource workSource3 = new WorkSource(2292);
1112        ScanResults results3 = results2400;
1113
1114        startServiceAndLoadDriver();
1115        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1116
1117        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1118                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1119
1120        Handler handler = mock(Handler.class);
1121        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1122        InOrder handlerOrder = inOrder(handler);
1123        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1124
1125        // Run scan 1
1126        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, workSource1);
1127
1128        mLooper.dispatchAll();
1129        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
1130                computeSingleScanNativeSettings(requestSettings1));
1131        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1132        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource1));
1133
1134
1135        // Queue scan 2 (will not run because previous is in progress)
1136        // uses uid of calling process
1137        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1138        mLooper.dispatchAll();
1139        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1140
1141        // Queue scan 3 (will be merged into the active scan)
1142        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, workSource3);
1143        mLooper.dispatchAll();
1144        verifySuccessfulResponse(handlerOrder, handler, requestId3);
1145
1146        // dispatch scan 1 results
1147        when(mWifiScannerImpl.getLatestSingleScanResults())
1148                .thenReturn(results1and3.getScanData());
1149        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1150
1151        mLooper.dispatchAll();
1152        verifyMultipleSingleScanResults(handlerOrder, handler, requestId1, results1, requestId3,
1153                results3);
1154        // only the requests know at the beginning of the scan get blamed
1155        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource1));
1156        verify(mBatteryStats).noteWifiScanStartedFromSource(eq(workSource2));
1157
1158        // now that the first scan completed we expect the second and third ones to start
1159        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(nativeOrder,
1160                computeSingleScanNativeSettings(requestSettings2));
1161
1162        // dispatch scan 2 and 3 results
1163        when(mWifiScannerImpl.getLatestSingleScanResults())
1164                .thenReturn(results2.getScanData());
1165        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1166
1167        mLooper.dispatchAll();
1168
1169        verifyScanResultsReceived(handlerOrder, handler, requestId2, results2.getScanData());
1170        verifySingleScanCompletedReceived(handlerOrder, handler, requestId2);
1171        verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1172        assertEquals(mWifiMetrics.getOneshotScanCount(), 3);
1173        assertEquals(mWifiMetrics.getScanReturnEntry(WifiMetricsProto.WifiLog.SCAN_SUCCESS), 3);
1174
1175        verify(mBatteryStats).noteWifiScanStoppedFromSource(eq(workSource2));
1176
1177        assertDumpContainsRequestLog("addSingleScanRequest", requestId1);
1178        assertDumpContainsRequestLog("addSingleScanRequest", requestId2);
1179        assertDumpContainsRequestLog("addSingleScanRequest", requestId3);
1180        assertDumpContainsCallbackLog("singleScanResults", requestId1,
1181                "results=" + results1.getRawScanResults().length);
1182        assertDumpContainsCallbackLog("singleScanResults", requestId2,
1183                "results=" + results2.getRawScanResults().length);
1184        assertDumpContainsCallbackLog("singleScanResults", requestId3,
1185                "results=" + results3.getRawScanResults().length);
1186    }
1187
1188    /**
1189     * Verify that WifiService provides a way to get the most recent SingleScan results.
1190     */
1191    @Test
1192    public void retrieveSingleScanResults() throws Exception {
1193        WifiScanner.ScanSettings requestSettings =
1194                createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
1195                              0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1196        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1197        doSuccessfulSingleScan(requestSettings,
1198                               computeSingleScanNativeSettings(requestSettings),
1199                               expectedResults);
1200        Handler handler = mock(Handler.class);
1201        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1202        InOrder order = inOrder(handler, mWifiScannerImpl);
1203
1204        controlChannel.sendMessage(
1205                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1206        mLooper.dispatchAll();
1207        Message response = verifyHandleMessageAndGetMessage(order, handler);
1208        List<ScanResult> results = Arrays.asList(
1209                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1210        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1211
1212        // Make sure that we logged the scan results in the dump method.
1213        String serviceDump = dumpService();
1214        Pattern logLineRegex = Pattern.compile("Latest scan results:");
1215        assertTrue("dump did not contain Latest scan results: " + serviceDump + "\n",
1216                logLineRegex.matcher(serviceDump).find());
1217    }
1218
1219    /**
1220     * Verify that WifiService provides a way to get the most recent SingleScan results even when
1221     * they are empty.
1222     */
1223    @Test
1224    public void retrieveSingleScanResultsEmpty() throws Exception {
1225        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1226                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1227        doSuccessfulSingleScan(requestSettings, computeSingleScanNativeSettings(requestSettings),
1228                ScanResults.create(0, new int[0]));
1229
1230        Handler handler = mock(Handler.class);
1231        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1232        InOrder order = inOrder(handler, mWifiScannerImpl);
1233
1234        controlChannel.sendMessage(
1235                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1236        mLooper.dispatchAll();
1237        Message response = verifyHandleMessageAndGetMessage(order, handler);
1238
1239        List<ScanResult> results = Arrays.asList(
1240                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1241        assertEquals(results.size(), 0);
1242    }
1243
1244    /**
1245     * Verify that WifiService will return empty SingleScan results if a scan has not been
1246     * performed.
1247     */
1248    @Test
1249    public void retrieveSingleScanResultsBeforeAnySingleScans() throws Exception {
1250        startServiceAndLoadDriver();
1251        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1252        Handler handler = mock(Handler.class);
1253        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1254        InOrder order = inOrder(handler, mWifiScannerImpl);
1255
1256        controlChannel.sendMessage(
1257                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1258        mLooper.dispatchAll();
1259        Message response = verifyHandleMessageAndGetMessage(order, handler);
1260
1261        List<ScanResult> results = Arrays.asList(
1262                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1263        assertEquals(results.size(), 0);
1264    }
1265
1266    /**
1267     * Verify that the newest full scan results are returned by WifiService.getSingleScanResults.
1268     */
1269    @Test
1270    public void retrieveMostRecentFullSingleScanResults() throws Exception {
1271        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1272                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1273        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1274        doSuccessfulSingleScan(requestSettings,
1275                               computeSingleScanNativeSettings(requestSettings),
1276                               expectedResults);
1277
1278        Handler handler = mock(Handler.class);
1279        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1280        InOrder order = inOrder(handler, mWifiScannerImpl);
1281
1282        controlChannel.sendMessage(
1283                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1284        mLooper.dispatchAll();
1285        Message response = verifyHandleMessageAndGetMessage(order, handler);
1286
1287        List<ScanResult> results = Arrays.asList(
1288                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1289        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1290
1291        // now update with a new scan that only has one result
1292        int secondScanRequestId = 35;
1293        ScanResults expectedSingleResult = ScanResults.create(0, true, 5150);
1294        sendSingleScanRequest(controlChannel, secondScanRequestId, requestSettings, null);
1295
1296        mLooper.dispatchAll();
1297        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order,
1298                computeSingleScanNativeSettings(requestSettings));
1299        verifySuccessfulResponse(order, handler, secondScanRequestId);
1300
1301        // dispatch scan 2 results
1302        when(mWifiScannerImpl.getLatestSingleScanResults())
1303                .thenReturn(expectedSingleResult.getScanData());
1304        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1305
1306        mLooper.dispatchAll();
1307        verifyScanResultsReceived(order, handler, secondScanRequestId,
1308                expectedSingleResult.getScanData());
1309        verifySingleScanCompletedReceived(order, handler, secondScanRequestId);
1310
1311        controlChannel.sendMessage(
1312                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1313        mLooper.dispatchAll();
1314        Message response2 = verifyHandleMessageAndGetMessage(order, handler);
1315
1316        List<ScanResult> results2 = Arrays.asList(
1317                ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
1318        assertEquals(results2.size(), expectedSingleResult.getRawScanResults().length);
1319    }
1320
1321    /**
1322     * Verify that the newest partial scan results are not returned by
1323     * WifiService.getSingleScanResults.
1324     */
1325    @Test
1326    public void doesNotRetrieveMostRecentPartialSingleScanResults() throws Exception {
1327        WifiScanner.ScanSettings fullRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1328                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1329        ScanResults expectedFullResults = ScanResults.create(0, true, 2400, 5150, 5175);
1330        doSuccessfulSingleScan(fullRequestSettings,
1331                computeSingleScanNativeSettings(fullRequestSettings),
1332                expectedFullResults);
1333
1334        Handler handler = mock(Handler.class);
1335        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1336        InOrder order = inOrder(handler, mWifiScannerImpl);
1337
1338        controlChannel.sendMessage(
1339                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1340        mLooper.dispatchAll();
1341        Message response = verifyHandleMessageAndGetMessage(order, handler);
1342
1343        List<ScanResult> results = Arrays.asList(
1344                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1345        assertEquals(results.size(), expectedFullResults.getRawScanResults().length);
1346
1347        // now update with a new scan that only has one result
1348        int secondScanRequestId = 35;
1349        WifiScanner.ScanSettings partialRequestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH,
1350                0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1351        ScanResults expectedPartialResults = ScanResults.create(0, false, 5150);
1352        sendSingleScanRequest(controlChannel, secondScanRequestId, partialRequestSettings, null);
1353
1354        mLooper.dispatchAll();
1355        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order,
1356                computeSingleScanNativeSettings(partialRequestSettings));
1357        verifySuccessfulResponse(order, handler, secondScanRequestId);
1358
1359        // dispatch scan 2 results
1360        when(mWifiScannerImpl.getLatestSingleScanResults())
1361                .thenReturn(expectedPartialResults.getScanData());
1362        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1363
1364        mLooper.dispatchAll();
1365        verifyScanResultsReceived(order, handler, secondScanRequestId,
1366                expectedPartialResults.getScanData());
1367        verifySingleScanCompletedReceived(order, handler, secondScanRequestId);
1368
1369        controlChannel.sendMessage(
1370                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1371        mLooper.dispatchAll();
1372        Message response2 = verifyHandleMessageAndGetMessage(order, handler);
1373
1374        List<ScanResult> results2 = Arrays.asList(
1375                ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
1376        assertEquals(results2.size(), expectedFullResults.getRawScanResults().length);
1377    }
1378
1379    /**
1380     * Verify that the scan results returned by WifiService.getSingleScanResults are not older
1381     * than {@link com.android.server.wifi.scanner.WifiScanningServiceImpl
1382     * .WifiSingleScanStateMachine#CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS}.
1383     */
1384    @Test
1385    public void doesNotRetrieveStaleScanResultsFromLastFullSingleScan() throws Exception {
1386        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1387                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1388        ScanResults scanResults = ScanResults.create(0, true, 2400, 5150, 5175);
1389
1390        // Out of the 3 scan results, modify the timestamp of 2 of them to be within the expiration
1391        // age and 1 out of it.
1392        long currentTimeInMillis = CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS * 2;
1393        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeInMillis);
1394        scanResults.getRawScanResults()[0].timestamp = (currentTimeInMillis - 1) * 1000;
1395        scanResults.getRawScanResults()[1].timestamp = (currentTimeInMillis - 2) * 1000;
1396        scanResults.getRawScanResults()[2].timestamp =
1397                (currentTimeInMillis - CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS) * 1000;
1398        List<ScanResult> expectedResults = new ArrayList<ScanResult>() {{
1399                add(scanResults.getRawScanResults()[0]);
1400                add(scanResults.getRawScanResults()[1]);
1401            }};
1402
1403        doSuccessfulSingleScan(requestSettings,
1404                computeSingleScanNativeSettings(requestSettings), scanResults);
1405
1406        Handler handler = mock(Handler.class);
1407        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1408        InOrder order = inOrder(handler, mWifiScannerImpl);
1409
1410        controlChannel.sendMessage(
1411                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1412        mLooper.dispatchAll();
1413        Message response = verifyHandleMessageAndGetMessage(order, handler);
1414
1415        List<ScanResult> results = Arrays.asList(
1416                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1417        assertScanResultsEquals(expectedResults.toArray(new ScanResult[expectedResults.size()]),
1418                results.toArray(new ScanResult[results.size()]));
1419    }
1420
1421    /**
1422     * Cached scan results should be cleared after the driver is unloaded.
1423     */
1424    @Test
1425    public void validateScanResultsClearedAfterDriverUnloaded() throws Exception {
1426        WifiScanner.ScanSettings requestSettings =
1427                createRequest(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
1428                              0, 0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1429        ScanResults expectedResults = ScanResults.create(0, true, 2400, 5150, 5175);
1430        doSuccessfulSingleScan(requestSettings,
1431                               computeSingleScanNativeSettings(requestSettings),
1432                               expectedResults);
1433        Handler handler = mock(Handler.class);
1434        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1435        InOrder order = inOrder(handler, mWifiScannerImpl);
1436
1437        controlChannel.sendMessage(
1438                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1439        mLooper.dispatchAll();
1440        Message response = verifyHandleMessageAndGetMessage(order, handler);
1441        List<ScanResult> results = Arrays.asList(
1442                ((WifiScanner.ParcelableScanResults) response.obj).getResults());
1443        assertEquals(results.size(), expectedResults.getRawScanResults().length);
1444
1445        // disable wifi
1446        TestUtil.sendWifiScanAvailable(mBroadcastReceiver,
1447                                       mContext,
1448                                       WifiManager.WIFI_STATE_DISABLED);
1449        // Now get scan results again. The returned list should be empty since we
1450        // clear the cache when exiting the DriverLoaded state.
1451        controlChannel.sendMessage(
1452                Message.obtain(null, WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS, 0));
1453        mLooper.dispatchAll();
1454        Message response2 = verifyHandleMessageAndGetMessage(order, handler);
1455        List<ScanResult> results2 = Arrays.asList(
1456                ((WifiScanner.ParcelableScanResults) response2.obj).getResults());
1457        assertEquals(results2.size(), 0);
1458    }
1459
1460    /**
1461     * Register a single scan listener and do a single scan
1462     */
1463    @Test
1464    public void registerScanListener() throws Exception {
1465        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1466                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1467        WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings);
1468        ScanResults results = ScanResults.create(0, 2400, 5150, 5175);
1469
1470        int requestId = 12;
1471        int listenerRequestId = 13;
1472
1473        startServiceAndLoadDriver();
1474        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1475
1476        Handler handler = mock(Handler.class);
1477        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1478        InOrder order = inOrder(handler, mWifiScannerImpl);
1479
1480        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1481                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1482
1483        registerScanListener(controlChannel, listenerRequestId);
1484        mLooper.dispatchAll();
1485        verifySuccessfulResponse(order, handler, listenerRequestId);
1486
1487        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1488
1489        mLooper.dispatchAll();
1490        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
1491        verifySuccessfulResponse(order, handler, requestId);
1492
1493        when(mWifiScannerImpl.getLatestSingleScanResults())
1494                .thenReturn(results.getRawScanData());
1495        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1496
1497        mLooper.dispatchAll();
1498        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1499        verifySingleScanCompletedReceived(order, handler, requestId);
1500        verifyScanResultsReceived(order, handler, listenerRequestId, results.getScanData());
1501        verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1502        verifyNoMoreInteractions(handler);
1503
1504        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1505        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1506                "results=" + results.getScanData().getResults().length);
1507    }
1508
1509    /**
1510     * Register a single scan listener and do a single scan
1511     */
1512    @Test
1513    public void deregisterScanListener() throws Exception {
1514        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
1515                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1516        WifiNative.ScanSettings nativeSettings = computeSingleScanNativeSettings(requestSettings);
1517        ScanResults results = ScanResults.create(0, 2400, 5150, 5175);
1518
1519        int requestId = 12;
1520        int listenerRequestId = 13;
1521
1522        startServiceAndLoadDriver();
1523        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1524
1525        Handler handler = mock(Handler.class);
1526        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1527        InOrder order = inOrder(handler, mWifiScannerImpl);
1528
1529        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1530                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1531
1532        registerScanListener(controlChannel, listenerRequestId);
1533        mLooper.dispatchAll();
1534        verifySuccessfulResponse(order, handler, listenerRequestId);
1535
1536        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
1537
1538        mLooper.dispatchAll();
1539        WifiNative.ScanEventHandler eventHandler = verifyStartSingleScan(order, nativeSettings);
1540        verifySuccessfulResponse(order, handler, requestId);
1541
1542        deregisterScanListener(controlChannel, listenerRequestId);
1543        mLooper.dispatchAll();
1544
1545        when(mWifiScannerImpl.getLatestSingleScanResults())
1546                .thenReturn(results.getRawScanData());
1547        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1548
1549        mLooper.dispatchAll();
1550        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
1551        verifySingleScanCompletedReceived(order, handler, requestId);
1552        verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1553        verifyNoMoreInteractions(handler);
1554
1555        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1556        assertDumpContainsRequestLog("deregisterScanListener", listenerRequestId);
1557    }
1558
1559    /**
1560     * Send a single scan request and then two more before the first completes. Neither are
1561     * satisfied by the first scan. Verify that the first completes and the second two are merged.
1562     */
1563    @Test
1564    public void scanListenerReceivesAllResults() throws RemoteException {
1565        WifiScanner.ScanSettings requestSettings1 = createRequest(channelsToSpec(2400), 0,
1566                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1567        int requestId1 = 12;
1568        ScanResults results1 = ScanResults.create(0, 2400);
1569
1570        WifiScanner.ScanSettings requestSettings2 = createRequest(channelsToSpec(2450, 5175), 0,
1571                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1572        int requestId2 = 13;
1573        ScanResults results2 = ScanResults.create(0, 2450, 5175, 2450);
1574
1575        WifiScanner.ScanSettings requestSettings3 = createRequest(channelsToSpec(5150), 0,
1576                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1577        int requestId3 = 15;
1578        ScanResults results3 = ScanResults.create(0, 5150, 5150, 5150, 5150);
1579
1580        WifiNative.ScanSettings nativeSettings2and3 = createSingleScanNativeSettingsForChannels(
1581                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, channelsToSpec(2450, 5175, 5150));
1582        ScanResults results2and3 = ScanResults.merge(results2, results3);
1583
1584        int listenerRequestId = 13;
1585
1586
1587        startServiceAndLoadDriver();
1588        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1589
1590        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1591                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1592
1593        Handler handler = mock(Handler.class);
1594        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1595        InOrder handlerOrder = inOrder(handler);
1596        InOrder nativeOrder = inOrder(mWifiScannerImpl);
1597
1598        // Run scan 1
1599        sendSingleScanRequest(controlChannel, requestId1, requestSettings1, null);
1600
1601        mLooper.dispatchAll();
1602        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(nativeOrder,
1603                computeSingleScanNativeSettings(requestSettings1));
1604        verifySuccessfulResponse(handlerOrder, handler, requestId1);
1605
1606
1607        // Queue scan 2 (will not run because previous is in progress)
1608        sendSingleScanRequest(controlChannel, requestId2, requestSettings2, null);
1609        mLooper.dispatchAll();
1610        verifySuccessfulResponse(handlerOrder, handler, requestId2);
1611
1612        // Queue scan 3 (will not run because previous is in progress)
1613        sendSingleScanRequest(controlChannel, requestId3, requestSettings3, null);
1614        mLooper.dispatchAll();
1615        verifySuccessfulResponse(handlerOrder, handler, requestId3);
1616
1617        // Register scan listener
1618        registerScanListener(controlChannel, listenerRequestId);
1619        mLooper.dispatchAll();
1620        verifySuccessfulResponse(handlerOrder, handler, listenerRequestId);
1621
1622        // dispatch scan 1 results
1623        when(mWifiScannerImpl.getLatestSingleScanResults())
1624                .thenReturn(results1.getScanData());
1625        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1626
1627        mLooper.dispatchAll();
1628        verifyScanResultsReceived(handlerOrder, handler, requestId1, results1.getScanData());
1629        verifySingleScanCompletedReceived(handlerOrder, handler, requestId1);
1630        verifyScanResultsReceived(handlerOrder, handler, listenerRequestId, results1.getScanData());
1631        verify(mContext, never()).sendBroadcastAsUser(any(Intent.class), eq(UserHandle.ALL));
1632
1633        // now that the first scan completed we expect the second and third ones to start
1634        WifiNative.ScanEventHandler eventHandler2and3 = verifyStartSingleScan(nativeOrder,
1635                nativeSettings2and3);
1636
1637        // dispatch scan 2 and 3 results
1638        when(mWifiScannerImpl.getLatestSingleScanResults())
1639                .thenReturn(results2and3.getScanData());
1640        eventHandler2and3.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1641
1642        mLooper.dispatchAll();
1643
1644        verifyMultipleSingleScanResults(handlerOrder, handler, requestId2, results2, requestId3,
1645                results3, listenerRequestId, results2and3);
1646
1647        assertDumpContainsRequestLog("registerScanListener", listenerRequestId);
1648        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1649                "results=" + results1.getRawScanResults().length);
1650        assertDumpContainsCallbackLog("singleScanResults", listenerRequestId,
1651                "results=" + results2and3.getRawScanResults().length);
1652    }
1653
1654
1655    private void doSuccessfulBackgroundScan(WifiScanner.ScanSettings requestSettings,
1656            WifiNative.ScanSettings nativeSettings) {
1657        startServiceAndLoadDriver();
1658        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1659
1660        Handler handler = mock(Handler.class);
1661        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1662        InOrder order = inOrder(handler, mWifiScannerImpl);
1663
1664        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1665                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1666
1667        sendBackgroundScanRequest(controlChannel, 12, requestSettings, null);
1668        mLooper.dispatchAll();
1669        verifyStartBackgroundScan(order, nativeSettings);
1670        verifySuccessfulResponse(order, handler, 12);
1671        verifyNoMoreInteractions(handler);
1672        assertDumpContainsRequestLog("addBackgroundScanRequest", 12);
1673    }
1674
1675    /**
1676     * Do a background scan for a band and verify that it is successful.
1677     */
1678    @Test
1679    public void sendBackgroundScanBandRequest() throws Exception {
1680        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 30000,
1681                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1682        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1683                .withBasePeriod(30000)
1684                .withMaxApPerScan(MAX_AP_PER_SCAN)
1685                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1686                .addBucketWithBand(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
1687                        WifiScanner.WIFI_BAND_BOTH)
1688                .build();
1689        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
1690        assertEquals(mWifiMetrics.getBackgroundScanCount(), 1);
1691    }
1692
1693    /**
1694     * Do a background scan for a list of channels and verify that it is successful.
1695     */
1696    @Test
1697    public void sendBackgroundScanChannelsRequest() throws Exception {
1698        WifiScanner.ScanSettings requestSettings = createRequest(channelsToSpec(5150), 30000,
1699                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1700        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1701                .withBasePeriod(30000)
1702                .withMaxApPerScan(MAX_AP_PER_SCAN)
1703                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1704                .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5150)
1705                .build();
1706        doSuccessfulBackgroundScan(requestSettings, nativeSettings);
1707    }
1708
1709    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForHwPno()
1710            throws Exception {
1711        WifiScanner.ScanSettings requestSettings = createRequest(
1712                channelsToSpec(0, 2400, 5150, 5175), 30000, 0, 20,
1713                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
1714        WifiNative.ScanSettings nativeSettings = new NativeScanSettingsBuilder()
1715                .withBasePeriod(30000)
1716                .withMaxApPerScan(MAX_AP_PER_SCAN)
1717                .withMaxScansToCache(BackgroundScanScheduler.DEFAULT_MAX_SCANS_TO_BATCH)
1718                .addBucketWithChannels(30000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN,
1719                        0, 2400, 5150, 5175)
1720                .build();
1721        return Pair.create(requestSettings, nativeSettings);
1722    }
1723
1724    private Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> createScanSettingsForSwPno()
1725            throws Exception {
1726        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> settingsPair =
1727                createScanSettingsForHwPno();
1728
1729        WifiScanner.ScanSettings requestSettings = settingsPair.first;
1730        WifiNative.ScanSettings nativeSettings = settingsPair.second;
1731        // reportEvents field is overridden for SW PNO
1732        for (int i = 0; i < nativeSettings.buckets.length; i++) {
1733            nativeSettings.buckets[i].report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
1734                    | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT;
1735        }
1736        return Pair.create(requestSettings, nativeSettings);
1737    }
1738
1739    private Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> createPnoSettings(
1740            ScanResults results)
1741            throws Exception {
1742        WifiScanner.PnoSettings requestPnoSettings = new WifiScanner.PnoSettings();
1743        requestPnoSettings.networkList =
1744                new WifiScanner.PnoSettings.PnoNetwork[results.getRawScanResults().length];
1745        int i = 0;
1746        for (ScanResult scanResult : results.getRawScanResults()) {
1747            requestPnoSettings.networkList[i++] =
1748                    new WifiScanner.PnoSettings.PnoNetwork(scanResult.SSID);
1749        }
1750
1751        WifiNative.PnoSettings nativePnoSettings = new WifiNative.PnoSettings();
1752        nativePnoSettings.min5GHzRssi = requestPnoSettings.min5GHzRssi;
1753        nativePnoSettings.min24GHzRssi = requestPnoSettings.min24GHzRssi;
1754        nativePnoSettings.initialScoreMax = requestPnoSettings.initialScoreMax;
1755        nativePnoSettings.currentConnectionBonus = requestPnoSettings.currentConnectionBonus;
1756        nativePnoSettings.sameNetworkBonus = requestPnoSettings.sameNetworkBonus;
1757        nativePnoSettings.secureBonus = requestPnoSettings.secureBonus;
1758        nativePnoSettings.band5GHzBonus = requestPnoSettings.band5GHzBonus;
1759        nativePnoSettings.isConnected = requestPnoSettings.isConnected;
1760        nativePnoSettings.networkList =
1761                new WifiNative.PnoNetwork[requestPnoSettings.networkList.length];
1762        for (i = 0; i < requestPnoSettings.networkList.length; i++) {
1763            nativePnoSettings.networkList[i] = new WifiNative.PnoNetwork();
1764            nativePnoSettings.networkList[i].ssid = requestPnoSettings.networkList[i].ssid;
1765            nativePnoSettings.networkList[i].flags = requestPnoSettings.networkList[i].flags;
1766            nativePnoSettings.networkList[i].auth_bit_field =
1767                    requestPnoSettings.networkList[i].authBitField;
1768        }
1769        return Pair.create(requestPnoSettings, nativePnoSettings);
1770    }
1771
1772    private ScanResults createScanResultsForPno() {
1773        return ScanResults.create(0, 2400, 5150, 5175);
1774    }
1775
1776    private ScanResults createScanResultsForPnoWithNoIE() {
1777        return ScanResults.createWithNoIE(0, 2400, 5150, 5175);
1778    }
1779
1780    private WifiNative.PnoEventHandler verifyHwPno(InOrder order,
1781            WifiNative.PnoSettings expected) {
1782        ArgumentCaptor<WifiNative.PnoSettings> pnoSettingsCaptor =
1783                ArgumentCaptor.forClass(WifiNative.PnoSettings.class);
1784        ArgumentCaptor<WifiNative.PnoEventHandler> pnoEventHandlerCaptor =
1785                ArgumentCaptor.forClass(WifiNative.PnoEventHandler.class);
1786        order.verify(mWifiScannerImpl).setHwPnoList(pnoSettingsCaptor.capture(),
1787                pnoEventHandlerCaptor.capture());
1788        assertNativePnoSettingsEquals(expected, pnoSettingsCaptor.getValue());
1789        return pnoEventHandlerCaptor.getValue();
1790    }
1791
1792    private void sendPnoScanRequest(BidirectionalAsyncChannel controlChannel,
1793            int scanRequestId, WifiScanner.ScanSettings scanSettings,
1794            WifiScanner.PnoSettings pnoSettings) {
1795        Bundle pnoParams = new Bundle();
1796        scanSettings.isPnoScan = true;
1797        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY, scanSettings);
1798        pnoParams.putParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY, pnoSettings);
1799        controlChannel.sendMessage(Message.obtain(null, WifiScanner.CMD_START_PNO_SCAN, 0,
1800                scanRequestId, pnoParams));
1801    }
1802
1803    private void assertPnoNetworkFoundMessage(int listenerId, ScanResult[] expected,
1804            Message networkFoundMessage) {
1805        assertEquals("what", WifiScanner.CMD_PNO_NETWORK_FOUND, networkFoundMessage.what);
1806        assertEquals("listenerId", listenerId, networkFoundMessage.arg2);
1807        assertScanResultsEquals(expected,
1808                ((WifiScanner.ParcelableScanResults) networkFoundMessage.obj).getResults());
1809    }
1810
1811    private void verifyPnoNetworkFoundReceived(InOrder order, Handler handler, int listenerId,
1812            ScanResult[] expected) {
1813        Message scanResultMessage = verifyHandleMessageAndGetMessage(order, handler,
1814                WifiScanner.CMD_PNO_NETWORK_FOUND);
1815        assertPnoNetworkFoundMessage(listenerId, expected, scanResultMessage);
1816    }
1817
1818    private void expectSuccessfulBackgroundScan(InOrder order,
1819            WifiNative.ScanSettings nativeSettings, ScanResults results) {
1820        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1821                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1822        mLooper.dispatchAll();
1823        WifiNative.ScanEventHandler eventHandler = verifyStartBackgroundScan(order, nativeSettings);
1824        WifiScanner.ScanData[] scanDatas = new WifiScanner.ScanData[1];
1825        scanDatas[0] = results.getScanData();
1826        for (ScanResult fullScanResult : results.getRawScanResults()) {
1827            eventHandler.onFullScanResult(fullScanResult, 0);
1828        }
1829        when(mWifiScannerImpl.getLatestBatchedScanResults(anyBoolean())).thenReturn(scanDatas);
1830        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1831        mLooper.dispatchAll();
1832    }
1833
1834    private void expectHwPnoScanWithNoBackgroundScan(InOrder order, Handler handler, int requestId,
1835            WifiNative.PnoSettings nativeSettings, ScanResults results) {
1836        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
1837        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(false);
1838
1839        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
1840                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
1841        mLooper.dispatchAll();
1842        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativeSettings);
1843        verifySuccessfulResponse(order, handler, requestId);
1844        eventHandler.onPnoNetworkFound(results.getRawScanResults());
1845        mLooper.dispatchAll();
1846    }
1847
1848    private void expectHwPnoScanWithBackgroundScan(InOrder order, Handler handler, int requestId,
1849            WifiNative.ScanSettings nativeScanSettings,
1850            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
1851        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(true);
1852        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
1853
1854        when(mWifiScannerImpl.setHwPnoList(any(WifiNative.PnoSettings.class),
1855                any(WifiNative.PnoEventHandler.class))).thenReturn(true);
1856        when(mWifiScannerImpl.startBatchedScan(any(WifiNative.ScanSettings.class),
1857                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1858        mLooper.dispatchAll();
1859        WifiNative.PnoEventHandler eventHandler = verifyHwPno(order, nativePnoSettings);
1860        verifySuccessfulResponse(order, handler, requestId);
1861        verifyStartBackgroundScan(order, nativeScanSettings);
1862        eventHandler.onPnoNetworkFound(results.getRawScanResults());
1863        mLooper.dispatchAll();
1864    }
1865
1866    private void expectHwPnoScanWithBackgroundScanWithNoIE(InOrder order, Handler handler,
1867            int requestId, WifiNative.ScanSettings nativeBackgroundScanSettings,
1868            WifiNative.ScanSettings nativeSingleScanSettings,
1869            WifiNative.PnoSettings nativePnoSettings, ScanResults results) {
1870        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
1871                any(WifiNative.ScanEventHandler.class))).thenReturn(true);
1872
1873        expectHwPnoScanWithBackgroundScan(order, handler, requestId, nativeBackgroundScanSettings,
1874                nativePnoSettings, results);
1875        WifiNative.ScanEventHandler eventHandler =
1876                verifyStartSingleScan(order, nativeSingleScanSettings);
1877        when(mWifiScannerImpl.getLatestSingleScanResults()).thenReturn(results.getScanData());
1878        eventHandler.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1879        mLooper.dispatchAll();
1880    }
1881    private void expectSwPnoScan(InOrder order, WifiNative.ScanSettings nativeScanSettings,
1882            ScanResults results) {
1883        when(mWifiScannerImpl.isHwPnoSupported(anyBoolean())).thenReturn(false);
1884        when(mWifiScannerImpl.shouldScheduleBackgroundScanForHwPno()).thenReturn(true);
1885
1886        expectSuccessfulBackgroundScan(order, nativeScanSettings, results);
1887    }
1888
1889    /**
1890     * Tests wificond PNO scan when the PNO scan results contain IE info. This ensures that the
1891     * PNO scan results are plumbed back to the client as a PNO network found event.
1892     */
1893    @Test
1894    public void testSuccessfulHwPnoScanWithNoBackgroundScan() throws Exception {
1895        startServiceAndLoadDriver();
1896        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1897        Handler handler = mock(Handler.class);
1898        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1899        InOrder order = inOrder(handler, mWifiScannerImpl);
1900        int requestId = 12;
1901
1902        ScanResults scanResults = createScanResultsForPno();
1903        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1904                createScanSettingsForHwPno();
1905        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1906                createPnoSettings(scanResults);
1907
1908        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1909        expectHwPnoScanWithNoBackgroundScan(order, handler, requestId, pnoSettings.second,
1910                scanResults);
1911        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1912    }
1913
1914    /**
1915     * Tests Hal ePNO scan when the PNO scan results contain IE info. This ensures that the
1916     * PNO scan results are plumbed back to the client as a PNO network found event.
1917     */
1918    @Test
1919    public void testSuccessfulHwPnoScanWithBackgroundScan() throws Exception {
1920        startServiceAndLoadDriver();
1921        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1922        Handler handler = mock(Handler.class);
1923        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1924        InOrder order = inOrder(handler, mWifiScannerImpl);
1925        int requestId = 12;
1926
1927        ScanResults scanResults = createScanResultsForPno();
1928        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1929                createScanSettingsForHwPno();
1930        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1931                createPnoSettings(scanResults);
1932
1933        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1934        expectHwPnoScanWithBackgroundScan(order, handler, requestId, scanSettings.second,
1935                pnoSettings.second, scanResults);
1936        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1937    }
1938
1939    /**
1940     * Tests Hal ePNO scan when the PNO scan results don't contain IE info. This ensures that the
1941     * single scan results are plumbed back to the client as a PNO network found event.
1942     */
1943    @Test
1944    public void testSuccessfulHwPnoScanWithBackgroundScanWithNoIE() throws Exception {
1945        startServiceAndLoadDriver();
1946        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1947        Handler handler = mock(Handler.class);
1948        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1949        InOrder order = inOrder(handler, mWifiScannerImpl);
1950        int requestId = 12;
1951
1952        ScanResults scanResults = createScanResultsForPnoWithNoIE();
1953        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1954                createScanSettingsForHwPno();
1955        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1956                createPnoSettings(scanResults);
1957
1958        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1959        expectHwPnoScanWithBackgroundScanWithNoIE(order, handler, requestId, scanSettings.second,
1960                computeSingleScanNativeSettings(scanSettings.first), pnoSettings.second,
1961                scanResults);
1962
1963        ArrayList<ScanResult> sortScanList =
1964                new ArrayList<ScanResult>(Arrays.asList(scanResults.getRawScanResults()));
1965        Collections.sort(sortScanList, WifiScannerImpl.SCAN_RESULT_SORT_COMPARATOR);
1966        verifyPnoNetworkFoundReceived(order, handler, requestId,
1967                sortScanList.toArray(new ScanResult[sortScanList.size()]));
1968    }
1969
1970    /**
1971     * Tests SW PNO scan. This ensures that the background scan results are plumbed back to the
1972     * client as a PNO network found event.
1973     */
1974    @Test
1975    public void testSuccessfulSwPnoScan() throws Exception {
1976        startServiceAndLoadDriver();
1977        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
1978        Handler handler = mock(Handler.class);
1979        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
1980        InOrder order = inOrder(handler, mWifiScannerImpl);
1981        int requestId = 12;
1982
1983        ScanResults scanResults = createScanResultsForPno();
1984        Pair<WifiScanner.ScanSettings, WifiNative.ScanSettings> scanSettings =
1985                createScanSettingsForSwPno();
1986        Pair<WifiScanner.PnoSettings, WifiNative.PnoSettings> pnoSettings =
1987                createPnoSettings(scanResults);
1988
1989        sendPnoScanRequest(controlChannel, requestId, scanSettings.first, pnoSettings.first);
1990        expectSwPnoScan(order, scanSettings.second, scanResults);
1991        verifyPnoNetworkFoundReceived(order, handler, requestId, scanResults.getRawScanResults());
1992    }
1993
1994    /**
1995     * Tries to simulate the race scenario where a client is disconnected immediately after single
1996     * scan request is sent to |SingleScanStateMachine|.
1997     */
1998    @Test
1999    public void processSingleScanRequestAfterDisconnect() throws Exception {
2000        startServiceAndLoadDriver();
2001        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
2002        BidirectionalAsyncChannel controlChannel = connectChannel(mock(Handler.class));
2003        mLooper.dispatchAll();
2004
2005        // Send the single scan request and then send the disconnect immediately after.
2006        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
2007                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
2008        int requestId = 10;
2009
2010        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
2011        // Can't call |disconnect| here because that sends |CMD_CHANNEL_DISCONNECT| followed by
2012        // |CMD_CHANNEL_DISCONNECTED|.
2013        controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
2014                        AsyncChannel.STATUS_REMOTE_DISCONNECTION, 0, null));
2015
2016        // Now process the above 2 actions. This should result in first processing the single scan
2017        // request (which forwards the request to SingleScanStateMachine) and then processing the
2018        // disconnect after.
2019        mLooper.dispatchAll();
2020
2021        // Now check that we logged the invalid request.
2022        String serviceDump = dumpService();
2023        Pattern logLineRegex = Pattern.compile("^.+" + "singleScanInvalidRequest: "
2024                + "ClientInfo\\[unknown\\],Id=" + requestId + ",bad request$", Pattern.MULTILINE);
2025        assertTrue("dump did not contain log with ClientInfo[unknown]: " + serviceDump + "\n",
2026                logLineRegex.matcher(serviceDump).find());
2027    }
2028
2029    /**
2030     * Tries to simulate the race scenario where a client is disconnected immediately after single
2031     * scan request is sent to |SingleScanStateMachine|.
2032     */
2033    @Test
2034    public void sendScanRequestAfterUnsuccessfulSend() throws Exception {
2035        WifiScanner.ScanSettings requestSettings = createRequest(WifiScanner.WIFI_BAND_BOTH, 0,
2036                0, 20, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN);
2037        int requestId = 9;
2038
2039        startServiceAndLoadDriver();
2040        mWifiScanningServiceImpl.setWifiHandlerLogForTest(mLog);
2041        Handler handler = mock(Handler.class);
2042        BidirectionalAsyncChannel controlChannel = connectChannel(handler);
2043        mLooper.dispatchAll();
2044
2045        when(mWifiScannerImpl.startSingleScan(any(WifiNative.ScanSettings.class),
2046                        any(WifiNative.ScanEventHandler.class))).thenReturn(true);
2047        ScanResults results = ScanResults.create(0, 2400);
2048        when(mWifiScannerImpl.getLatestSingleScanResults())
2049                .thenReturn(results.getRawScanData());
2050
2051        InOrder order = inOrder(mWifiScannerImpl, handler);
2052
2053        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
2054        mLooper.dispatchAll();
2055        WifiNative.ScanEventHandler eventHandler1 = verifyStartSingleScan(order,
2056                computeSingleScanNativeSettings(requestSettings));
2057        verifySuccessfulResponse(order, handler, requestId);
2058
2059        eventHandler1.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
2060        mLooper.dispatchAll();
2061        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
2062        verifySingleScanCompletedReceived(order, handler, requestId);
2063        verifyNoMoreInteractions(handler);
2064
2065        controlChannel.sendMessage(Message.obtain(null, AsyncChannel.CMD_CHANNEL_DISCONNECTED,
2066                        AsyncChannel.STATUS_SEND_UNSUCCESSFUL, 0, null));
2067        mLooper.dispatchAll();
2068
2069        sendSingleScanRequest(controlChannel, requestId, requestSettings, null);
2070        mLooper.dispatchAll();
2071        WifiNative.ScanEventHandler eventHandler2 = verifyStartSingleScan(order,
2072                computeSingleScanNativeSettings(requestSettings));
2073        verifySuccessfulResponse(order, handler, requestId);
2074
2075        eventHandler2.onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
2076        mLooper.dispatchAll();
2077        verifyScanResultsReceived(order, handler, requestId, results.getScanData());
2078        verifySingleScanCompletedReceived(order, handler, requestId);
2079        verifyNoMoreInteractions(handler);
2080    }
2081}
2082