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;
18 
19 import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ;
20 import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ;
21 
22 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES;
23 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES;
24 import static com.android.server.wifi.util.GeneralUtil.bitsetToLong;
25 import static com.android.server.wifi.TestUtil.createCapabilityBitset;
26 
27 import static org.junit.Assert.assertArrayEquals;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertNotNull;
31 import static org.junit.Assert.assertNull;
32 import static org.junit.Assert.assertTrue;
33 import static org.junit.Assume.assumeFalse;
34 import static org.junit.Assume.assumeTrue;
35 import static org.mockito.ArgumentMatchers.any;
36 import static org.mockito.ArgumentMatchers.anyList;
37 import static org.mockito.ArgumentMatchers.anyString;
38 import static org.mockito.ArgumentMatchers.same;
39 import static org.mockito.Mockito.anyBoolean;
40 import static org.mockito.Mockito.anyInt;
41 import static org.mockito.Mockito.eq;
42 import static org.mockito.Mockito.inOrder;
43 import static org.mockito.Mockito.mock;
44 import static org.mockito.Mockito.never;
45 import static org.mockito.Mockito.times;
46 import static org.mockito.Mockito.validateMockitoUsage;
47 import static org.mockito.Mockito.verify;
48 import static org.mockito.Mockito.when;
49 import static org.mockito.Mockito.withSettings;
50 
51 import android.net.MacAddress;
52 import android.net.wifi.CoexUnsafeChannel;
53 import android.net.wifi.ScanResult;
54 import android.net.wifi.SoftApConfiguration;
55 import android.net.wifi.WifiAvailableChannel;
56 import android.net.wifi.WifiConfiguration;
57 import android.net.wifi.WifiContext;
58 import android.net.wifi.WifiManager;
59 import android.net.wifi.WifiMigration;
60 import android.net.wifi.WifiScanner;
61 import android.net.wifi.WifiScanner.ScanData;
62 import android.net.wifi.WifiSsid;
63 import android.net.wifi.nl80211.NativeScanResult;
64 import android.net.wifi.nl80211.RadioChainInfo;
65 import android.net.wifi.nl80211.WifiNl80211Manager;
66 import android.net.wifi.nl80211.WifiNl80211Manager.SendMgmtFrameCallback;
67 import android.os.Bundle;
68 import android.os.Handler;
69 import android.os.WorkSource;
70 import android.text.TextUtils;
71 
72 import androidx.test.filters.SmallTest;
73 
74 import com.android.dx.mockito.inline.extended.ExtendedMockito;
75 import com.android.modules.utils.build.SdkLevel;
76 import com.android.server.wifi.coex.CoexManager;
77 import com.android.server.wifi.hal.WifiChip;
78 import com.android.server.wifi.p2p.WifiP2pNative;
79 import com.android.server.wifi.proto.WifiStatsLog;
80 import com.android.server.wifi.util.NativeUtil;
81 import com.android.server.wifi.util.NetdWrapper;
82 import com.android.wifi.flags.Flags;
83 import com.android.wifi.resources.R;
84 
85 import org.junit.After;
86 import org.junit.Before;
87 import org.junit.Test;
88 import org.mockito.AdditionalMatchers;
89 import org.mockito.ArgumentCaptor;
90 import org.mockito.InOrder;
91 import org.mockito.Mock;
92 import org.mockito.MockitoAnnotations;
93 import org.mockito.MockitoSession;
94 import org.mockito.quality.Strictness;
95 import org.mockito.stubbing.Answer;
96 
97 import java.util.ArrayList;
98 import java.util.Arrays;
99 import java.util.BitSet;
100 import java.util.Collections;
101 import java.util.List;
102 import java.util.Random;
103 import java.util.Set;
104 import java.util.regex.Pattern;
105 
106 /**
107  * Unit tests for {@link com.android.server.wifi.WifiNative}.
108  */
109 @SmallTest
110 public class WifiNativeTest extends WifiBaseTest {
111     private static final String WIFI_IFACE_NAME = "mockWlan";
112     private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345;
113     private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] {
114             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
115     private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport(
116             WifiLoggerHal.TX_PKT_FATE_SENT,
117             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
118             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
119             FATE_REPORT_FRAME_BYTES
120     );
121     private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport(
122             WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
123             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
124             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
125             FATE_REPORT_FRAME_BYTES
126     );
127     private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] {
128             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"),
129             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"),
130             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management",
131                     "802.11 Mgmt"),
132             new FrameTypeMapping((byte) 42, "42", "N/A")
133     };
134     private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] {
135             new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
136             new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
137             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
138             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
139                     "firmware dropped (invalid frame)"),
140             new FateMapping(
141                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS,  "firmware dropped (no bufs)"),
142             new FateMapping(
143                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
144             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
145             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
146                     "driver dropped (invalid frame)"),
147             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
148                     "driver dropped (no bufs)"),
149             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
150             new FateMapping((byte) 42, "42")
151     };
152     private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] {
153             new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
154             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
155             new FateMapping(
156                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
157             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
158                     "firmware dropped (invalid frame)"),
159             new FateMapping(
160                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
161             new FateMapping(
162                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
163             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
164             new FateMapping(
165                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
166             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
167                     "driver dropped (invalid frame)"),
168             new FateMapping(
169                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
170             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
171             new FateMapping((byte) 42, "42")
172     };
173     private static final WifiNl80211Manager.SignalPollResult SIGNAL_POLL_RESULT =
174             new WifiNl80211Manager.SignalPollResult(-60, 12, 6, 5240);
175 
176     private static final Set<Integer> SCAN_FREQ_SET = Set.of(
177             2410,
178             2450,
179             5050,
180             5200);
181 
182     private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\"";
183     private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\"";
184     private static final int[] TEST_FREQUENCIES_1 = {};
185     private static final int[] TEST_FREQUENCIES_2 = {2500, 5124};
186     private static final List<String> SCAN_HIDDEN_NETWORK_SSID_SET = List.of(
187             TEST_QUOTED_SSID_1,
188             TEST_QUOTED_SSID_2);
189 
190     private static final List<byte[]> SCAN_HIDDEN_NETWORK_BYTE_SSID_SET = List.of(
191             NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_1)),
192             NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
193 
194     private static final WifiNative.PnoSettings TEST_PNO_SETTINGS =
195             new WifiNative.PnoSettings() {{
196                 isConnected = false;
197                 periodInMs = 6000;
198                 scanIterations = 3;
199                 scanIntervalMultiplier = 3;
200                 networkList = new WifiNative.PnoNetwork[2];
201                 networkList[0] = new WifiNative.PnoNetwork();
202                 networkList[1] = new WifiNative.PnoNetwork();
203                 networkList[0].ssid = TEST_QUOTED_SSID_1;
204                 networkList[1].ssid = TEST_QUOTED_SSID_2;
205                 networkList[0].frequencies = TEST_FREQUENCIES_1;
206                 networkList[1].frequencies = TEST_FREQUENCIES_2;
207             }};
208     private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92");
209 
210     private static final String TEST_MAC_ADDRESS_STR = "f4:f5:e8:51:9e:09";
211     private static final String TEST_BSSID_STR = "a8:bd:27:5b:33:72";
212     private static final int TEST_MCS_RATE = 5;
213     private static final int TEST_SEQUENCE_NUM = 0x66b0;
214 
215     private static final byte[] TEST_SSID =
216             new byte[] {'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
217     private static final byte[] TEST_BSSID =
218             new byte[] {(byte) 0x12, (byte) 0xef, (byte) 0xa1,
219                     (byte) 0x2c, (byte) 0x97, (byte) 0x8b};
220     // This the IE buffer which is consistent with TEST_SSID.
221     private static final byte[] TEST_INFO_ELEMENT_SSID =
222             new byte[] {
223                     // Element ID for SSID.
224                     (byte) 0x00,
225                     // Length of the SSID: 0x0b or 11.
226                     (byte) 0x0b,
227                     // This is string "GoogleGuest"
228                     'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
229     // RSN IE data indicating EAP key management.
230     private static final byte[] TEST_INFO_ELEMENT_RSN =
231             new byte[] {
232                     // Element ID for RSN.
233                     (byte) 0x30,
234                     // Length of the element data.
235                     (byte) 0x18,
236                     (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
237                     (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
238                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, (byte) 0x01, (byte) 0x00,
239                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, (byte) 0x00, (byte) 0x00 };
240 
241     private static final int TEST_FREQUENCY = 2456;
242     private static final int TEST_SIGNAL_MBM = -4500;
243     private static final long TEST_TSF = 34455441;
244     private static final int TEST_CAPABILITY = 0b0000_0000_0010_0100;
245     private static final boolean TEST_ASSOCIATED = true;
246     private static final NativeScanResult MOCK_NATIVE_SCAN_RESULT = createMockNativeScanResult();
createMockNativeScanResult()247     private static NativeScanResult createMockNativeScanResult() {
248         NativeScanResult result = new NativeScanResult();
249         result.ssid = TEST_SSID;
250         result.bssid = TEST_BSSID;
251         result.infoElement = TEST_INFO_ELEMENT_SSID;
252         result.frequency = TEST_FREQUENCY;
253         result.signalMbm = TEST_SIGNAL_MBM;
254         result.tsf = TEST_TSF;
255         result.capability = TEST_CAPABILITY;
256         result.associated = TEST_ASSOCIATED;
257         result.radioChainInfos = new ArrayList<>();
258         return result;
259     }
260 
261     private static final BitSet WIFI_TEST_FEATURE =
262             createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE);
263     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = new RadioChainInfo(1, -89);
264     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = new RadioChainInfo(0, -78);
265     private static final WorkSource TEST_WORKSOURCE = new WorkSource();
266     private static final WorkSource TEST_WORKSOURCE2 = new WorkSource();
267 
268     MockResources mResources;
269 
270     @Mock private WifiContext mContext;
271     @Mock private WifiVendorHal mWifiVendorHal;
272     @Mock private WifiNl80211Manager mWificondControl;
273     @Mock private SupplicantStaIfaceHal mStaIfaceHal;
274     @Mock private HostapdHal mHostapdHal;
275     @Mock private WifiMonitor mWifiMonitor;
276     @Mock private PropertyService mPropertyService;
277     @Mock private WifiMetrics mWifiMetrics;
278     @Mock private Handler mHandler;
279     @Mock private SendMgmtFrameCallback mSendMgmtFrameCallback;
280     @Mock private Random mRandom;
281     @Mock private WifiInjector mWifiInjector;
282     @Mock private NetdWrapper mNetdWrapper;
283     @Mock private CoexManager mCoexManager;
284     @Mock BuildProperties mBuildProperties;
285     @Mock private WifiNative.InterfaceCallback mInterfaceCallback;
286     @Mock private WifiCountryCode.ChangeListener mWifiCountryCodeChangeListener;
287     @Mock WifiSettingsConfigStore mSettingsConfigStore;
288     @Mock private ConcreteClientModeManager mConcreteClientModeManager;
289     @Mock private SoftApManager mSoftApManager;
290     @Mock private SsidTranslator mSsidTranslator;
291     @Mock private WifiGlobals mWifiGlobals;
292     @Mock DeviceConfigFacade mDeviceConfigFacade;
293     @Mock WifiChip.AfcChannelAllowance mAfcChannelAllowance;
294     @Mock private WifiP2pNative mWifiP2pNative;
295 
296     private MockitoSession mSession;
297     ArgumentCaptor<WifiNl80211Manager.ScanEventCallback> mScanCallbackCaptor =
298             ArgumentCaptor.forClass(WifiNl80211Manager.ScanEventCallback.class);
299 
300     private WifiNative mWifiNative;
301 
302     @Before
setUp()303     public void setUp() throws Exception {
304         MockitoAnnotations.initMocks(this);
305 
306         when(mWifiVendorHal.initialize(any())).thenReturn(true);
307         when(mWifiVendorHal.isVendorHalSupported()).thenReturn(true);
308         when(mWifiVendorHal.startVendorHal()).thenReturn(true);
309         when(mWifiVendorHal.startVendorHalSta(eq(mConcreteClientModeManager))).thenReturn(true);
310         when(mWifiVendorHal.createStaIface(any(), any(), eq(mConcreteClientModeManager)))
311                 .thenReturn(WIFI_IFACE_NAME);
312         when(mWifiVendorHal.createApIface(any(), any(), anyInt(), anyBoolean(), any(), anyList()))
313                 .thenReturn(WIFI_IFACE_NAME);
314         when(mWifiVendorHal.getSupportedFeatureSet(anyString())).thenReturn(new BitSet());
315         when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE))
316                 .thenReturn(true);
317 
318         when(mBuildProperties.isEngBuild()).thenReturn(false);
319         when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
320         when(mBuildProperties.isUserBuild()).thenReturn(true);
321 
322         when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn(
323                 true);
324         when(mWificondControl.setupInterfaceForSoftApMode(any())).thenReturn(true);
325 
326         when(mStaIfaceHal.registerDeathHandler(any())).thenReturn(true);
327         when(mStaIfaceHal.isInitializationComplete()).thenReturn(true);
328         when(mStaIfaceHal.initialize()).thenReturn(true);
329         when(mStaIfaceHal.startDaemon()).thenReturn(true);
330         when(mStaIfaceHal.setupIface(any())).thenReturn(true);
331         when(mStaIfaceHal.getAdvancedCapabilities(anyString())).thenReturn(new BitSet());
332         when(mStaIfaceHal.getWpaDriverFeatureSet(anyString())).thenReturn(new BitSet());
333 
334         when(mHostapdHal.isInitializationStarted()).thenReturn(true);
335         when(mHostapdHal.startDaemon()).thenReturn(true);
336         when(mHostapdHal.isInitializationComplete()).thenReturn(true);
337         when(mHostapdHal.registerDeathHandler(any())).thenReturn(true);
338 
339         when(mWifiInjector.makeNetdWrapper()).thenReturn(mNetdWrapper);
340         when(mWifiInjector.getCoexManager()).thenReturn(mCoexManager);
341 
342         when(mWifiInjector.getSettingsConfigStore()).thenReturn(mSettingsConfigStore);
343         when(mWifiInjector.getContext()).thenReturn(mContext);
344         when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator);
345         when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
346         when(mWifiInjector.getWifiP2pNative()).thenReturn(mWifiP2pNative);
347         mResources = getMockResources();
348         mResources.setBoolean(R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled, false);
349         when(mContext.getResources()).thenReturn(mResources);
350         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
351                 .thenReturn(WIFI_TEST_FEATURE.toLongArray());
352         when(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset(any(), any()))
353                 .thenAnswer((Answer<WifiSsid>) invocation ->
354                         getTranslatedSsid(invocation.getArgument(0)));
355         when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
356         when(mDeviceConfigFacade.isInterfaceFailureBugreportEnabled()).thenReturn(false);
357 
358         // Mock static methods from WifiStatsLog.
359         mSession = ExtendedMockito.mockitoSession()
360                 .strictness(Strictness.LENIENT)
361                 .mockStatic(WifiStatsLog.class)
362                 .mockStatic(Flags.class, withSettings().lenient())
363                 .mockStatic(WifiMigration.class, withSettings().lenient())
364                 .startMocking();
365 
366         when(Flags.rsnOverriding()).thenReturn(true);
367 
368         mWifiNative = new WifiNative(
369                 mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
370                 mWifiMonitor, mPropertyService, mWifiMetrics,
371                 mHandler, mRandom, mBuildProperties, mWifiInjector);
372         mWifiNative.enableVerboseLogging(true, true);
373         mWifiNative.initialize();
374         assertNull(mWifiNative.mUnknownAkmMap);
375     }
376 
377     @After
tearDown()378     public void tearDown() {
379         validateMockitoUsage();
380         if (mSession != null) {
381             mSession.finishMocking();
382         }
383     }
384 
385     /** Mock translating an SSID */
getTranslatedSsid(WifiSsid ssid)386     private WifiSsid getTranslatedSsid(WifiSsid ssid) {
387         byte[] ssidBytes = ssid.getBytes();
388         for (int i = 0; i < ssidBytes.length; i++) {
389             ssidBytes[i]++;
390         }
391         return WifiSsid.fromBytes(ssidBytes);
392     }
393 
getMockResources()394     private MockResources getMockResources() {
395         MockResources resources = new MockResources();
396         return resources;
397     }
398 
399     /**
400      * Verifies that TxFateReport's constructor sets all of the TxFateReport fields.
401      */
402     @Test
testTxFateReportCtorSetsFields()403     public void testTxFateReportCtorSetsFields() {
404         WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
405                 WifiLoggerHal.TX_PKT_FATE_SENT,  // non-zero value
406                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
407                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
408                 FATE_REPORT_FRAME_BYTES
409         );
410         assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate);
411         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
412         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
413         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
414     }
415 
416     /**
417      * Verifies that RxFateReport's constructor sets all of the RxFateReport fields.
418      */
419     @Test
testRxFateReportCtorSetsFields()420     public void testRxFateReportCtorSetsFields() {
421         WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
422                 WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,  // non-zero value
423                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
424                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
425                 FATE_REPORT_FRAME_BYTES
426         );
427         assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate);
428         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
429         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
430         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
431     }
432 
433     /**
434      * Verifies the hashCode methods for HiddenNetwork and PnoNetwork classes
435      */
436     @Test
testHashCode()437     public void testHashCode() {
438         WifiNative.HiddenNetwork hiddenNet1 = new WifiNative.HiddenNetwork();
439         hiddenNet1.ssid = new String("sametext");
440 
441         WifiNative.HiddenNetwork hiddenNet2 = new WifiNative.HiddenNetwork();
442         hiddenNet2.ssid = new String("sametext");
443 
444         assertTrue(hiddenNet1.equals(hiddenNet2));
445         assertEquals(hiddenNet1.hashCode(), hiddenNet2.hashCode());
446 
447         WifiNative.PnoNetwork pnoNet1 = new WifiNative.PnoNetwork();
448         pnoNet1.ssid = new String("sametext");
449         pnoNet1.flags = 2;
450         pnoNet1.auth_bit_field = 4;
451         pnoNet1.frequencies = TEST_FREQUENCIES_2;
452 
453         WifiNative.PnoNetwork pnoNet2 = new WifiNative.PnoNetwork();
454         pnoNet2.ssid = new String("sametext");
455         pnoNet2.flags = 2;
456         pnoNet2.auth_bit_field = 4;
457         pnoNet2.frequencies = TEST_FREQUENCIES_2;
458 
459         assertTrue(pnoNet1.equals(pnoNet2));
460         assertEquals(pnoNet1.hashCode(), pnoNet2.hashCode());
461     }
462 
463     // Support classes for test{Tx,Rx}FateReportToString.
464     private static class FrameTypeMapping {
465         byte mTypeNumber;
466         String mExpectedTypeText;
467         String mExpectedProtocolText;
FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText)468         FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) {
469             this.mTypeNumber = typeNumber;
470             this.mExpectedTypeText = expectedTypeText;
471             this.mExpectedProtocolText = expectedProtocolText;
472         }
473     }
474     private static class FateMapping {
475         byte mFateNumber;
476         String mExpectedText;
FateMapping(byte fateNumber, String expectedText)477         FateMapping(byte fateNumber, String expectedText) {
478             this.mFateNumber = fateNumber;
479             this.mExpectedText = expectedText;
480         }
481     }
482 
483     /**
484      * Verifies that FateReport.getTableHeader() prints the right header.
485      */
486     @Test
testFateReportTableHeader()487     public void testFateReportTableHeader() {
488         final String header = WifiNative.FateReport.getTableHeader();
489         assertEquals(
490                 "\nTime usec        Walltime      Direction  Fate                              "
491                 + "Protocol      Type                     Result\n"
492                 + "---------        --------      ---------  ----                              "
493                 + "--------      ----                     ------\n", header);
494     }
495 
496     /**
497      * Verifies that TxFateReport.toTableRowString() includes the information we care about.
498      */
499     @Test
testTxFateReportToTableRowString()500     public void testTxFateReportToTableRowString() {
501         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
502         assertTrue(
503                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
504                     FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
505                             + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
506                             + "TX "  // direction
507                             + "sent "  // fate
508                             + "Ethernet "  // type
509                             + "N/A "  // protocol
510                             + "N/A"  // result
511                 )
512         );
513 
514         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
515             fateReport = new WifiNative.TxFateReport(
516                     WifiLoggerHal.TX_PKT_FATE_SENT,
517                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
518                     frameTypeMapping.mTypeNumber,
519                     FATE_REPORT_FRAME_BYTES
520             );
521             assertTrue(
522                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
523                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
524                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
525                                     + "TX "  // direction
526                                     + "sent "  // fate
527                                     + frameTypeMapping.mExpectedProtocolText + " "  // type
528                                     + "N/A "  // protocol
529                                     + "N/A"  // result
530                     )
531             );
532         }
533 
534         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
535             fateReport = new WifiNative.TxFateReport(
536                     fateMapping.mFateNumber,
537                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
538                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
539                     FATE_REPORT_FRAME_BYTES
540             );
541             assertTrue(
542                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
543                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
544                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
545                                     + "TX "  // direction
546                                     + Pattern.quote(fateMapping.mExpectedText) + " "  // fate
547                                     + "802.11 Mgmt "  // type
548                                     + "N/A "  // protocol
549                                     + "N/A"  // result
550                     )
551             );
552         }
553     }
554 
555     /**
556      * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
557      * about.
558      */
559     @Test
testTxFateReportToVerboseStringWithPiiAllowed()560     public void testTxFateReportToVerboseStringWithPiiAllowed() {
561         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
562 
563         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
564         assertTrue(verboseFateString.contains("Frame direction: TX"));
565         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
566         assertTrue(verboseFateString.contains("Frame fate: sent"));
567         assertTrue(verboseFateString.contains("Frame type: data"));
568         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
569         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
570         assertTrue(verboseFateString.contains("Frame length: 16"));
571         assertTrue(verboseFateString.contains(
572                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
573         // TODO(quiche): uncomment this, once b/27975149 is fixed.
574         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
575 
576         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
577             fateReport = new WifiNative.TxFateReport(
578                     WifiLoggerHal.TX_PKT_FATE_SENT,
579                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
580                     frameTypeMapping.mTypeNumber,
581                     FATE_REPORT_FRAME_BYTES
582             );
583             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
584             assertTrue(verboseFateString.contains("Frame type: "
585                     + frameTypeMapping.mExpectedTypeText));
586         }
587 
588         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
589             fateReport = new WifiNative.TxFateReport(
590                     fateMapping.mFateNumber,
591                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
592                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
593                     FATE_REPORT_FRAME_BYTES
594             );
595             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
596             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
597         }
598     }
599 
600     /**
601      * Verifies that RxFateReport.toTableRowString() includes the information we care about.
602      */
603     @Test
testRxFateReportToTableRowString()604     public void testRxFateReportToTableRowString() {
605         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
606         assertTrue(
607                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
608                         FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
609                                 + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
610                                 + "RX "  // direction
611                                 + Pattern.quote("firmware dropped (invalid frame) ")  // fate
612                                 + "Ethernet "  // type
613                                 + "N/A "  // protocol
614                                 + "N/A"  // result
615                 )
616         );
617 
618         // FrameTypeMappings omitted, as they're the same as for TX.
619 
620         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
621             fateReport = new WifiNative.RxFateReport(
622                     fateMapping.mFateNumber,
623                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
624                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
625                     FATE_REPORT_FRAME_BYTES
626             );
627             assertTrue(
628                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
629                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
630                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
631                                     + "RX "  // direction
632                                     + Pattern.quote(fateMapping.mExpectedText) + " " // fate
633                                     + "802.11 Mgmt "  // type
634                                     + "N/A " // protocol
635                                     + "N/A"  // result
636                     )
637             );
638         }
639     }
640 
641     /**
642      * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
643      * about.
644      */
645     @Test
testRxFateReportToVerboseStringWithPiiAllowed()646     public void testRxFateReportToVerboseStringWithPiiAllowed() {
647         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
648 
649         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
650         assertTrue(verboseFateString.contains("Frame direction: RX"));
651         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
652         assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)"));
653         assertTrue(verboseFateString.contains("Frame type: data"));
654         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
655         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
656         assertTrue(verboseFateString.contains("Frame length: 16"));
657         assertTrue(verboseFateString.contains(
658                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
659         // TODO(quiche): uncomment this, once b/27975149 is fixed.
660         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
661 
662         // FrameTypeMappings omitted, as they're the same as for TX.
663 
664         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
665             fateReport = new WifiNative.RxFateReport(
666                     fateMapping.mFateNumber,
667                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
668                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
669                     FATE_REPORT_FRAME_BYTES
670             );
671             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
672             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
673         }
674     }
675 
676     /**
677      * Verifies that startPktFateMonitoring returns false when HAL is not started.
678      */
679     @Test
testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted()680     public void testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted() {
681         assertFalse(mWifiNative.isHalStarted());
682         assertFalse(mWifiNative.startPktFateMonitoring(WIFI_IFACE_NAME));
683     }
684 
685     /**
686      * Verifies that getTxPktFates returns error when HAL is not started.
687      */
688     @Test
testGetTxPktFatesReturnsErrorWhenHalIsNotStarted()689     public void testGetTxPktFatesReturnsErrorWhenHalIsNotStarted() {
690         assertFalse(mWifiNative.isHalStarted());
691         assertEquals(0, mWifiNative.getTxPktFates(WIFI_IFACE_NAME).size());
692     }
693 
694     /**
695      * Verifies that getRxPktFates returns error when HAL is not started.
696      */
697     @Test
testGetRxPktFatesReturnsErrorWhenHalIsNotStarted()698     public void testGetRxPktFatesReturnsErrorWhenHalIsNotStarted() {
699         assertFalse(mWifiNative.isHalStarted());
700         assertEquals(0, mWifiNative.getRxPktFates(WIFI_IFACE_NAME).size());
701     }
702 
703     // TODO(quiche): Add tests for the success cases (when HAL has been started). Specifically:
704     // - testStartPktFateMonitoringCallsHalIfHalIsStarted()
705     // - testGetTxPktFatesCallsHalIfHalIsStarted()
706     // - testGetRxPktFatesCallsHalIfHalIsStarted()
707     //
708     // Adding these tests is difficult to do at the moment, because we can't mock out the HAL
709     // itself. Also, we can't mock out the native methods, because those methods are private.
710     // b/28005116.
711 
712     /** Verifies that getDriverStateDumpNative returns null when HAL is not started. */
713     @Test
testGetDriverStateDumpReturnsNullWhenHalIsNotStarted()714     public void testGetDriverStateDumpReturnsNullWhenHalIsNotStarted() {
715         assertEquals(null, mWifiNative.getDriverStateDump());
716     }
717 
718     // TODO(b/28005116): Add test for the success case of getDriverStateDump().
719 
720     /**
721      * Verifies getWifiLinkLayerStats() calls underlying WifiVendorHal.
722      *
723      */
724     @Test
testGetWifiLinkLayerStatsForClientInConnectivityMode()725     public void testGetWifiLinkLayerStatsForClientInConnectivityMode() throws Exception {
726         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
727                 mConcreteClientModeManager);
728         mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
729         mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
730         verify(mWifiVendorHal, times(2)).getWifiLinkLayerStats(eq(WIFI_IFACE_NAME));
731     }
732 
733     /**
734      * Verifies valules of ScanResultWithSameFreq in getWifiLinkLayerStats() call
735      *
736      */
737     @Test
testGetWifiLinkLayerStatsForScanResultWithSameFreq()738     public void testGetWifiLinkLayerStatsForScanResultWithSameFreq() {
739         WifiLinkLayerStats testWifiLinkLayerStats = new WifiLinkLayerStats();
740         testWifiLinkLayerStats.links = new WifiLinkLayerStats.LinkSpecificStats[2];
741         // Define 2 test WiFi links, whose frequencyMhz are 0, 1, respectively
742         for (int i = 0; i < 2; ++i) {
743             testWifiLinkLayerStats.links[i] = new WifiLinkLayerStats.LinkSpecificStats();
744             testWifiLinkLayerStats.links[i].frequencyMhz = i;
745         }
746         when(mWifiVendorHal.getWifiLinkLayerStats(WIFI_IFACE_NAME))
747                 .thenReturn(testWifiLinkLayerStats);
748 
749         // Define 6 test WiFi scan results with unique BSSID
750         // Their frequency are 0, 1, 2, 0, 1, 2, respectively
751         ScanResult[] scanResults = new ScanResult[6];
752         for (int i = 0; i < 6; i++) {
753             ScanResult scanResult = new ScanResult();
754             scanResult.BSSID = Integer.toString(i);
755             scanResult.frequency = i < 3 ? i : (i - 3);
756             // Make sure the timestamp is valid
757             scanResult.timestamp = Long.MAX_VALUE;
758             scanResults[i] = scanResult;
759         }
760         ScanData testScanData = new ScanData(0, 0,
761                 0, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults);
762         when(mWifiVendorHal.getCachedScanData(WIFI_IFACE_NAME)).thenReturn(testScanData);
763         mWifiNative.setLocationModeEnabled(true);
764 
765         WifiLinkLayerStats resultWifiLinkLayerStats =
766                 mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
767         assertEquals(2, resultWifiLinkLayerStats.links.length);
768         // WiFi link 0's frequency is 0, scan results 0 and 3 have the same frequency
769         assertEquals(2, resultWifiLinkLayerStats.links[0].scan_results_same_freq.size());
770         assertEquals("0", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(0).bssid);
771         assertEquals("3", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(1).bssid);
772         // WiFi link 1's frequency is 1, scan results 1 and 4 have the same frequency
773         assertEquals(2, resultWifiLinkLayerStats.links[1].scan_results_same_freq.size());
774         assertEquals("1", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(0).bssid);
775         assertEquals("4", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(1).bssid);
776     }
777 
778     /**
779      * Verifies client mode + scan success.
780      */
781     @Test
782     public void testClientModeScanSuccess() {
783         InOrder order = inOrder(mWificondControl, mNetdWrapper, mWifiVendorHal);
784         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
785                 mConcreteClientModeManager);
786         order.verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
787                 mScanCallbackCaptor.capture(), any());
788         order.verify(mNetdWrapper).isInterfaceUp(eq(WIFI_IFACE_NAME));
789         order.verify(mWifiVendorHal).enableLinkLayerStats(eq(WIFI_IFACE_NAME));
790 
791         mScanCallbackCaptor.getValue().onScanResultReady();
792         verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME);
793     }
794 
795     /**
796      * Verifies client mode + scan failure.
797      */
798     @Test
799     public void testClientModeScanFailure() {
800         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
801                 mConcreteClientModeManager);
802         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
803                 mScanCallbackCaptor.capture(), any());
804 
805         if (SdkLevel.isAtLeastU()) {
806             mScanCallbackCaptor.getValue().onScanFailed(WifiScanner.REASON_UNSPECIFIED);
807         } else {
808             mScanCallbackCaptor.getValue().onScanFailed();
809         }
810         verify(mWifiMonitor).broadcastScanFailedEvent(WIFI_IFACE_NAME,
811                 WifiScanner.REASON_UNSPECIFIED);
812     }
813 
814     /**
815      * Verifies client mode + PNO scan success.
816      */
817     @Test
818     public void testClientModePnoScanSuccess() {
819         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
820                 mConcreteClientModeManager);
821         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
822                 any(), mScanCallbackCaptor.capture());
823 
824         mScanCallbackCaptor.getValue().onScanResultReady();
825         verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME);
826         verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
827     }
828 
829     /**
830      * Verifies client mode + PNO scan failure.
831      */
832     @Test
833     public void testClientModePnoScanFailure() {
834         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
835                 mConcreteClientModeManager);
836         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
837                 any(), mScanCallbackCaptor.capture());
838 
839         mScanCallbackCaptor.getValue().onScanFailed();
840         ExtendedMockito.verify(() -> WifiStatsLog.write(WifiStatsLog.PNO_SCAN_STOPPED,
841                 WifiStatsLog.PNO_SCAN_STOPPED__STOP_REASON__SCAN_FAILED,
842                 0, false, false, false, false,
843                 WifiStatsLog.PNO_SCAN_STOPPED__FAILURE_CODE__WIFICOND_SCAN_FAILURE));
844     }
845 
846     /**
847      * Verifies scan mode + scan success.
848      */
849     @Test
testScanModeScanSuccess()850     public void testScanModeScanSuccess() {
851         InOrder order = inOrder(mWificondControl, mNetdWrapper, mWifiVendorHal);
852         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
853                 mConcreteClientModeManager);
854         order.verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
855                 mScanCallbackCaptor.capture(), any());
856         order.verify(mNetdWrapper).isInterfaceUp(eq(WIFI_IFACE_NAME));
857         order.verify(mWifiVendorHal).enableLinkLayerStats(eq(WIFI_IFACE_NAME));
858 
859         mScanCallbackCaptor.getValue().onScanResultReady();
860         verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME);
861     }
862 
863     /**
864      * Verifies scan mode + scan success.
865      */
866     @Test
testBridgedApModeWifiCondSetupTeardown()867     public void testBridgedApModeWifiCondSetupTeardown() {
868         String instance1 = "instance1";
869         String instance2 = "instance2";
870         when(mWifiVendorHal.getBridgedApInstances(WIFI_IFACE_NAME))
871                 .thenReturn(Arrays.asList(instance1, instance2));
872         mWifiNative.setupInterfaceForSoftApMode(null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ
873                 | SoftApConfiguration.BAND_5GHZ, true, mSoftApManager, new ArrayList<>(), false);
874         ArgumentCaptor<HalDeviceManager.InterfaceDestroyedListener> ifaceDestroyedListenerCaptor =
875                 ArgumentCaptor.forClass(HalDeviceManager.InterfaceDestroyedListener.class);
876         verify(mWifiVendorHal).createApIface(ifaceDestroyedListenerCaptor.capture(), any(),
877                 anyInt(), anyBoolean(), any(), anyList());
878         verify(mWificondControl).setupInterfaceForSoftApMode(instance1);
879 
880         when(mWifiVendorHal.getBridgedApInstances(WIFI_IFACE_NAME)).thenReturn(null);
881         ifaceDestroyedListenerCaptor.getValue().onDestroyed(WIFI_IFACE_NAME);
882 
883         verify(mWificondControl).tearDownSoftApInterface(instance1);
884     }
885 
886     /**
887      * Verifies scan mode + scan failure.
888      */
889     @Test
testScanModeScanFailure()890     public void testScanModeScanFailure() {
891         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
892                 mConcreteClientModeManager);
893         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
894                 mScanCallbackCaptor.capture(), any());
895 
896         if (SdkLevel.isAtLeastU()) {
897             mScanCallbackCaptor.getValue().onScanFailed(WifiScanner.REASON_UNSPECIFIED);
898         } else {
899             mScanCallbackCaptor.getValue().onScanFailed();
900         }
901         verify(mWifiMonitor).broadcastScanFailedEvent(eq(WIFI_IFACE_NAME),
902                 eq(WifiScanner.REASON_UNSPECIFIED));
903     }
904 
905     /**
906      * Verifies scan mode + PNO scan success.
907      */
908     @Test
testScanModePnoScanSuccess()909     public void testScanModePnoScanSuccess() {
910         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
911                 mConcreteClientModeManager);
912         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
913                 any(), mScanCallbackCaptor.capture());
914 
915         mScanCallbackCaptor.getValue().onScanResultReady();
916         verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME);
917         verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
918     }
919 
920     /**
921      * Verifies scan mode + PNO scan failure.
922      */
923     @Test
testScanModePnoScanFailure()924     public void testScanModePnoScanFailure() {
925         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
926                 mConcreteClientModeManager);
927         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
928                 any(), mScanCallbackCaptor.capture());
929 
930         mScanCallbackCaptor.getValue().onScanFailed();
931         ExtendedMockito.verify(() -> WifiStatsLog.write(WifiStatsLog.PNO_SCAN_STOPPED,
932                 WifiStatsLog.PNO_SCAN_STOPPED__STOP_REASON__SCAN_FAILED,
933                 0, false, false, false, false,
934                 WifiStatsLog.PNO_SCAN_STOPPED__FAILURE_CODE__WIFICOND_SCAN_FAILURE));
935     }
936 
937     /**
938      * Verifies starting the hal results in coex unsafe channels being updated with cached values.
939      */
940     @Test
testStartHalUpdatesCoexUnsafeChannels()941     public void testStartHalUpdatesCoexUnsafeChannels() {
942         assumeTrue(SdkLevel.isAtLeastS());
943         final List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
944         unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6));
945         unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_5_GHZ, 36));
946         final int restrictions = 0;
947         when(mCoexManager.getCoexUnsafeChannels()).thenReturn(unsafeChannels);
948         when(mCoexManager.getCoexRestrictions()).thenReturn(restrictions);
949         mWifiNative.setCoexUnsafeChannels(unsafeChannels, restrictions);
950 
951         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
952                 mConcreteClientModeManager);
953         verify(mWifiVendorHal, times(2)).setCoexUnsafeChannels(unsafeChannels, restrictions);
954 
955         mWifiNative.teardownAllInterfaces();
956         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
957                 mConcreteClientModeManager);
958         verify(mWifiVendorHal, times(3)).setCoexUnsafeChannels(unsafeChannels, restrictions);
959 
960         mWifiNative.teardownAllInterfaces();
961         mWifiNative.setupInterfaceForSoftApMode(null, TEST_WORKSOURCE, WIFI_BAND_24_GHZ, false,
962                 mSoftApManager, new ArrayList<>(), false);
963         verify(mWifiVendorHal, times(4)).setCoexUnsafeChannels(unsafeChannels, restrictions);
964     }
965 
966     /**
967      * Verifies that signalPoll() calls underlying WificondControl.
968      */
969     @Test
testSignalPoll()970     public void testSignalPoll() throws Exception {
971         when(mWificondControl.signalPoll(WIFI_IFACE_NAME))
972                 .thenReturn(SIGNAL_POLL_RESULT);
973         when(mStaIfaceHal.getSignalPollResults(WIFI_IFACE_NAME)).thenReturn(null);
974 
975         WifiSignalPollResults pollResults = mWifiNative.signalPoll(WIFI_IFACE_NAME);
976         assertEquals(SIGNAL_POLL_RESULT.currentRssiDbm, pollResults.getRssi());
977         assertEquals(SIGNAL_POLL_RESULT.txBitrateMbps, pollResults.getTxLinkSpeed());
978         assertEquals(SIGNAL_POLL_RESULT.associationFrequencyMHz,
979                 pollResults.getFrequency());
980         assertEquals(SIGNAL_POLL_RESULT.rxBitrateMbps, pollResults.getRxLinkSpeed());
981 
982         verify(mWificondControl).signalPoll(WIFI_IFACE_NAME);
983     }
984 
985     /**
986      * Verifies that scan() calls underlying WificondControl.
987      */
988     @Test
testScan()989     public void testScan() throws Exception {
990         // This test will NOT run if the device has SDK level S or later
991         assumeFalse(SdkLevel.isAtLeastS());
992         mWifiNative.scan(WIFI_IFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, SCAN_FREQ_SET,
993                 SCAN_HIDDEN_NETWORK_SSID_SET, false, null);
994         ArgumentCaptor<List<byte[]>> ssidSetCaptor = ArgumentCaptor.forClass(List.class);
995         verify(mWificondControl).startScan(
996                 eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY),
997                 eq(SCAN_FREQ_SET), ssidSetCaptor.capture());
998         List<byte[]> ssidSet = ssidSetCaptor.getValue();
999         assertArrayEquals(ssidSet.toArray(), SCAN_HIDDEN_NETWORK_BYTE_SSID_SET.toArray());
1000     }
1001 
1002     /**
1003      * Verifies that scan() calls the new startScan API with a Bundle when the Sdk level
1004      * is S or above.
1005      */
1006     @Test
testScanWithBundle()1007     public void testScanWithBundle() throws Exception {
1008         assumeTrue(SdkLevel.isAtLeastU());
1009         byte[] vendorIes =
1010                 new byte[]{(byte) 0xdd, 0x7, 0x00, 0x50, (byte) 0xf2, 0x08, 0x11, 0x22, 0x33,
1011                         (byte) 0xdd, 0x7, 0x00, 0x50, (byte) 0xf2, 0x08, 0x44, 0x55, 0x66};
1012         mWifiNative.scan(WIFI_IFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, SCAN_FREQ_SET,
1013                 SCAN_HIDDEN_NETWORK_SSID_SET, true, vendorIes);
1014         ArgumentCaptor<List<byte[]>> ssidSetCaptor = ArgumentCaptor.forClass(List.class);
1015         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
1016         if (SdkLevel.isAtLeastU()) {
1017             verify(mWificondControl).startScan2(
1018                     eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY),
1019                     eq(SCAN_FREQ_SET), ssidSetCaptor.capture(), bundleCaptor.capture());
1020         } else {
1021             verify(mWificondControl).startScan(
1022                     eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY),
1023                     eq(SCAN_FREQ_SET), ssidSetCaptor.capture(), bundleCaptor.capture());
1024         }
1025         List<byte[]> ssidSet = ssidSetCaptor.getValue();
1026         assertArrayEquals(ssidSet.toArray(), SCAN_HIDDEN_NETWORK_BYTE_SSID_SET.toArray());
1027         Bundle bundle = bundleCaptor.getValue();
1028         assertTrue(bundle.getBoolean(WifiNl80211Manager.SCANNING_PARAM_ENABLE_6GHZ_RNR));
1029         assertArrayEquals(vendorIes,
1030                 bundle.getByteArray(WifiNl80211Manager.EXTRA_SCANNING_PARAM_VENDOR_IES));
1031     }
1032 
1033     /**
1034      * Verifies that startPnoscan() calls underlying WificondControl.
1035      */
1036     @Test
testStartPnoScanOnRequestProcessed()1037     public void testStartPnoScanOnRequestProcessed() throws Exception {
1038         mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS);
1039 
1040         ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor =
1041                 ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class);
1042         verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME),
1043                 eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture());
1044         captor.getValue().onPnoRequestSucceeded();
1045         verify(mWifiMetrics).incrementPnoScanStartAttemptCount();
1046     }
1047 
1048     /**
1049      * Verifies that startPnoscan() calls underlying WificondControl.
1050      */
1051     @Test
testStartPnoScanOnRequestFailed()1052     public void testStartPnoScanOnRequestFailed() throws Exception {
1053         mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS);
1054 
1055         ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor =
1056                 ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class);
1057         verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME),
1058                 eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture());
1059         captor.getValue().onPnoRequestFailed();
1060         ExtendedMockito.verify(() -> WifiStatsLog.write(WifiStatsLog.PNO_SCAN_STOPPED,
1061                 WifiStatsLog.PNO_SCAN_STOPPED__STOP_REASON__SCAN_FAILED,
1062                 0, false, false, false, false,
1063                 WifiStatsLog.PNO_SCAN_STOPPED__FAILURE_CODE__WIFICOND_REQUEST_FAILURE));
1064     }
1065 
1066     /**
1067      * Verifies that stopPnoscan() calls underlying WificondControl.
1068      */
1069     @Test
testStopPnoScan()1070     public void testStopPnoScan() throws Exception {
1071         mWifiNative.stopPnoScan(WIFI_IFACE_NAME);
1072         verify(mWificondControl).stopPnoScan(WIFI_IFACE_NAME);
1073     }
1074 
1075     /**
1076      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
1077      */
1078     @Test
testGetScanResults()1079     public void testGetScanResults() {
1080         // Mock the returned array of NativeScanResult.
1081         List<NativeScanResult> mockScanResults = Arrays.asList(MOCK_NATIVE_SCAN_RESULT);
1082         when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults);
1083 
1084         ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME);
1085         assertEquals(mockScanResults.size(), returnedScanResults.size());
1086         // Since NativeScanResult is organized differently from ScanResult, this only checks
1087         // a few fields.
1088         for (int i = 0; i < mockScanResults.size(); i++) {
1089             assertEquals(getTranslatedSsid(WifiSsid.fromBytes(mockScanResults.get(i).getSsid())),
1090                     returnedScanResults.get(i).getScanResult().getWifiSsid());
1091             assertEquals(mockScanResults.get(i).getFrequencyMhz(),
1092                     returnedScanResults.get(i).getScanResult().frequency);
1093             assertEquals(mockScanResults.get(i).getTsf(),
1094                     returnedScanResults.get(i).getScanResult().timestamp);
1095         }
1096     }
1097 
1098     /**
1099      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
1100      */
1101     @Test
testGetScanResultsWithInvalidSsidLength()1102     public void testGetScanResultsWithInvalidSsidLength() {
1103         // Mock the returned array of NativeScanResult.
1104         List<NativeScanResult> mockScanResults = Arrays.asList(createMockNativeScanResult());
1105         for (NativeScanResult scanResult : mockScanResults) {
1106             scanResult.ssid = Arrays.copyOf(scanResult.ssid, 33);
1107         }
1108         when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults);
1109 
1110         assertEquals(0, mWifiNative.getScanResults(WIFI_IFACE_NAME).size());
1111     }
1112 
1113     /**
1114      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
1115      * when there is radio chain info.
1116      */
1117     @Test
testGetScanResultsWithRadioChainInfo()1118     public void testGetScanResultsWithRadioChainInfo() throws Exception {
1119         // Mock the returned array of NativeScanResult.
1120         NativeScanResult nativeScanResult = createMockNativeScanResult();
1121         // Add radio chain info
1122         List<RadioChainInfo> nativeRadioChainInfos = Arrays.asList(
1123                 MOCK_NATIVE_RADIO_CHAIN_INFO_1, MOCK_NATIVE_RADIO_CHAIN_INFO_2);
1124         nativeScanResult.radioChainInfos = nativeRadioChainInfos;
1125         List<NativeScanResult> mockScanResults = Arrays.asList(nativeScanResult);
1126 
1127         when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults);
1128 
1129         ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME);
1130         assertEquals(mockScanResults.size(), returnedScanResults.size());
1131         // Since NativeScanResult is organized differently from ScanResult, this only checks
1132         // a few fields.
1133         for (int i = 0; i < mockScanResults.size(); i++) {
1134             assertEquals(getTranslatedSsid(WifiSsid.fromBytes(mockScanResults.get(i).getSsid())),
1135                     returnedScanResults.get(i).getScanResult().getWifiSsid());
1136             assertEquals(mockScanResults.get(i).getFrequencyMhz(),
1137                     returnedScanResults.get(i).getScanResult().frequency);
1138             assertEquals(mockScanResults.get(i).getTsf(),
1139                     returnedScanResults.get(i).getScanResult().timestamp);
1140             ScanResult.RadioChainInfo[] scanRcis = returnedScanResults.get(
1141                     i).getScanResult().radioChainInfos;
1142             assertEquals(nativeRadioChainInfos.size(), scanRcis.length);
1143             for (int j = 0; j < scanRcis.length; ++j) {
1144                 assertEquals(nativeRadioChainInfos.get(j).getChainId(), scanRcis[j].id);
1145                 assertEquals(nativeRadioChainInfos.get(j).getLevelDbm(), scanRcis[j].level);
1146             }
1147         }
1148     }
1149 
1150     /**
1151      * Verifies that connectToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal.
1152      */
1153     @Test
testConnectToNetwork()1154     public void testConnectToNetwork() throws Exception {
1155         WifiConfiguration config = mock(WifiConfiguration.class);
1156         mWifiNative.connectToNetwork(WIFI_IFACE_NAME, config);
1157         // connectToNetwork() should abort ongoing scan before connection.
1158         verify(mWificondControl).abortScan(WIFI_IFACE_NAME);
1159         verify(mStaIfaceHal).connectToNetwork(WIFI_IFACE_NAME, config);
1160     }
1161 
1162     /**
1163      * Verifies that roamToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal.
1164      */
1165     @Test
testRoamToNetwork()1166     public void testRoamToNetwork() throws Exception {
1167         WifiConfiguration config = mock(WifiConfiguration.class);
1168         mWifiNative.roamToNetwork(WIFI_IFACE_NAME, config);
1169         // roamToNetwork() should abort ongoing scan before connection.
1170         verify(mWificondControl).abortScan(WIFI_IFACE_NAME);
1171         verify(mStaIfaceHal).roamToNetwork(WIFI_IFACE_NAME, config);
1172     }
1173 
1174     /**
1175      * Verifies that removeIfaceInstanceFromBridgedApIface() calls underlying WifiVendorHal.
1176      */
1177     @Test
testRemoveIfaceInstanceFromBridgedApIface()1178     public void testRemoveIfaceInstanceFromBridgedApIface() throws Exception {
1179         mWifiNative.removeIfaceInstanceFromBridgedApIface(
1180                 "br_" + WIFI_IFACE_NAME, WIFI_IFACE_NAME);
1181         verify(mWifiVendorHal).removeIfaceInstanceFromBridgedApIface(
1182                 "br_" + WIFI_IFACE_NAME, WIFI_IFACE_NAME);
1183     }
1184 
1185     /**
1186      * Verifies that setMacAddress() calls underlying WifiVendorHal.
1187      */
1188     @Test
testStaSetMacAddress()1189     public void testStaSetMacAddress() throws Exception {
1190         mWifiNative.setStaMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1191         verify(mStaIfaceHal).disconnect(WIFI_IFACE_NAME);
1192         verify(mWifiVendorHal).setStaMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1193     }
1194 
1195     /**
1196      * Verifies that setMacAddress() calls underlying WifiVendorHal.
1197      */
1198     @Test
testApSetMacAddress()1199     public void testApSetMacAddress() throws Exception {
1200         mWifiNative.setApMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1201         verify(mWifiVendorHal).setApMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1202     }
1203 
1204     /**
1205      * Verifies that resetApMacToFactoryMacAddress() calls underlying WifiVendorHal.
1206      */
1207     @Test
testResetApMacToFactoryMacAddress()1208     public void testResetApMacToFactoryMacAddress() throws Exception {
1209         mWifiNative.resetApMacToFactoryMacAddress(WIFI_IFACE_NAME);
1210         verify(mWifiVendorHal).resetApMacToFactoryMacAddress(WIFI_IFACE_NAME);
1211     }
1212 
1213     /**
1214      * Verifies that setCoexUnsafeChannels() calls underlying WifiVendorHal.
1215      */
1216     @Test
testSetCoexUnsafeChannels()1217     public void testSetCoexUnsafeChannels() throws Exception {
1218         assumeTrue(SdkLevel.isAtLeastS());
1219         mWifiNative.setCoexUnsafeChannels(Collections.emptyList(), 0);
1220         verify(mWifiVendorHal).setCoexUnsafeChannels(Collections.emptyList(), 0);
1221     }
1222 
1223     /**
1224      * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal.
1225      */
1226     @Test
testIsApSetMacAddressSupported()1227     public void testIsApSetMacAddressSupported() throws Exception {
1228         mWifiNative.isApSetMacAddressSupported(WIFI_IFACE_NAME);
1229         verify(mWifiVendorHal).isApSetMacAddressSupported(WIFI_IFACE_NAME);
1230     }
1231 
1232     /**
1233      * Test that selectTxPowerScenario() calls into WifiVendorHal (success case)
1234      */
1235     @Test
testSelectTxPowerScenario_success()1236     public void testSelectTxPowerScenario_success() throws Exception {
1237         when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(true);
1238         SarInfo sarInfo = new SarInfo();
1239         assertTrue(mWifiNative.selectTxPowerScenario(sarInfo));
1240         verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
1241     }
1242 
1243     /**
1244      * Test that selectTxPowerScenario() calls into WifiVendorHal (failure case)
1245      */
1246     @Test
testSelectTxPowerScenario_failure()1247     public void testSelectTxPowerScenario_failure() throws Exception {
1248         when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false);
1249         SarInfo sarInfo = new SarInfo();
1250         assertFalse(mWifiNative.selectTxPowerScenario(sarInfo));
1251         verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
1252     }
1253 
1254     /**
1255      * Test that setPowerSave() with true, results in calling into SupplicantStaIfaceHal
1256      */
1257     @Test
testSetPowerSaveTrue()1258     public void testSetPowerSaveTrue() throws Exception {
1259         mWifiNative.setPowerSave(WIFI_IFACE_NAME, true);
1260         verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, true);
1261     }
1262 
1263     /**
1264      * Test that setPowerSave() with false, results in calling into SupplicantStaIfaceHal
1265      */
1266     @Test
testSetPowerSaveFalse()1267     public void testSetPowerSaveFalse() throws Exception {
1268         mWifiNative.setPowerSave(WIFI_IFACE_NAME, false);
1269         verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, false);
1270     }
1271 
1272     /**
1273      * Test that setLowLatencyMode() with true, results in calling into WifiVendorHal
1274      */
1275     @Test
testLowLatencyModeTrue()1276     public void testLowLatencyModeTrue() throws Exception {
1277         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true);
1278         assertTrue(mWifiNative.setLowLatencyMode(true));
1279         verify(mWifiVendorHal).setLowLatencyMode(true);
1280     }
1281 
1282     /**
1283      * Test that setLowLatencyMode() with false, results in calling into WifiVendorHal
1284      */
1285     @Test
testLowLatencyModeFalse()1286     public void testLowLatencyModeFalse() throws Exception {
1287         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true);
1288         assertTrue(mWifiNative.setLowLatencyMode(false));
1289         verify(mWifiVendorHal).setLowLatencyMode(false);
1290     }
1291 
1292     /**
1293      * Test that setLowLatencyMode() returns with failure when WifiVendorHal fails.
1294      */
1295     @Test
testSetLowLatencyModeFail()1296     public void testSetLowLatencyModeFail() throws Exception {
1297         final boolean lowLatencyMode = true;
1298         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(false);
1299         assertFalse(mWifiNative.setLowLatencyMode(lowLatencyMode));
1300         verify(mWifiVendorHal).setLowLatencyMode(lowLatencyMode);
1301     }
1302 
1303     @Test
testStaGetFactoryMacAddress()1304     public void testStaGetFactoryMacAddress() throws Exception {
1305         when(mWifiVendorHal.getStaFactoryMacAddress(any()))
1306                 .thenReturn(MacAddress.BROADCAST_ADDRESS);
1307         assertNotNull(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME));
1308         verify(mWifiVendorHal).getStaFactoryMacAddress(any());
1309     }
1310 
1311 
1312     @Test
testGetApFactoryMacAddress()1313     public void testGetApFactoryMacAddress() throws Exception {
1314         when(mWifiVendorHal.getApFactoryMacAddress(any())).thenReturn(MacAddress.BROADCAST_ADDRESS);
1315         assertNotNull(mWifiNative.getApFactoryMacAddress(WIFI_IFACE_NAME));
1316         verify(mWifiVendorHal).getApFactoryMacAddress(any());
1317     }
1318 
1319     /**
1320      * Test that flushRingBufferData(), results in calling into WifiVendorHal
1321      */
1322     @Test
testFlushRingBufferDataTrue()1323     public void testFlushRingBufferDataTrue() throws Exception {
1324         when(mWifiVendorHal.flushRingBufferData()).thenReturn(true);
1325         assertTrue(mWifiNative.flushRingBufferData());
1326         verify(mWifiVendorHal).flushRingBufferData();
1327     }
1328 
1329     /**
1330      * Tests that WifiNative#sendMgmtFrame() calls WificondControl#sendMgmtFrame()
1331      */
1332     @Test
testSendMgmtFrame()1333     public void testSendMgmtFrame() {
1334         mWifiNative.sendMgmtFrame(WIFI_IFACE_NAME, FATE_REPORT_FRAME_BYTES,
1335                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1336 
1337         verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME),
1338                 AdditionalMatchers.aryEq(FATE_REPORT_FRAME_BYTES), eq(TEST_MCS_RATE),
1339                 any(), eq(mSendMgmtFrameCallback));
1340     }
1341 
1342     /**
1343      * Tests that probeLink() generates the correct frame and calls WificondControl#sendMgmtFrame().
1344      */
1345     @Test
testProbeLinkSuccess()1346     public void testProbeLinkSuccess() {
1347         byte[] expectedFrame = {
1348                 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
1349                 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
1350                 (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
1351                 0x00, 0x00
1352         };
1353 
1354         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR);
1355 
1356         when(mRandom.nextInt()).thenReturn(TEST_SEQUENCE_NUM);
1357 
1358         mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR),
1359                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1360 
1361         verify(mSendMgmtFrameCallback, never()).onFailure(anyInt());
1362         verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME),
1363                 AdditionalMatchers.aryEq(expectedFrame), eq(TEST_MCS_RATE),
1364                 any(), eq(mSendMgmtFrameCallback));
1365     }
1366 
1367     /**
1368      * Tests that probeLink() triggers the failure callback when it cannot get the sender MAC
1369      * address.
1370      */
1371     @Test
testProbeLinkFailureCannotGetSenderMac()1372     public void testProbeLinkFailureCannotGetSenderMac() {
1373         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
1374 
1375         mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR),
1376                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1377 
1378         verify(mSendMgmtFrameCallback).onFailure(
1379                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1380         verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any());
1381     }
1382 
1383     /**
1384      * Tests that probeLink() triggers the failure callback when it cannot get the BSSID.
1385      */
1386     @Test
testProbeLinkFailureCannotGetBssid()1387     public void testProbeLinkFailureCannotGetBssid() {
1388         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR);
1389 
1390         mWifiNative.probeLink(WIFI_IFACE_NAME, null, mSendMgmtFrameCallback, TEST_MCS_RATE);
1391 
1392         verify(mSendMgmtFrameCallback).onFailure(
1393                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1394         verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any());
1395     }
1396 
1397     /**
1398      * Tests that WifiNative#addHlpReq() calls
1399      * SupplicantStaIfaceHal#addHlpReq()
1400      */
1401     @Test
testaddHlpReq()1402     public void testaddHlpReq() {
1403         byte[] hlpPacket = {
1404                 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
1405                 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
1406                 (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
1407                 0x00, 0x00
1408         };
1409         mWifiNative.addHlpReq(WIFI_IFACE_NAME, TEST_MAC_ADDRESS, hlpPacket);
1410 
1411         verify(mStaIfaceHal).addHlpReq(eq(WIFI_IFACE_NAME),
1412                 eq(TEST_MAC_ADDRESS.toByteArray()), eq(hlpPacket));
1413     }
1414 
1415     /**
1416      * Tests that WifiNative#flushAllHlp() calls
1417      * SupplicantStaIfaceHal#flushAllHlp()
1418      */
1419     @Test
testflushAllHlp()1420     public void testflushAllHlp() {
1421         mWifiNative.flushAllHlp(WIFI_IFACE_NAME);
1422 
1423         verify(mStaIfaceHal).flushAllHlp(eq(WIFI_IFACE_NAME));
1424     }
1425 
1426     @Test
testIsItPossibleToCreateIface()1427     public void testIsItPossibleToCreateIface() {
1428         // HAL not started
1429         when(mWifiVendorHal.isHalStarted()).thenReturn(false);
1430         // Using any() here since SparseArray doesn't support Object.equals().
1431         when(mWifiVendorHal.canDeviceSupportCreateTypeCombo(any())).thenReturn(true);
1432         when(mWifiVendorHal.isItPossibleToCreateStaIface(any())).thenReturn(false);
1433         assertTrue(mWifiNative.isItPossibleToCreateStaIface(new WorkSource()));
1434 
1435         when(mWifiVendorHal.isItPossibleToCreateApIface(any())).thenReturn(false);
1436         assertTrue(mWifiNative.isItPossibleToCreateApIface(new WorkSource()));
1437 
1438         when(mWifiVendorHal.isItPossibleToCreateBridgedApIface(any())).thenReturn(false);
1439         assertTrue(mWifiNative.isItPossibleToCreateBridgedApIface(new WorkSource()));
1440 
1441         // HAL started
1442         when(mWifiVendorHal.isHalStarted()).thenReturn(true);
1443         when(mWifiVendorHal.isItPossibleToCreateStaIface(any())).thenReturn(true);
1444         assertTrue(mWifiNative.isItPossibleToCreateStaIface(new WorkSource()));
1445 
1446         when(mWifiVendorHal.isItPossibleToCreateApIface(any())).thenReturn(true);
1447         assertTrue(mWifiNative.isItPossibleToCreateApIface(new WorkSource()));
1448 
1449         when(mWifiVendorHal.isItPossibleToCreateBridgedApIface(any())).thenReturn(true);
1450         assertTrue(mWifiNative.isItPossibleToCreateBridgedApIface(new WorkSource()));
1451     }
1452 
1453     @Test
testReplaceStaIfaceRequestorWs()1454     public void testReplaceStaIfaceRequestorWs() {
1455         assertEquals(WIFI_IFACE_NAME,
1456                 mWifiNative.setupInterfaceForClientInScanMode(
1457                         mInterfaceCallback, TEST_WORKSOURCE, mConcreteClientModeManager));
1458         when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE2))
1459                 .thenReturn(true);
1460 
1461         assertTrue(mWifiNative.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE2));
1462         verify(mWifiVendorHal).replaceStaIfaceRequestorWs(
1463                 eq(WIFI_IFACE_NAME), same(TEST_WORKSOURCE2));
1464     }
1465 
1466     /**
1467      * Verifies that updateLinkedNetworks() calls underlying SupplicantStaIfaceHal.
1468      */
1469     @Test
testUpdateLinkedNetworks()1470     public void testUpdateLinkedNetworks() {
1471         when(mStaIfaceHal.updateLinkedNetworks(any(), anyInt(), any())).thenReturn(true);
1472 
1473         assertTrue(mWifiNative.updateLinkedNetworks(WIFI_IFACE_NAME, 0, null));
1474         verify(mStaIfaceHal).updateLinkedNetworks(WIFI_IFACE_NAME, 0, null);
1475     }
1476 
1477     /**
1478      * Verifies that getEapAnonymousIdentity() works as expected.
1479      */
1480     @Test
testGetEapAnonymousIdentity()1481     public void testGetEapAnonymousIdentity() {
1482         // Verify the empty use case
1483         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1484                 .thenReturn("");
1485         assertTrue(TextUtils.isEmpty(mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME)));
1486 
1487         // Verify with an anonymous identity
1488         final String anonymousId = "[email protected]";
1489         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1490                 .thenReturn(anonymousId);
1491         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1492 
1493         // Verify with a pseudonym identity
1494         final String pseudonymId = "[email protected]";
1495         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1496                 .thenReturn(pseudonymId);
1497         assertEquals(pseudonymId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1498 
1499         // Verify that decorated anonymous identity is truncated
1500         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1501                 .thenReturn("otherrealm.example.net!" + anonymousId);
1502         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1503 
1504         // Verify that recursive decorated anonymous identity is truncated
1505         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1506                 .thenReturn("proxyrealm.example.com!otherrealm.example.net!" + anonymousId);
1507         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1508 
1509         // Verify an invalid decoration with no identity use cases
1510         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1511                 .thenReturn("otherrealm.example.net!");
1512         assertNull(mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1513     }
1514 
1515 
1516     @Test
testCountryCodeChangedListener()1517     public void testCountryCodeChangedListener() {
1518         assumeTrue(SdkLevel.isAtLeastS());
1519         final String testCountryCode = "US";
1520         ArgumentCaptor<WifiNl80211Manager.CountryCodeChangedListener>
1521                 mCountryCodeChangedListenerCaptor = ArgumentCaptor.forClass(
1522                 WifiNl80211Manager.CountryCodeChangedListener.class);
1523         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1524         verify(mWificondControl).registerCountryCodeChangedListener(any(),
1525                 mCountryCodeChangedListenerCaptor.capture());
1526         mCountryCodeChangedListenerCaptor.getValue().onCountryCodeChanged(testCountryCode);
1527         verify(mWifiCountryCodeChangeListener).onDriverCountryCodeChanged(testCountryCode);
1528     }
1529 
1530     @Test
testSetStaCountryCodeSuccessful()1531     public void testSetStaCountryCodeSuccessful() {
1532         when(mStaIfaceHal.setCountryCode(any(), any())).thenReturn(true);
1533         final String testCountryCode = "US";
1534         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1535         mWifiNative.setStaCountryCode(WIFI_IFACE_NAME, testCountryCode);
1536         verify(mStaIfaceHal).setCountryCode(WIFI_IFACE_NAME, testCountryCode);
1537         if (SdkLevel.isAtLeastS()) {
1538             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1539         }
1540     }
1541 
1542     @Test
testSetStaCountryCodeFailure()1543     public void testSetStaCountryCodeFailure() {
1544         when(mStaIfaceHal.setCountryCode(any(), any())).thenReturn(false);
1545         final String testCountryCode = "US";
1546         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1547         mWifiNative.setStaCountryCode(WIFI_IFACE_NAME, testCountryCode);
1548         verify(mStaIfaceHal).setCountryCode(WIFI_IFACE_NAME, testCountryCode);
1549         if (SdkLevel.isAtLeastS()) {
1550             verify(mWifiCountryCodeChangeListener, never())
1551                     .onSetCountryCodeSucceeded(testCountryCode);
1552         }
1553     }
1554 
1555     /**
1556      * Verifies setEapAnonymousIdentity() sunny case.
1557      */
1558     @Test
testSetEapAnonymousIdentitySuccess()1559     public void testSetEapAnonymousIdentitySuccess() throws Exception {
1560         when(mStaIfaceHal.setEapAnonymousIdentity(any(), any(), anyBoolean())).thenReturn(true);
1561         final String anonymousIdentity = "[email protected]";
1562         assertTrue(mWifiNative.setEapAnonymousIdentity(WIFI_IFACE_NAME, anonymousIdentity, true));
1563         verify(mStaIfaceHal).setEapAnonymousIdentity(eq(WIFI_IFACE_NAME),
1564                 eq(anonymousIdentity), eq(true));
1565     }
1566 
1567     /**
1568      * Verifies setEapAnonymousIdentity() sunny case when native service is
1569      * not updated.
1570      */
1571     @Test
testSetEapAnonymousIdentitySuccessWithNotUpdateToNativeService()1572     public void testSetEapAnonymousIdentitySuccessWithNotUpdateToNativeService() throws Exception {
1573         when(mStaIfaceHal.setEapAnonymousIdentity(any(), any(), anyBoolean())).thenReturn(true);
1574         final String anonymousIdentity = "[email protected]";
1575         assertTrue(mWifiNative.setEapAnonymousIdentity(WIFI_IFACE_NAME, anonymousIdentity, false));
1576         verify(mStaIfaceHal).setEapAnonymousIdentity(eq(WIFI_IFACE_NAME),
1577                 eq(anonymousIdentity), eq(false));
1578     }
1579 
1580     /**
1581      * Verifies that setEapAnonymousIdentity() fails with null anonymous identity.
1582      */
1583     @Test
testSetEapAnonymousIdentityFailureWithNullString()1584     public void testSetEapAnonymousIdentityFailureWithNullString() throws Exception {
1585         when(mStaIfaceHal.setEapAnonymousIdentity(any(), any(), anyBoolean())).thenReturn(true);
1586         assertFalse(mWifiNative.setEapAnonymousIdentity(WIFI_IFACE_NAME, null, true));
1587         verify(mStaIfaceHal, never()).setEapAnonymousIdentity(any(), any(), anyBoolean());
1588     }
1589 
1590     @Test
testSetApCountryCodeSuccessful()1591     public void testSetApCountryCodeSuccessful() {
1592         when(mWifiVendorHal.setApCountryCode(any(), any())).thenReturn(true);
1593         final String testCountryCode = "US";
1594         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1595         mWifiNative.setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1596         verify(mWifiVendorHal).setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1597         if (SdkLevel.isAtLeastS()) {
1598             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1599         }
1600     }
1601 
1602     @Test
testSetApCountryCodeFailure()1603     public void testSetApCountryCodeFailure() {
1604         when(mWifiVendorHal.setApCountryCode(any(), any())).thenReturn(false);
1605         final String testCountryCode = "US";
1606         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1607         mWifiNative.setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1608         verify(mWifiVendorHal).setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1609         if (SdkLevel.isAtLeastS()) {
1610             verify(mWifiCountryCodeChangeListener, never())
1611                     .onSetCountryCodeSucceeded(testCountryCode);
1612         }
1613     }
1614 
1615     @Test
testSetChipCountryCodeSuccessful()1616     public void testSetChipCountryCodeSuccessful() {
1617         when(mWifiVendorHal.setChipCountryCode(any())).thenReturn(true);
1618         final String testCountryCode = "US";
1619         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1620         mWifiNative.setChipCountryCode(testCountryCode);
1621         verify(mWifiVendorHal).setChipCountryCode(testCountryCode);
1622         if (SdkLevel.isAtLeastS()) {
1623             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1624         }
1625     }
1626 
1627     @Test
testSetChipCountryCodeFailure()1628     public void testSetChipCountryCodeFailure() {
1629         when(mWifiVendorHal.setChipCountryCode(any())).thenReturn(false);
1630         final String testCountryCode = "US";
1631         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1632         mWifiNative.setChipCountryCode(testCountryCode);
1633         verify(mWifiVendorHal).setChipCountryCode(testCountryCode);
1634         if (SdkLevel.isAtLeastS()) {
1635             verify(mWifiCountryCodeChangeListener, never())
1636                 .onSetCountryCodeSucceeded(testCountryCode);
1637         }
1638     }
1639 
1640     /**
1641      * Tests notifyWifiCondCountryCodeChanged
1642      */
1643     @Test
testNotifyWifiCondCountryCodeChanged()1644     public void testNotifyWifiCondCountryCodeChanged() throws Exception {
1645         assumeTrue(SdkLevel.isAtLeastT());
1646         String testCountryCode = "US";
1647         mWifiNative.countryCodeChanged(testCountryCode);
1648         verify(mWificondControl).notifyCountryCodeChanged(testCountryCode);
1649     }
1650 
1651     /**
1652      * Tests that getSupportedFeatureSet() guaranteed to include the feature set stored in config
1653      * store even when interface doesn't exist. If both legacy and extended features are stored in
1654      * the config store, then the extended features should be returned.
1655      */
1656     @Test
testGetExtendedFeaturesWhenInterfaceDoesntExist()1657     public void testGetExtendedFeaturesWhenInterfaceDoesntExist() throws Exception {
1658         long legacyFeatures = 0x321;
1659         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES)))
1660                 .thenReturn(legacyFeatures);
1661         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
1662                 .thenReturn(WIFI_TEST_FEATURE.toLongArray());
1663         BitSet featureSet = mWifiNative.getSupportedFeatureSet(null);
1664         assertTrue(featureSet.equals(WIFI_TEST_FEATURE));
1665     }
1666 
1667     /**
1668      * Tests that getSupportedFeatureSet() guaranteed to include the feature set stored in config
1669      * store even when interface doesn't exist. If only legacy features are stored in the
1670      * config store, then they should be returned.
1671      */
1672     @Test
testGetLegacyFeaturesWhenInterfaceDoesntExist()1673     public void testGetLegacyFeaturesWhenInterfaceDoesntExist() throws Exception {
1674         long legacyFeatures = bitsetToLong(WIFI_TEST_FEATURE);
1675         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES)))
1676                 .thenReturn(legacyFeatures);
1677         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
1678                 .thenReturn(new long[0]); // no extended features
1679         BitSet featureSet = mWifiNative.getSupportedFeatureSet(null);
1680         assertTrue(featureSet.equals(WIFI_TEST_FEATURE));
1681     }
1682 
1683     /**
1684      * Verifies that getSupportedBandsForSta() calls underlying vendor HAL.
1685      */
1686     @Test
testGetSupportedBandsFromHal()1687     public void testGetSupportedBandsFromHal() throws Exception {
1688         List<WifiAvailableChannel> usableChannelList = new ArrayList<>();
1689         usableChannelList.add(new WifiAvailableChannel(2412, WifiAvailableChannel.OP_MODE_STA,
1690                 ScanResult.CHANNEL_WIDTH_20MHZ));
1691         usableChannelList.add(new WifiAvailableChannel(5160, WifiAvailableChannel.OP_MODE_STA,
1692                 ScanResult.CHANNEL_WIDTH_40MHZ));
1693         when(mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ,
1694                 WifiAvailableChannel.OP_MODE_STA,
1695                 WifiAvailableChannel.FILTER_REGULATORY)).thenReturn(usableChannelList);
1696         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1697                 mConcreteClientModeManager);
1698         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1699         assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME));
1700     }
1701 
1702     /**
1703      * Verifies that getSupportedBandsForStaFromWifiCond() calls underlying wificond.
1704      */
1705     @Test
testGetSupportedBands()1706     public void testGetSupportedBands() throws Exception {
1707         when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ)).thenReturn(
1708                 new int[]{2412});
1709         when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ)).thenReturn(
1710                 new int[]{5160});
1711         when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn(
1712                 new int[0]);
1713         when(mWificondControl.getChannelsMhzForBand(WifiScanner.WIFI_BAND_60_GHZ)).thenReturn(
1714                 new int[0]);
1715         when(mWifiVendorHal.getUsableChannels(WifiScanner.WIFI_BAND_24_5_WITH_DFS_6_60_GHZ,
1716                 WifiAvailableChannel.OP_MODE_STA,
1717                 WifiAvailableChannel.FILTER_REGULATORY)).thenReturn(null);
1718         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1719                 mConcreteClientModeManager);
1720         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1721         verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ);
1722         verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ);
1723         assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME));
1724     }
1725 
1726     /**
1727      * Verifies that isSoftApInstanceDiedHandlerSupported() calls underlying HostapdHal.
1728      */
1729     @Test
testIsSoftApInstanceDiedHandlerSupported()1730     public void testIsSoftApInstanceDiedHandlerSupported() throws Exception {
1731         mWifiNative.isSoftApInstanceDiedHandlerSupported();
1732         verify(mHostapdHal).isSoftApInstanceDiedHandlerSupported();
1733     }
1734 
1735     @Test
testGetCachedScanResultsLocationDisabledOrInvalidTimestamp()1736     public void testGetCachedScanResultsLocationDisabledOrInvalidTimestamp() throws Exception {
1737         ScanResult[] scanResults = new ScanResult[2];
1738         for (int i = 0; i < 2; i++) {
1739             ScanResult scanResult = new ScanResult();
1740             scanResult.timestamp = 0;
1741             scanResults[i] = scanResult;
1742         }
1743         ScanData testScanData = new ScanData(0, 0,
1744                 0, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults);
1745         when(mWifiVendorHal.getCachedScanData(any())).thenReturn(testScanData);
1746 
1747         mWifiNative.setLocationModeEnabled(false);
1748         ScanData scanData = mWifiNative.getCachedScanResults(WIFI_IFACE_NAME);
1749         // Get no scan result because the location mode is disabled
1750         assertEquals(0, scanData.getResults().length);
1751 
1752         mWifiNative.setLocationModeEnabled(true);
1753         scanData = mWifiNative.getCachedScanResults(WIFI_IFACE_NAME);
1754         // Get no scan result because the scan timestamp is too new
1755         assertEquals(0, scanData.getResults().length);
1756     }
1757 
1758     @Test
testGetCachedScanResultsLocationEnabledValidTimestamp()1759     public void testGetCachedScanResultsLocationEnabledValidTimestamp() throws Exception {
1760         ScanResult[] scanResults = new ScanResult[3];
1761         for (int i = 0; i < 3; i++) {
1762             ScanResult scanResult = new ScanResult();
1763             // 1st ScanResult has invalid timestamp
1764             scanResult.timestamp = (i > 0) ? Long.MAX_VALUE : 0;
1765             scanResults[i] = scanResult;
1766         }
1767         ScanData testScanData = new ScanData(0, 0,
1768                 0, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults);
1769         when(mWifiVendorHal.getCachedScanData(any())).thenReturn(testScanData);
1770 
1771         mWifiNative.setLocationModeEnabled(true);
1772         ScanData scanData = mWifiNative.getCachedScanResults(WIFI_IFACE_NAME);
1773         // Get the last two scan results which has the valid timestamp
1774         assertEquals(2, scanData.getResults().length);
1775     }
1776 
1777     @Test
testEnableStaChannelForPeerNetworkWithOverride()1778     public void testEnableStaChannelForPeerNetworkWithOverride() throws Exception {
1779         mResources.setBoolean(R.bool.config_wifiEnableStaIndoorChannelForPeerNetwork, true);
1780         mResources.setBoolean(R.bool.config_wifiEnableStaDfsChannelForPeerNetwork, true);
1781         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1782                 mConcreteClientModeManager);
1783         verify(mWifiVendorHal).enableStaChannelForPeerNetwork(true, true);
1784     }
1785 
1786     /**
1787      * Verifies that setAfcChannelAllowance() calls underlying WifiVendorHal.
1788      */
1789     @Test
testSetAfcChannelAllowance()1790     public void testSetAfcChannelAllowance() {
1791         mWifiNative.setAfcChannelAllowance(mAfcChannelAllowance);
1792         verify(mWifiVendorHal).setAfcChannelAllowance(mAfcChannelAllowance);
1793     }
1794 
1795     /**
1796      * Verifies that overlay config item config_wifiUnknownAkmToKnownAkmMapping is parsed correctly
1797      * and an expected value is set in unknown AKM map.
1798      */
1799     @Test
testConfigWifiUnknownAkmToKnownAkmMapping()1800     public void testConfigWifiUnknownAkmToKnownAkmMapping() throws Exception {
1801         // Test that UnknownAkmMap is not set if two values are not added in the config.
1802         mResources.setStringArray(
1803                 R.array.config_wifiUnknownAkmToKnownAkmMapping, new String[] {"1234"});
1804         WifiNative wifiNativeInstance =
1805                 new WifiNative(
1806                         mWifiVendorHal,
1807                         mStaIfaceHal,
1808                         mHostapdHal,
1809                         mWificondControl,
1810                         mWifiMonitor,
1811                         mPropertyService,
1812                         mWifiMetrics,
1813                         mHandler,
1814                         mRandom,
1815                         mBuildProperties,
1816                         mWifiInjector);
1817         assertNull(wifiNativeInstance.mUnknownAkmMap);
1818 
1819         // Test that UnknownAkmMap is not set if non-integer values are added in the config.
1820         mResources.setStringArray(
1821                 R.array.config_wifiUnknownAkmToKnownAkmMapping, new String[] {"1234, bad"});
1822         wifiNativeInstance =
1823                 new WifiNative(
1824                         mWifiVendorHal,
1825                         mStaIfaceHal,
1826                         mHostapdHal,
1827                         mWificondControl,
1828                         mWifiMonitor,
1829                         mPropertyService,
1830                         mWifiMetrics,
1831                         mHandler,
1832                         mRandom,
1833                         mBuildProperties,
1834                         mWifiInjector);
1835         assertNull(wifiNativeInstance.mUnknownAkmMap);
1836 
1837         // Test that UnknownAkmMap is not set when an invalid AKM is set in the known AKM field
1838         // known AKM - 555 (which is not a valid AKM suite specifier)
1839         mResources.setStringArray(
1840                 R.array.config_wifiUnknownAkmToKnownAkmMapping, new String[] {"9846784, 555"});
1841         wifiNativeInstance =
1842                 new WifiNative(
1843                         mWifiVendorHal,
1844                         mStaIfaceHal,
1845                         mHostapdHal,
1846                         mWificondControl,
1847                         mWifiMonitor,
1848                         mPropertyService,
1849                         mWifiMetrics,
1850                         mHandler,
1851                         mRandom,
1852                         mBuildProperties,
1853                         mWifiInjector);
1854         assertNull(wifiNativeInstance.mUnknownAkmMap);
1855 
1856         // Test that UnknownAkmMap is set for a valid configuration
1857         // known AKM - 28053248 (which corresponds to ScanResult.KEY_MGMT_EAP)
1858         mResources.setStringArray(
1859                 R.array.config_wifiUnknownAkmToKnownAkmMapping, new String[] {"9846784, 28053248"});
1860         wifiNativeInstance =
1861                 new WifiNative(
1862                         mWifiVendorHal,
1863                         mStaIfaceHal,
1864                         mHostapdHal,
1865                         mWificondControl,
1866                         mWifiMonitor,
1867                         mPropertyService,
1868                         mWifiMetrics,
1869                         mHandler,
1870                         mRandom,
1871                         mBuildProperties,
1872                         mWifiInjector);
1873         assertEquals(1, wifiNativeInstance.mUnknownAkmMap.size());
1874         assertEquals(ScanResult.KEY_MGMT_EAP, wifiNativeInstance.mUnknownAkmMap.get(9846784));
1875 
1876         // Test that UnknownAkmMap is set for multiple valid configuration entries
1877         // known AKM - 28053248 (which corresponds to ScanResult.KEY_MGMT_EAP)
1878         // known AKM - 413929216 (which corresponds to ScanResult.KEY_MGMT_SAE_EXT_KEY)
1879         mResources.setStringArray(
1880                 R.array.config_wifiUnknownAkmToKnownAkmMapping,
1881                 new String[] {"9846784, 28053248", "1234, 413929216"});
1882         wifiNativeInstance =
1883                 new WifiNative(
1884                         mWifiVendorHal,
1885                         mStaIfaceHal,
1886                         mHostapdHal,
1887                         mWificondControl,
1888                         mWifiMonitor,
1889                         mPropertyService,
1890                         mWifiMetrics,
1891                         mHandler,
1892                         mRandom,
1893                         mBuildProperties,
1894                         mWifiInjector);
1895         assertEquals(2, wifiNativeInstance.mUnknownAkmMap.size());
1896         assertEquals(ScanResult.KEY_MGMT_EAP, wifiNativeInstance.mUnknownAkmMap.get(9846784));
1897         assertEquals(ScanResult.KEY_MGMT_SAE_EXT_KEY, wifiNativeInstance.mUnknownAkmMap.get(1234));
1898     }
1899 
1900     @Test
testSetRoamingMode()1901     public void testSetRoamingMode() throws Exception {
1902         int status = 0;
1903         when(mWifiVendorHal.setRoamingMode(eq(WIFI_IFACE_NAME), anyInt())).thenReturn(status);
1904         assertEquals(status, mWifiNative.setRoamingMode(WIFI_IFACE_NAME,
1905                 WifiManager.ROAMING_MODE_NORMAL));
1906         verify(mWifiVendorHal).setRoamingMode(WIFI_IFACE_NAME, WifiManager.ROAMING_MODE_NORMAL);
1907     }
1908 
1909     @Test
testRsnOverridingFeatureSupportOnOlderHals()1910     public void testRsnOverridingFeatureSupportOnOlderHals() throws Exception {
1911         when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(false);
1912 
1913         /* RSN Overriding feature is enabled when overlay config item is set to true */
1914         mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true);
1915         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1916                 mConcreteClientModeManager);
1917         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1918         assertTrue(mWifiNative.mIsRsnOverridingSupported);
1919         mWifiNative.teardownAllInterfaces();
1920 
1921         /* RSN Overriding feature is disabled when overlay config item is set to false */
1922         mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false);
1923         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1924                 mConcreteClientModeManager);
1925         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1926         assertFalse(mWifiNative.mIsRsnOverridingSupported);
1927         mWifiNative.teardownAllInterfaces();
1928     }
1929 
1930     @Test
testRsnOverridingFeatureSupportOnNewerHals()1931     public void testRsnOverridingFeatureSupportOnNewerHals() throws Exception {
1932         when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(true);
1933 
1934         /* RSN Overriding feature is enabled based on chip capability */
1935         mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false);
1936         when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(true);
1937         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1938                 mConcreteClientModeManager);
1939         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1940         assertTrue(mWifiNative.mIsRsnOverridingSupported);
1941         mWifiNative.teardownAllInterfaces();
1942 
1943         /* Overlay config has no effect on newer HALs */
1944         mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true);
1945 
1946         when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(false);
1947         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE,
1948                 mConcreteClientModeManager);
1949         mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE);
1950         assertFalse(mWifiNative.mIsRsnOverridingSupported);
1951         mWifiNative.teardownAllInterfaces();
1952     }
1953 
1954     @Test
testIsMLDApSupportMLO()1955     public void testIsMLDApSupportMLO() throws Exception {
1956         when(Flags.mloSap()).thenReturn(true);
1957         BitSet mloFeature =
1958                 createCapabilityBitset(WifiManager.WIFI_FEATURE_SOFTAP_MLO);
1959         when(mWifiGlobals.isMLDApSupported()).thenReturn(true);
1960         assertFalse(mWifiNative.isMLDApSupportMLO());
1961 
1962         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES)))
1963                 .thenReturn(mloFeature.toLongArray());
1964         mWifiNative = new WifiNative(
1965                 mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
1966                 mWifiMonitor, mPropertyService, mWifiMetrics,
1967                 mHandler, mRandom, mBuildProperties, mWifiInjector);
1968         assertTrue(mWifiNative.isMLDApSupportMLO());
1969         when(Flags.mloSap()).thenReturn(false);
1970         assertFalse(mWifiNative.isMLDApSupportMLO());
1971         when(Flags.mloSap()).thenReturn(true);
1972         when(mWifiGlobals.isMLDApSupported()).thenReturn(false);
1973         assertFalse(mWifiNative.isMLDApSupportMLO());
1974     }
1975 }
1976