Home | History | Annotate | Download | only in scanner
      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 
     17 package com.android.server.wifi.scanner;
     18 
     19 import static com.android.server.wifi.ScanTestUtil.*;
     20 import static com.android.server.wifi.scanner.WifiScanningServiceImpl.WifiSingleScanStateMachine
     21         .CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS;
     22 
     23 import static org.junit.Assert.*;
     24 import static org.mockito.Mockito.*;
     25 
     26 import android.app.test.MockAnswerUtil.AnswerWithArguments;
     27 import android.app.test.TestAlarmManager;
     28 import android.content.BroadcastReceiver;
     29 import android.content.Context;
     30 import android.content.Intent;
     31 import android.content.IntentFilter;
     32 import android.net.wifi.ScanResult;
     33 import android.net.wifi.WifiManager;
     34 import android.net.wifi.WifiScanner;
     35 import android.os.Binder;
     36 import android.os.Bundle;
     37 import android.os.Handler;
     38 import android.os.Message;
     39 import android.os.RemoteException;
     40 import android.os.UserHandle;
     41 import android.os.WorkSource;
     42 import android.os.test.TestLooper;
     43 import android.test.suitebuilder.annotation.SmallTest;
     44 import android.util.Pair;
     45 
     46 import com.android.internal.app.IBatteryStats;
     47 import com.android.internal.util.AsyncChannel;
     48 import com.android.internal.util.Protocol;
     49 import com.android.internal.util.test.BidirectionalAsyncChannel;
     50 import com.android.server.wifi.Clock;
     51 import com.android.server.wifi.FakeWifiLog;
     52 import com.android.server.wifi.FrameworkFacade;
     53 import com.android.server.wifi.ScanResults;
     54 import com.android.server.wifi.TestUtil;
     55 import com.android.server.wifi.WifiInjector;
     56 import com.android.server.wifi.WifiMetrics;
     57 import com.android.server.wifi.WifiNative;
     58 import com.android.server.wifi.nano.WifiMetricsProto;
     59 import com.android.server.wifi.util.WifiAsyncChannel;
     60 
     61 import org.junit.After;
     62 import org.junit.Before;
     63 import org.junit.Test;
     64 import org.mockito.ArgumentCaptor;
     65 import org.mockito.InOrder;
     66 import org.mockito.Mock;
     67 import org.mockito.MockitoAnnotations;
     68 import org.mockito.Spy;
     69 import org.mockito.compat.CapturingMatcher;
     70 
     71 import java.io.FileDescriptor;
     72 import java.io.PrintWriter;
     73 import java.io.StringWriter;
     74 import java.util.ArrayList;
     75 import java.util.Arrays;
     76 import java.util.Collections;
     77 import java.util.List;
     78 import java.util.regex.Pattern;
     79 
     80 /**
     81  * Unit tests for {@link com.android.server.wifi.scanner.WifiScanningServiceImpl}.
     82  */
     83 @SmallTest
     84 public 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