• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 import static org.junit.Assert.assertArrayEquals;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assume.assumeFalse;
31 import static org.junit.Assume.assumeTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.ArgumentMatchers.anyString;
34 import static org.mockito.ArgumentMatchers.same;
35 import static org.mockito.Mockito.anyBoolean;
36 import static org.mockito.Mockito.anyInt;
37 import static org.mockito.Mockito.eq;
38 import static org.mockito.Mockito.inOrder;
39 import static org.mockito.Mockito.mock;
40 import static org.mockito.Mockito.never;
41 import static org.mockito.Mockito.times;
42 import static org.mockito.Mockito.verify;
43 import static org.mockito.Mockito.when;
44 
45 import android.net.MacAddress;
46 import android.net.wifi.CoexUnsafeChannel;
47 import android.net.wifi.ScanResult;
48 import android.net.wifi.WifiConfiguration;
49 import android.net.wifi.WifiContext;
50 import android.net.wifi.WifiScanner;
51 import android.net.wifi.nl80211.NativeScanResult;
52 import android.net.wifi.nl80211.RadioChainInfo;
53 import android.net.wifi.nl80211.WifiNl80211Manager;
54 import android.net.wifi.nl80211.WifiNl80211Manager.SendMgmtFrameCallback;
55 import android.os.Bundle;
56 import android.os.Handler;
57 import android.os.WorkSource;
58 import android.text.TextUtils;
59 
60 import androidx.test.filters.SmallTest;
61 
62 import com.android.modules.utils.build.SdkLevel;
63 import com.android.server.wifi.coex.CoexManager;
64 import com.android.server.wifi.util.NativeUtil;
65 import com.android.server.wifi.util.NetdWrapper;
66 import com.android.wifi.resources.R;
67 
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.mockito.AdditionalMatchers;
71 import org.mockito.ArgumentCaptor;
72 import org.mockito.InOrder;
73 import org.mockito.Mock;
74 import org.mockito.MockitoAnnotations;
75 
76 import java.util.ArrayList;
77 import java.util.Arrays;
78 import java.util.Collections;
79 import java.util.HashSet;
80 import java.util.List;
81 import java.util.Random;
82 import java.util.Set;
83 import java.util.regex.Pattern;
84 
85 /**
86  * Unit tests for {@link com.android.server.wifi.WifiNative}.
87  */
88 @SmallTest
89 public class WifiNativeTest extends WifiBaseTest {
90     private static final String WIFI_IFACE_NAME = "mockWlan";
91     private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345;
92     private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] {
93             'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
94     private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport(
95             WifiLoggerHal.TX_PKT_FATE_SENT,
96             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
97             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
98             FATE_REPORT_FRAME_BYTES
99     );
100     private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport(
101             WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
102             FATE_REPORT_DRIVER_TIMESTAMP_USEC,
103             WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
104             FATE_REPORT_FRAME_BYTES
105     );
106     private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] {
107             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"),
108             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"),
109             new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management",
110                     "802.11 Mgmt"),
111             new FrameTypeMapping((byte) 42, "42", "N/A")
112     };
113     private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] {
114             new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
115             new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
116             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
117             new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
118                     "firmware dropped (invalid frame)"),
119             new FateMapping(
120                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS,  "firmware dropped (no bufs)"),
121             new FateMapping(
122                     WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
123             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
124             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
125                     "driver dropped (invalid frame)"),
126             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
127                     "driver dropped (no bufs)"),
128             new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
129             new FateMapping((byte) 42, "42")
130     };
131     private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] {
132             new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
133             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
134             new FateMapping(
135                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
136             new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
137                     "firmware dropped (invalid frame)"),
138             new FateMapping(
139                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
140             new FateMapping(
141                     WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
142             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
143             new FateMapping(
144                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
145             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
146                     "driver dropped (invalid frame)"),
147             new FateMapping(
148                     WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
149             new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
150             new FateMapping((byte) 42, "42")
151     };
152     private static final WifiNl80211Manager.SignalPollResult SIGNAL_POLL_RESULT =
153             new WifiNl80211Manager.SignalPollResult(-60, 12, 6, 5240);
154 
155     private static final Set<Integer> SCAN_FREQ_SET =
156             new HashSet<Integer>() {{
157                 add(2410);
158                 add(2450);
159                 add(5050);
160                 add(5200);
161             }};
162     private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\"";
163     private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\"";
164     private static final int[] TEST_FREQUENCIES_1 = {};
165     private static final int[] TEST_FREQUENCIES_2 = {2500, 5124};
166     private static final List<String> SCAN_HIDDEN_NETWORK_SSID_SET =
167             new ArrayList<String>() {{
168                 add(TEST_QUOTED_SSID_1);
169                 add(TEST_QUOTED_SSID_2);
170             }};
171     private static final List<byte[]> SCAN_HIDDEN_NETWORK_BYTE_SSID_SET =
172             new ArrayList<byte[]>() {{
173                 add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_1)));
174                 add(NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(TEST_QUOTED_SSID_2)));
175             }};
176 
177     private static final WifiNative.PnoSettings TEST_PNO_SETTINGS =
178             new WifiNative.PnoSettings() {{
179                 isConnected = false;
180                 periodInMs = 6000;
181                 networkList = new WifiNative.PnoNetwork[2];
182                 networkList[0] = new WifiNative.PnoNetwork();
183                 networkList[1] = new WifiNative.PnoNetwork();
184                 networkList[0].ssid = TEST_QUOTED_SSID_1;
185                 networkList[1].ssid = TEST_QUOTED_SSID_2;
186                 networkList[0].frequencies = TEST_FREQUENCIES_1;
187                 networkList[1].frequencies = TEST_FREQUENCIES_2;
188             }};
189     private static final MacAddress TEST_MAC_ADDRESS = MacAddress.fromString("ee:33:a2:94:10:92");
190 
191     private static final String TEST_MAC_ADDRESS_STR = "f4:f5:e8:51:9e:09";
192     private static final String TEST_BSSID_STR = "a8:bd:27:5b:33:72";
193     private static final int TEST_MCS_RATE = 5;
194     private static final int TEST_SEQUENCE_NUM = 0x66b0;
195 
196     private static final byte[] TEST_SSID =
197             new byte[] {'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
198     private static final byte[] TEST_BSSID =
199             new byte[] {(byte) 0x12, (byte) 0xef, (byte) 0xa1,
200                     (byte) 0x2c, (byte) 0x97, (byte) 0x8b};
201     // This the IE buffer which is consistent with TEST_SSID.
202     private static final byte[] TEST_INFO_ELEMENT_SSID =
203             new byte[] {
204                     // Element ID for SSID.
205                     (byte) 0x00,
206                     // Length of the SSID: 0x0b or 11.
207                     (byte) 0x0b,
208                     // This is string "GoogleGuest"
209                     'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
210     // RSN IE data indicating EAP key management.
211     private static final byte[] TEST_INFO_ELEMENT_RSN =
212             new byte[] {
213                     // Element ID for RSN.
214                     (byte) 0x30,
215                     // Length of the element data.
216                     (byte) 0x18,
217                     (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
218                     (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
219                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, (byte) 0x01, (byte) 0x00,
220                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, (byte) 0x00, (byte) 0x00 };
221 
222     private static final int TEST_FREQUENCY = 2456;
223     private static final int TEST_SIGNAL_MBM = -4500;
224     private static final long TEST_TSF = 34455441;
225     private static final int TEST_CAPABILITY = 0b0000_0000_0010_0100;
226     private static final boolean TEST_ASSOCIATED = true;
227     private static final NativeScanResult MOCK_NATIVE_SCAN_RESULT = createMockNativeScanResult();
createMockNativeScanResult()228     private static NativeScanResult createMockNativeScanResult() {
229         NativeScanResult result = new NativeScanResult();
230         result.ssid = TEST_SSID;
231         result.bssid = TEST_BSSID;
232         result.infoElement = TEST_INFO_ELEMENT_SSID;
233         result.frequency = TEST_FREQUENCY;
234         result.signalMbm = TEST_SIGNAL_MBM;
235         result.tsf = TEST_TSF;
236         result.capability = TEST_CAPABILITY;
237         result.associated = TEST_ASSOCIATED;
238         result.radioChainInfos = new ArrayList<>();
239         return result;
240     }
241 
242     public static final long WIFI_TEST_FEATURE = 0x800000000L;
243 
244     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = new RadioChainInfo(1, -89);
245     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = new RadioChainInfo(0, -78);
246     private static final WorkSource TEST_WORKSOURCE = new WorkSource();
247     private static final WorkSource TEST_WORKSOURCE2 = new WorkSource();
248 
249     MockResources mResources;
250 
251     @Mock private WifiContext mContext;
252     @Mock private WifiVendorHal mWifiVendorHal;
253     @Mock private WifiNl80211Manager mWificondControl;
254     @Mock private SupplicantStaIfaceHal mStaIfaceHal;
255     @Mock private HostapdHal mHostapdHal;
256     @Mock private WifiMonitor mWifiMonitor;
257     @Mock private PropertyService mPropertyService;
258     @Mock private WifiMetrics mWifiMetrics;
259     @Mock private Handler mHandler;
260     @Mock private SendMgmtFrameCallback mSendMgmtFrameCallback;
261     @Mock private Random mRandom;
262     @Mock private WifiInjector mWifiInjector;
263     @Mock private NetdWrapper mNetdWrapper;
264     @Mock private CoexManager mCoexManager;
265     @Mock BuildProperties mBuildProperties;
266     @Mock private WifiNative.InterfaceCallback mInterfaceCallback;
267     @Mock private WifiCountryCode.ChangeListener mWifiCountryCodeChangeListener;
268     @Mock WifiSettingsConfigStore mSettingsConfigStore;
269     @Mock private SoftApManager mSoftApManager;
270 
271     ArgumentCaptor<WifiNl80211Manager.ScanEventCallback> mScanCallbackCaptor =
272             ArgumentCaptor.forClass(WifiNl80211Manager.ScanEventCallback.class);
273 
274     private WifiNative mWifiNative;
275 
276     @Before
setUp()277     public void setUp() throws Exception {
278         MockitoAnnotations.initMocks(this);
279 
280         when(mWifiVendorHal.initialize(any())).thenReturn(true);
281         when(mWifiVendorHal.isVendorHalSupported()).thenReturn(true);
282         when(mWifiVendorHal.startVendorHal()).thenReturn(true);
283         when(mWifiVendorHal.startVendorHalSta()).thenReturn(true);
284         when(mWifiVendorHal.createStaIface(any(), any())).thenReturn(WIFI_IFACE_NAME);
285 
286         when(mBuildProperties.isEngBuild()).thenReturn(false);
287         when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
288         when(mBuildProperties.isUserBuild()).thenReturn(true);
289 
290         when(mWificondControl.setupInterfaceForClientMode(any(), any(), any(), any())).thenReturn(
291                 true);
292 
293         when(mStaIfaceHal.registerDeathHandler(any())).thenReturn(true);
294         when(mStaIfaceHal.isInitializationComplete()).thenReturn(true);
295         when(mStaIfaceHal.initialize()).thenReturn(true);
296         when(mStaIfaceHal.startDaemon()).thenReturn(true);
297         when(mStaIfaceHal.setupIface(any())).thenReturn(true);
298 
299         when(mWifiInjector.makeNetdWrapper()).thenReturn(mNetdWrapper);
300         when(mWifiInjector.getCoexManager()).thenReturn(mCoexManager);
301 
302         when(mWifiInjector.getSettingsConfigStore()).thenReturn(mSettingsConfigStore);
303         when(mWifiInjector.getContext()).thenReturn(mContext);
304         mResources = getMockResources();
305         mResources.setBoolean(R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled, false);
306         when(mContext.getResources()).thenReturn(mResources);
307         when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES)))
308                 .thenReturn(WIFI_TEST_FEATURE);
309 
310         mWifiNative = new WifiNative(
311                 mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl,
312                 mWifiMonitor, mPropertyService, mWifiMetrics,
313                 mHandler, mRandom, mBuildProperties, mWifiInjector);
314         mWifiNative.initialize();
315     }
316 
getMockResources()317     private MockResources getMockResources() {
318         MockResources resources = new MockResources();
319         return resources;
320     }
321 
322     /**
323      * Verifies that TxFateReport's constructor sets all of the TxFateReport fields.
324      */
325     @Test
testTxFateReportCtorSetsFields()326     public void testTxFateReportCtorSetsFields() {
327         WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
328                 WifiLoggerHal.TX_PKT_FATE_SENT,  // non-zero value
329                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
330                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
331                 FATE_REPORT_FRAME_BYTES
332         );
333         assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate);
334         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
335         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
336         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
337     }
338 
339     /**
340      * Verifies that RxFateReport's constructor sets all of the RxFateReport fields.
341      */
342     @Test
testRxFateReportCtorSetsFields()343     public void testRxFateReportCtorSetsFields() {
344         WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
345                 WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,  // non-zero value
346                 FATE_REPORT_DRIVER_TIMESTAMP_USEC,
347                 WifiLoggerHal.FRAME_TYPE_ETHERNET_II,  // non-zero value
348                 FATE_REPORT_FRAME_BYTES
349         );
350         assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate);
351         assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
352         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
353         assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
354     }
355 
356     /**
357      * Verifies the hashCode methods for HiddenNetwork and PnoNetwork classes
358      */
359     @Test
testHashCode()360     public void testHashCode() {
361         WifiNative.HiddenNetwork hiddenNet1 = new WifiNative.HiddenNetwork();
362         hiddenNet1.ssid = new String("sametext");
363 
364         WifiNative.HiddenNetwork hiddenNet2 = new WifiNative.HiddenNetwork();
365         hiddenNet2.ssid = new String("sametext");
366 
367         assertTrue(hiddenNet1.equals(hiddenNet2));
368         assertEquals(hiddenNet1.hashCode(), hiddenNet2.hashCode());
369 
370         WifiNative.PnoNetwork pnoNet1 = new WifiNative.PnoNetwork();
371         pnoNet1.ssid = new String("sametext");
372         pnoNet1.flags = 2;
373         pnoNet1.auth_bit_field = 4;
374         pnoNet1.frequencies = TEST_FREQUENCIES_2;
375 
376         WifiNative.PnoNetwork pnoNet2 = new WifiNative.PnoNetwork();
377         pnoNet2.ssid = new String("sametext");
378         pnoNet2.flags = 2;
379         pnoNet2.auth_bit_field = 4;
380         pnoNet2.frequencies = TEST_FREQUENCIES_2;
381 
382         assertTrue(pnoNet1.equals(pnoNet2));
383         assertEquals(pnoNet1.hashCode(), pnoNet2.hashCode());
384     }
385 
386     // Support classes for test{Tx,Rx}FateReportToString.
387     private static class FrameTypeMapping {
388         byte mTypeNumber;
389         String mExpectedTypeText;
390         String mExpectedProtocolText;
FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText)391         FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) {
392             this.mTypeNumber = typeNumber;
393             this.mExpectedTypeText = expectedTypeText;
394             this.mExpectedProtocolText = expectedProtocolText;
395         }
396     }
397     private static class FateMapping {
398         byte mFateNumber;
399         String mExpectedText;
FateMapping(byte fateNumber, String expectedText)400         FateMapping(byte fateNumber, String expectedText) {
401             this.mFateNumber = fateNumber;
402             this.mExpectedText = expectedText;
403         }
404     }
405 
406     /**
407      * Verifies that FateReport.getTableHeader() prints the right header.
408      */
409     @Test
testFateReportTableHeader()410     public void testFateReportTableHeader() {
411         final String header = WifiNative.FateReport.getTableHeader();
412         assertEquals(
413                 "\nTime usec        Walltime      Direction  Fate                              "
414                 + "Protocol      Type                     Result\n"
415                 + "---------        --------      ---------  ----                              "
416                 + "--------      ----                     ------\n", header);
417     }
418 
419     /**
420      * Verifies that TxFateReport.toTableRowString() includes the information we care about.
421      */
422     @Test
testTxFateReportToTableRowString()423     public void testTxFateReportToTableRowString() {
424         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
425         assertTrue(
426                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
427                     FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
428                             + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
429                             + "TX "  // direction
430                             + "sent "  // fate
431                             + "Ethernet "  // type
432                             + "N/A "  // protocol
433                             + "N/A"  // result
434                 )
435         );
436 
437         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
438             fateReport = new WifiNative.TxFateReport(
439                     WifiLoggerHal.TX_PKT_FATE_SENT,
440                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
441                     frameTypeMapping.mTypeNumber,
442                     FATE_REPORT_FRAME_BYTES
443             );
444             assertTrue(
445                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
446                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
447                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
448                                     + "TX "  // direction
449                                     + "sent "  // fate
450                                     + frameTypeMapping.mExpectedProtocolText + " "  // type
451                                     + "N/A "  // protocol
452                                     + "N/A"  // result
453                     )
454             );
455         }
456 
457         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
458             fateReport = new WifiNative.TxFateReport(
459                     fateMapping.mFateNumber,
460                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
461                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
462                     FATE_REPORT_FRAME_BYTES
463             );
464             assertTrue(
465                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
466                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
467                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
468                                     + "TX "  // direction
469                                     + Pattern.quote(fateMapping.mExpectedText) + " "  // fate
470                                     + "802.11 Mgmt "  // type
471                                     + "N/A "  // protocol
472                                     + "N/A"  // result
473                     )
474             );
475         }
476     }
477 
478     /**
479      * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
480      * about.
481      */
482     @Test
testTxFateReportToVerboseStringWithPiiAllowed()483     public void testTxFateReportToVerboseStringWithPiiAllowed() {
484         WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
485 
486         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
487         assertTrue(verboseFateString.contains("Frame direction: TX"));
488         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
489         assertTrue(verboseFateString.contains("Frame fate: sent"));
490         assertTrue(verboseFateString.contains("Frame type: data"));
491         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
492         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
493         assertTrue(verboseFateString.contains("Frame length: 16"));
494         assertTrue(verboseFateString.contains(
495                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
496         // TODO(quiche): uncomment this, once b/27975149 is fixed.
497         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
498 
499         for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
500             fateReport = new WifiNative.TxFateReport(
501                     WifiLoggerHal.TX_PKT_FATE_SENT,
502                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
503                     frameTypeMapping.mTypeNumber,
504                     FATE_REPORT_FRAME_BYTES
505             );
506             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
507             assertTrue(verboseFateString.contains("Frame type: "
508                     + frameTypeMapping.mExpectedTypeText));
509         }
510 
511         for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
512             fateReport = new WifiNative.TxFateReport(
513                     fateMapping.mFateNumber,
514                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
515                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
516                     FATE_REPORT_FRAME_BYTES
517             );
518             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
519             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
520         }
521     }
522 
523     /**
524      * Verifies that RxFateReport.toTableRowString() includes the information we care about.
525      */
526     @Test
testRxFateReportToTableRowString()527     public void testRxFateReportToTableRowString() {
528         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
529         assertTrue(
530                 fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
531                         FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
532                                 + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
533                                 + "RX "  // direction
534                                 + Pattern.quote("firmware dropped (invalid frame) ")  // fate
535                                 + "Ethernet "  // type
536                                 + "N/A "  // protocol
537                                 + "N/A"  // result
538                 )
539         );
540 
541         // FrameTypeMappings omitted, as they're the same as for TX.
542 
543         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
544             fateReport = new WifiNative.RxFateReport(
545                     fateMapping.mFateNumber,
546                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
547                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
548                     FATE_REPORT_FRAME_BYTES
549             );
550             assertTrue(
551                     fateReport.toTableRowString().replaceAll("\\s+", " ").trim().matches(
552                             FATE_REPORT_DRIVER_TIMESTAMP_USEC + " "  // timestamp
553                                     + "\\d{2}:\\d{2}:\\d{2}\\.\\d{3} "  // walltime
554                                     + "RX "  // direction
555                                     + Pattern.quote(fateMapping.mExpectedText) + " " // fate
556                                     + "802.11 Mgmt "  // type
557                                     + "N/A " // protocol
558                                     + "N/A"  // result
559                     )
560             );
561         }
562     }
563 
564     /**
565      * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
566      * about.
567      */
568     @Test
testRxFateReportToVerboseStringWithPiiAllowed()569     public void testRxFateReportToVerboseStringWithPiiAllowed() {
570         WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
571 
572         String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
573         assertTrue(verboseFateString.contains("Frame direction: RX"));
574         assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
575         assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)"));
576         assertTrue(verboseFateString.contains("Frame type: data"));
577         assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
578         assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
579         assertTrue(verboseFateString.contains("Frame length: 16"));
580         assertTrue(verboseFateString.contains(
581                 "61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
582         // TODO(quiche): uncomment this, once b/27975149 is fixed.
583         // assertTrue(verboseFateString.contains("abcdefgh........"));  // hex dump
584 
585         // FrameTypeMappings omitted, as they're the same as for TX.
586 
587         for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
588             fateReport = new WifiNative.RxFateReport(
589                     fateMapping.mFateNumber,
590                     FATE_REPORT_DRIVER_TIMESTAMP_USEC,
591                     WifiLoggerHal.FRAME_TYPE_80211_MGMT,
592                     FATE_REPORT_FRAME_BYTES
593             );
594             verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
595             assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
596         }
597     }
598 
599     /**
600      * Verifies that startPktFateMonitoring returns false when HAL is not started.
601      */
602     @Test
testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted()603     public void testStartPktFateMonitoringReturnsFalseWhenHalIsNotStarted() {
604         assertFalse(mWifiNative.isHalStarted());
605         assertFalse(mWifiNative.startPktFateMonitoring(WIFI_IFACE_NAME));
606     }
607 
608     /**
609      * Verifies that getTxPktFates returns error when HAL is not started.
610      */
611     @Test
testGetTxPktFatesReturnsErrorWhenHalIsNotStarted()612     public void testGetTxPktFatesReturnsErrorWhenHalIsNotStarted() {
613         assertFalse(mWifiNative.isHalStarted());
614         assertEquals(0, mWifiNative.getTxPktFates(WIFI_IFACE_NAME).size());
615     }
616 
617     /**
618      * Verifies that getRxPktFates returns error when HAL is not started.
619      */
620     @Test
testGetRxPktFatesReturnsErrorWhenHalIsNotStarted()621     public void testGetRxPktFatesReturnsErrorWhenHalIsNotStarted() {
622         assertFalse(mWifiNative.isHalStarted());
623         assertEquals(0, mWifiNative.getRxPktFates(WIFI_IFACE_NAME).size());
624     }
625 
626     // TODO(quiche): Add tests for the success cases (when HAL has been started). Specifically:
627     // - testStartPktFateMonitoringCallsHalIfHalIsStarted()
628     // - testGetTxPktFatesCallsHalIfHalIsStarted()
629     // - testGetRxPktFatesCallsHalIfHalIsStarted()
630     //
631     // Adding these tests is difficult to do at the moment, because we can't mock out the HAL
632     // itself. Also, we can't mock out the native methods, because those methods are private.
633     // b/28005116.
634 
635     /** Verifies that getDriverStateDumpNative returns null when HAL is not started. */
636     @Test
testGetDriverStateDumpReturnsNullWhenHalIsNotStarted()637     public void testGetDriverStateDumpReturnsNullWhenHalIsNotStarted() {
638         assertEquals(null, mWifiNative.getDriverStateDump());
639     }
640 
641     // TODO(b/28005116): Add test for the success case of getDriverStateDump().
642 
643     /**
644      * Verifies getWifiLinkLayerStats() calls underlying WifiVendorHal.
645      *
646      */
647     @Test
testGetWifiLinkLayerStatsForClientInConnectivityMode()648     public void testGetWifiLinkLayerStatsForClientInConnectivityMode() throws Exception {
649         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
650         mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
651         mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME);
652         verify(mWifiVendorHal, times(2)).getWifiLinkLayerStats(eq(WIFI_IFACE_NAME));
653     }
654 
655     /**
656      * Verifies client mode + scan success.
657      */
658     @Test
testClientModeScanSuccess()659     public void testClientModeScanSuccess() {
660         InOrder order = inOrder(mWificondControl, mNetdWrapper, mWifiVendorHal);
661         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
662         order.verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
663                 mScanCallbackCaptor.capture(), any());
664         order.verify(mNetdWrapper).isInterfaceUp(eq(WIFI_IFACE_NAME));
665         order.verify(mWifiVendorHal).enableLinkLayerStats(eq(WIFI_IFACE_NAME));
666 
667         mScanCallbackCaptor.getValue().onScanResultReady();
668         verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME);
669     }
670 
671     /**
672      * Verifies client mode + scan failure.
673      */
674     @Test
testClientModeScanFailure()675     public void testClientModeScanFailure() {
676         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
677         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
678                 mScanCallbackCaptor.capture(), any());
679 
680         mScanCallbackCaptor.getValue().onScanFailed();
681         verify(mWifiMonitor).broadcastScanFailedEvent(WIFI_IFACE_NAME);
682     }
683 
684     /**
685      * Verifies client mode + PNO scan success.
686      */
687     @Test
testClientModePnoScanSuccess()688     public void testClientModePnoScanSuccess() {
689         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
690         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
691                 any(), mScanCallbackCaptor.capture());
692 
693         mScanCallbackCaptor.getValue().onScanResultReady();
694         verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME);
695         verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
696     }
697 
698     /**
699      * Verifies client mode + PNO scan failure.
700      */
701     @Test
testClientModePnoScanFailure()702     public void testClientModePnoScanFailure() {
703         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
704         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
705                 any(), mScanCallbackCaptor.capture());
706 
707         mScanCallbackCaptor.getValue().onScanFailed();
708         verify(mWifiMetrics).incrementPnoScanFailedCount();
709     }
710 
711     /**
712      * Verifies scan mode + scan success.
713      */
714     @Test
testScanModeScanSuccess()715     public void testScanModeScanSuccess() {
716         InOrder order = inOrder(mWificondControl, mNetdWrapper, mWifiVendorHal);
717         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE);
718         order.verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
719                 mScanCallbackCaptor.capture(), any());
720         order.verify(mNetdWrapper).isInterfaceUp(eq(WIFI_IFACE_NAME));
721         order.verify(mWifiVendorHal).enableLinkLayerStats(eq(WIFI_IFACE_NAME));
722 
723         mScanCallbackCaptor.getValue().onScanResultReady();
724         verify(mWifiMonitor).broadcastScanResultEvent(WIFI_IFACE_NAME);
725     }
726 
727     /**
728      * Verifies scan mode + scan failure.
729      */
730     @Test
testScanModeScanFailure()731     public void testScanModeScanFailure() {
732         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE);
733         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
734                 mScanCallbackCaptor.capture(), any());
735 
736         mScanCallbackCaptor.getValue().onScanFailed();
737         verify(mWifiMonitor).broadcastScanFailedEvent(WIFI_IFACE_NAME);
738     }
739 
740     /**
741      * Verifies scan mode + PNO scan success.
742      */
743     @Test
testScanModePnoScanSuccess()744     public void testScanModePnoScanSuccess() {
745         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE);
746         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
747                 any(), mScanCallbackCaptor.capture());
748 
749         mScanCallbackCaptor.getValue().onScanResultReady();
750         verify(mWifiMonitor).broadcastPnoScanResultEvent(WIFI_IFACE_NAME);
751         verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
752     }
753 
754     /**
755      * Verifies scan mode + PNO scan failure.
756      */
757     @Test
testScanModePnoScanFailure()758     public void testScanModePnoScanFailure() {
759         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE);
760         verify(mWificondControl).setupInterfaceForClientMode(eq(WIFI_IFACE_NAME), any(),
761                 any(), mScanCallbackCaptor.capture());
762 
763         mScanCallbackCaptor.getValue().onScanFailed();
764         verify(mWifiMetrics).incrementPnoScanFailedCount();
765     }
766 
767     /**
768      * Verifies starting the hal results in coex unsafe channels being updated with cached values.
769      */
770     @Test
testStartHalUpdatesCoexUnsafeChannels()771     public void testStartHalUpdatesCoexUnsafeChannels() {
772         assumeTrue(SdkLevel.isAtLeastS());
773         final List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
774         unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6));
775         unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_5_GHZ, 36));
776         final int restrictions = 0;
777         when(mCoexManager.getCoexUnsafeChannels()).thenReturn(unsafeChannels);
778         when(mCoexManager.getCoexRestrictions()).thenReturn(restrictions);
779         mWifiNative.setCoexUnsafeChannels(unsafeChannels, restrictions);
780 
781         mWifiNative.setupInterfaceForClientInConnectivityMode(null, TEST_WORKSOURCE);
782         verify(mWifiVendorHal, times(2)).setCoexUnsafeChannels(unsafeChannels, restrictions);
783 
784         mWifiNative.teardownAllInterfaces();
785         mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE);
786         verify(mWifiVendorHal, times(3)).setCoexUnsafeChannels(unsafeChannels, restrictions);
787 
788         mWifiNative.teardownAllInterfaces();
789         mWifiNative.setupInterfaceForSoftApMode(null, TEST_WORKSOURCE, WIFI_BAND_24_GHZ, false,
790                 mSoftApManager);
791         verify(mWifiVendorHal, times(4)).setCoexUnsafeChannels(unsafeChannels, restrictions);
792     }
793 
794     /**
795      * Verifies that signalPoll() calls underlying WificondControl.
796      */
797     @Test
testSignalPoll()798     public void testSignalPoll() throws Exception {
799         when(mWificondControl.signalPoll(WIFI_IFACE_NAME))
800                 .thenReturn(SIGNAL_POLL_RESULT);
801 
802         WifiNl80211Manager.SignalPollResult pollResult = mWifiNative.signalPoll(WIFI_IFACE_NAME);
803         assertEquals(SIGNAL_POLL_RESULT.currentRssiDbm, pollResult.currentRssiDbm);
804         assertEquals(SIGNAL_POLL_RESULT.txBitrateMbps, pollResult.txBitrateMbps);
805         assertEquals(SIGNAL_POLL_RESULT.associationFrequencyMHz,
806                 pollResult.associationFrequencyMHz);
807         assertEquals(SIGNAL_POLL_RESULT.rxBitrateMbps, pollResult.rxBitrateMbps);
808 
809         verify(mWificondControl).signalPoll(WIFI_IFACE_NAME);
810     }
811 
812     /**
813      * Verifies that scan() calls underlying WificondControl.
814      */
815     @Test
testScan()816     public void testScan() throws Exception {
817         // This test will not run if the device has SDK level S or later
818         assumeFalse(SdkLevel.isAtLeastS());
819         mWifiNative.scan(WIFI_IFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, SCAN_FREQ_SET,
820                 SCAN_HIDDEN_NETWORK_SSID_SET, false);
821         ArgumentCaptor<List<byte[]>> ssidSetCaptor = ArgumentCaptor.forClass(List.class);
822         verify(mWificondControl).startScan(
823                 eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY),
824                 eq(SCAN_FREQ_SET), ssidSetCaptor.capture());
825         List<byte[]> ssidSet = ssidSetCaptor.getValue();
826         assertArrayEquals(ssidSet.toArray(), SCAN_HIDDEN_NETWORK_BYTE_SSID_SET.toArray());
827     }
828 
829     /**
830      * Verifies that scan() calls the new startScan API with a Bundle when the Sdk level
831      * is S or above.
832      */
833     @Test
testScanWithBundle()834     public void testScanWithBundle() throws Exception {
835         // This test will only run if the device has SDK level S and later.
836         assumeTrue(SdkLevel.isAtLeastS());
837         mWifiNative.scan(WIFI_IFACE_NAME, WifiScanner.SCAN_TYPE_HIGH_ACCURACY, SCAN_FREQ_SET,
838                 SCAN_HIDDEN_NETWORK_SSID_SET, true);
839         ArgumentCaptor<List<byte[]>> ssidSetCaptor = ArgumentCaptor.forClass(List.class);
840         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
841         verify(mWificondControl).startScan(
842                 eq(WIFI_IFACE_NAME), eq(WifiScanner.SCAN_TYPE_HIGH_ACCURACY),
843                 eq(SCAN_FREQ_SET), ssidSetCaptor.capture(), bundleCaptor.capture());
844         List<byte[]> ssidSet = ssidSetCaptor.getValue();
845         assertArrayEquals(ssidSet.toArray(), SCAN_HIDDEN_NETWORK_BYTE_SSID_SET.toArray());
846         Bundle bundle = bundleCaptor.getValue();
847         assertTrue(bundle.getBoolean(WifiNl80211Manager.SCANNING_PARAM_ENABLE_6GHZ_RNR));
848     }
849 
850     /**
851      * Verifies that startPnoscan() calls underlying WificondControl.
852      */
853     @Test
testStartPnoScanOnRequestProcessed()854     public void testStartPnoScanOnRequestProcessed() throws Exception {
855         mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS);
856 
857         ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor =
858                 ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class);
859         verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME),
860                 eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture());
861         captor.getValue().onPnoRequestSucceeded();
862         verify(mWifiMetrics).incrementPnoScanStartAttemptCount();
863     }
864 
865     /**
866      * Verifies that startPnoscan() calls underlying WificondControl.
867      */
868     @Test
testStartPnoScanOnRequestFailed()869     public void testStartPnoScanOnRequestFailed() throws Exception {
870         mWifiNative.startPnoScan(WIFI_IFACE_NAME, TEST_PNO_SETTINGS);
871 
872         ArgumentCaptor<WifiNl80211Manager.PnoScanRequestCallback> captor =
873                 ArgumentCaptor.forClass(WifiNl80211Manager.PnoScanRequestCallback.class);
874         verify(mWificondControl).startPnoScan(eq(WIFI_IFACE_NAME),
875                 eq(TEST_PNO_SETTINGS.toNativePnoSettings()), any(), captor.capture());
876         captor.getValue().onPnoRequestFailed();
877         verify(mWifiMetrics).incrementPnoScanStartAttemptCount();
878         verify(mWifiMetrics).incrementPnoScanFailedCount();
879     }
880 
881     /**
882      * Verifies that stopPnoscan() calls underlying WificondControl.
883      */
884     @Test
testStopPnoScan()885     public void testStopPnoScan() throws Exception {
886         mWifiNative.stopPnoScan(WIFI_IFACE_NAME);
887         verify(mWificondControl).stopPnoScan(WIFI_IFACE_NAME);
888     }
889 
890     /**
891      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
892      */
893     @Test
testGetScanResults()894     public void testGetScanResults() {
895         // Mock the returned array of NativeScanResult.
896         List<NativeScanResult> mockScanResults = Arrays.asList(MOCK_NATIVE_SCAN_RESULT);
897         when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults);
898 
899         ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME);
900         assertEquals(mockScanResults.size(), returnedScanResults.size());
901         // Since NativeScanResult is organized differently from ScanResult, this only checks
902         // a few fields.
903         for (int i = 0; i < mockScanResults.size(); i++) {
904             assertArrayEquals(mockScanResults.get(i).getSsid(),
905                     returnedScanResults.get(i).getScanResult().SSID.getBytes());
906             assertEquals(mockScanResults.get(i).getFrequencyMhz(),
907                     returnedScanResults.get(i).getScanResult().frequency);
908             assertEquals(mockScanResults.get(i).getTsf(),
909                     returnedScanResults.get(i).getScanResult().timestamp);
910         }
911     }
912 
913     /**
914      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
915      * when there is radio chain info.
916      */
917     @Test
testGetScanResultsWithRadioChainInfo()918     public void testGetScanResultsWithRadioChainInfo() throws Exception {
919         // Mock the returned array of NativeScanResult.
920         NativeScanResult nativeScanResult = createMockNativeScanResult();
921         // Add radio chain info
922         List<RadioChainInfo> nativeRadioChainInfos = Arrays.asList(
923                 MOCK_NATIVE_RADIO_CHAIN_INFO_1, MOCK_NATIVE_RADIO_CHAIN_INFO_2);
924         nativeScanResult.radioChainInfos = nativeRadioChainInfos;
925         List<NativeScanResult> mockScanResults = Arrays.asList(nativeScanResult);
926 
927         when(mWificondControl.getScanResults(anyString(), anyInt())).thenReturn(mockScanResults);
928 
929         ArrayList<ScanDetail> returnedScanResults = mWifiNative.getScanResults(WIFI_IFACE_NAME);
930         assertEquals(mockScanResults.size(), returnedScanResults.size());
931         // Since NativeScanResult is organized differently from ScanResult, this only checks
932         // a few fields.
933         for (int i = 0; i < mockScanResults.size(); i++) {
934             assertArrayEquals(mockScanResults.get(i).getSsid(),
935                     returnedScanResults.get(i).getScanResult().SSID.getBytes());
936             assertEquals(mockScanResults.get(i).getFrequencyMhz(),
937                     returnedScanResults.get(i).getScanResult().frequency);
938             assertEquals(mockScanResults.get(i).getTsf(),
939                     returnedScanResults.get(i).getScanResult().timestamp);
940             ScanResult.RadioChainInfo[] scanRcis = returnedScanResults.get(
941                     i).getScanResult().radioChainInfos;
942             assertEquals(nativeRadioChainInfos.size(), scanRcis.length);
943             for (int j = 0; j < scanRcis.length; ++j) {
944                 assertEquals(nativeRadioChainInfos.get(j).getChainId(), scanRcis[j].id);
945                 assertEquals(nativeRadioChainInfos.get(j).getLevelDbm(), scanRcis[j].level);
946             }
947         }
948     }
949 
950     /**
951      * Verifies that connectToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal.
952      */
953     @Test
testConnectToNetwork()954     public void testConnectToNetwork() throws Exception {
955         WifiConfiguration config = mock(WifiConfiguration.class);
956         mWifiNative.connectToNetwork(WIFI_IFACE_NAME, config);
957         // connectToNetwork() should abort ongoing scan before connection.
958         verify(mWificondControl).abortScan(WIFI_IFACE_NAME);
959         verify(mStaIfaceHal).connectToNetwork(WIFI_IFACE_NAME, config);
960     }
961 
962     /**
963      * Verifies that roamToNetwork() calls underlying WificondControl and SupplicantStaIfaceHal.
964      */
965     @Test
testRoamToNetwork()966     public void testRoamToNetwork() throws Exception {
967         WifiConfiguration config = mock(WifiConfiguration.class);
968         mWifiNative.roamToNetwork(WIFI_IFACE_NAME, config);
969         // roamToNetwork() should abort ongoing scan before connection.
970         verify(mWificondControl).abortScan(WIFI_IFACE_NAME);
971         verify(mStaIfaceHal).roamToNetwork(WIFI_IFACE_NAME, config);
972     }
973 
974     /**
975      * Verifies that removeIfaceInstanceFromBridgedApIface() calls underlying WifiVendorHal.
976      */
977     @Test
testRemoveIfaceInstanceFromBridgedApIface()978     public void testRemoveIfaceInstanceFromBridgedApIface() throws Exception {
979         mWifiNative.removeIfaceInstanceFromBridgedApIface(
980                 "br_" + WIFI_IFACE_NAME, WIFI_IFACE_NAME);
981         verify(mWifiVendorHal).removeIfaceInstanceFromBridgedApIface(
982                 "br_" + WIFI_IFACE_NAME, WIFI_IFACE_NAME);
983     }
984 
985     /**
986      * Verifies that setMacAddress() calls underlying WifiVendorHal.
987      */
988     @Test
testStaSetMacAddress()989     public void testStaSetMacAddress() throws Exception {
990         mWifiNative.setStaMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
991         verify(mStaIfaceHal).disconnect(WIFI_IFACE_NAME);
992         verify(mWifiVendorHal).setStaMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
993     }
994 
995     /**
996      * Verifies that setMacAddress() calls underlying WifiVendorHal.
997      */
998     @Test
testApSetMacAddress()999     public void testApSetMacAddress() throws Exception {
1000         mWifiNative.setApMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1001         verify(mWifiVendorHal).setApMacAddress(WIFI_IFACE_NAME, TEST_MAC_ADDRESS);
1002     }
1003 
1004     /**
1005      * Verifies that resetApMacToFactoryMacAddress() calls underlying WifiVendorHal.
1006      */
1007     @Test
testResetApMacToFactoryMacAddress()1008     public void testResetApMacToFactoryMacAddress() throws Exception {
1009         mWifiNative.resetApMacToFactoryMacAddress(WIFI_IFACE_NAME);
1010         verify(mWifiVendorHal).resetApMacToFactoryMacAddress(WIFI_IFACE_NAME);
1011     }
1012 
1013     /**
1014      * Verifies that setCoexUnsafeChannels() calls underlying WifiVendorHal.
1015      */
1016     @Test
testSetCoexUnsafeChannels()1017     public void testSetCoexUnsafeChannels() throws Exception {
1018         assumeTrue(SdkLevel.isAtLeastS());
1019         mWifiNative.setCoexUnsafeChannels(Collections.emptyList(), 0);
1020         verify(mWifiVendorHal).setCoexUnsafeChannels(Collections.emptyList(), 0);
1021     }
1022 
1023     /**
1024      * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal.
1025      */
1026     @Test
testIsStaSetMacAddressSupported()1027     public void testIsStaSetMacAddressSupported() throws Exception {
1028         mWifiNative.isStaSetMacAddressSupported(WIFI_IFACE_NAME);
1029         verify(mWifiVendorHal).isStaSetMacAddressSupported(WIFI_IFACE_NAME);
1030     }
1031 
1032     /**
1033      * Verifies that isSetMacAddressSupported() calls underlying WifiVendorHal.
1034      */
1035     @Test
testIsApSetMacAddressSupported()1036     public void testIsApSetMacAddressSupported() throws Exception {
1037         mWifiNative.isApSetMacAddressSupported(WIFI_IFACE_NAME);
1038         verify(mWifiVendorHal).isApSetMacAddressSupported(WIFI_IFACE_NAME);
1039     }
1040 
1041     /**
1042      * Test that selectTxPowerScenario() calls into WifiVendorHal (success case)
1043      */
1044     @Test
testSelectTxPowerScenario_success()1045     public void testSelectTxPowerScenario_success() throws Exception {
1046         when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(true);
1047         SarInfo sarInfo = new SarInfo();
1048         assertTrue(mWifiNative.selectTxPowerScenario(sarInfo));
1049         verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
1050     }
1051 
1052     /**
1053      * Test that selectTxPowerScenario() calls into WifiVendorHal (failure case)
1054      */
1055     @Test
testSelectTxPowerScenario_failure()1056     public void testSelectTxPowerScenario_failure() throws Exception {
1057         when(mWifiVendorHal.selectTxPowerScenario(any(SarInfo.class))).thenReturn(false);
1058         SarInfo sarInfo = new SarInfo();
1059         assertFalse(mWifiNative.selectTxPowerScenario(sarInfo));
1060         verify(mWifiVendorHal).selectTxPowerScenario(sarInfo);
1061     }
1062 
1063     /**
1064      * Test that setPowerSave() with true, results in calling into SupplicantStaIfaceHal
1065      */
1066     @Test
testSetPowerSaveTrue()1067     public void testSetPowerSaveTrue() throws Exception {
1068         mWifiNative.setPowerSave(WIFI_IFACE_NAME, true);
1069         verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, true);
1070     }
1071 
1072     /**
1073      * Test that setPowerSave() with false, results in calling into SupplicantStaIfaceHal
1074      */
1075     @Test
testSetPowerSaveFalse()1076     public void testSetPowerSaveFalse() throws Exception {
1077         mWifiNative.setPowerSave(WIFI_IFACE_NAME, false);
1078         verify(mStaIfaceHal).setPowerSave(WIFI_IFACE_NAME, false);
1079     }
1080 
1081     /**
1082      * Test that setLowLatencyMode() with true, results in calling into WifiVendorHal
1083      */
1084     @Test
testLowLatencyModeTrue()1085     public void testLowLatencyModeTrue() throws Exception {
1086         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true);
1087         assertTrue(mWifiNative.setLowLatencyMode(true));
1088         verify(mWifiVendorHal).setLowLatencyMode(true);
1089     }
1090 
1091     /**
1092      * Test that setLowLatencyMode() with false, results in calling into WifiVendorHal
1093      */
1094     @Test
testLowLatencyModeFalse()1095     public void testLowLatencyModeFalse() throws Exception {
1096         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(true);
1097         assertTrue(mWifiNative.setLowLatencyMode(false));
1098         verify(mWifiVendorHal).setLowLatencyMode(false);
1099     }
1100 
1101     /**
1102      * Test that setLowLatencyMode() returns with failure when WifiVendorHal fails.
1103      */
1104     @Test
testSetLowLatencyModeFail()1105     public void testSetLowLatencyModeFail() throws Exception {
1106         final boolean lowLatencyMode = true;
1107         when(mWifiVendorHal.setLowLatencyMode(anyBoolean())).thenReturn(false);
1108         assertFalse(mWifiNative.setLowLatencyMode(lowLatencyMode));
1109         verify(mWifiVendorHal).setLowLatencyMode(lowLatencyMode);
1110     }
1111 
1112     @Test
testStaGetFactoryMacAddress()1113     public void testStaGetFactoryMacAddress() throws Exception {
1114         when(mWifiVendorHal.getStaFactoryMacAddress(any()))
1115                 .thenReturn(MacAddress.BROADCAST_ADDRESS);
1116         assertNotNull(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME));
1117         verify(mWifiVendorHal).getStaFactoryMacAddress(any());
1118     }
1119 
1120 
1121     @Test
testGetApFactoryMacAddress()1122     public void testGetApFactoryMacAddress() throws Exception {
1123         when(mWifiVendorHal.getApFactoryMacAddress(any())).thenReturn(MacAddress.BROADCAST_ADDRESS);
1124         assertNotNull(mWifiNative.getApFactoryMacAddress(WIFI_IFACE_NAME));
1125         verify(mWifiVendorHal).getApFactoryMacAddress(any());
1126     }
1127 
1128     /**
1129      * Test that flushRingBufferData(), results in calling into WifiVendorHal
1130      */
1131     @Test
testFlushRingBufferDataTrue()1132     public void testFlushRingBufferDataTrue() throws Exception {
1133         when(mWifiVendorHal.flushRingBufferData()).thenReturn(true);
1134         assertTrue(mWifiNative.flushRingBufferData());
1135         verify(mWifiVendorHal).flushRingBufferData();
1136     }
1137 
1138     /**
1139      * Tests that WifiNative#sendMgmtFrame() calls WificondControl#sendMgmtFrame()
1140      */
1141     @Test
testSendMgmtFrame()1142     public void testSendMgmtFrame() {
1143         mWifiNative.sendMgmtFrame(WIFI_IFACE_NAME, FATE_REPORT_FRAME_BYTES,
1144                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1145 
1146         verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME),
1147                 AdditionalMatchers.aryEq(FATE_REPORT_FRAME_BYTES), eq(TEST_MCS_RATE),
1148                 any(), eq(mSendMgmtFrameCallback));
1149     }
1150 
1151     /**
1152      * Tests that probeLink() generates the correct frame and calls WificondControl#sendMgmtFrame().
1153      */
1154     @Test
testProbeLinkSuccess()1155     public void testProbeLinkSuccess() {
1156         byte[] expectedFrame = {
1157                 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
1158                 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
1159                 (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
1160                 0x00, 0x00
1161         };
1162 
1163         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR);
1164 
1165         when(mRandom.nextInt()).thenReturn(TEST_SEQUENCE_NUM);
1166 
1167         mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR),
1168                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1169 
1170         verify(mSendMgmtFrameCallback, never()).onFailure(anyInt());
1171         verify(mWificondControl).sendMgmtFrame(eq(WIFI_IFACE_NAME),
1172                 AdditionalMatchers.aryEq(expectedFrame), eq(TEST_MCS_RATE),
1173                 any(), eq(mSendMgmtFrameCallback));
1174     }
1175 
1176     /**
1177      * Tests that probeLink() triggers the failure callback when it cannot get the sender MAC
1178      * address.
1179      */
1180     @Test
testProbeLinkFailureCannotGetSenderMac()1181     public void testProbeLinkFailureCannotGetSenderMac() {
1182         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
1183 
1184         mWifiNative.probeLink(WIFI_IFACE_NAME, MacAddress.fromString(TEST_BSSID_STR),
1185                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1186 
1187         verify(mSendMgmtFrameCallback).onFailure(
1188                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1189         verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any());
1190     }
1191 
1192     /**
1193      * Tests that probeLink() triggers the failure callback when it cannot get the BSSID.
1194      */
1195     @Test
testProbeLinkFailureCannotGetBssid()1196     public void testProbeLinkFailureCannotGetBssid() {
1197         when(mStaIfaceHal.getMacAddress(WIFI_IFACE_NAME)).thenReturn(TEST_MAC_ADDRESS_STR);
1198 
1199         mWifiNative.probeLink(WIFI_IFACE_NAME, null, mSendMgmtFrameCallback, TEST_MCS_RATE);
1200 
1201         verify(mSendMgmtFrameCallback).onFailure(
1202                 WifiNl80211Manager.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1203         verify(mWificondControl, never()).sendMgmtFrame(any(), any(), anyInt(), any(), any());
1204     }
1205 
1206     /**
1207      * Tests that WifiNative#addHlpReq() calls
1208      * SupplicantStaIfaceHal#addHlpReq()
1209      */
1210     @Test
testaddHlpReq()1211     public void testaddHlpReq() {
1212         byte[] hlpPacket = {
1213                 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
1214                 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
1215                 (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
1216                 0x00, 0x00
1217         };
1218         mWifiNative.addHlpReq(WIFI_IFACE_NAME, TEST_MAC_ADDRESS, hlpPacket);
1219 
1220         verify(mStaIfaceHal).addHlpReq(eq(WIFI_IFACE_NAME),
1221                 eq(TEST_MAC_ADDRESS.toByteArray()), eq(hlpPacket));
1222     }
1223 
1224     /**
1225      * Tests that WifiNative#flushAllHlp() calls
1226      * SupplicantStaIfaceHal#flushAllHlp()
1227      */
1228     @Test
testflushAllHlp()1229     public void testflushAllHlp() {
1230         mWifiNative.flushAllHlp(WIFI_IFACE_NAME);
1231 
1232         verify(mStaIfaceHal).flushAllHlp(eq(WIFI_IFACE_NAME));
1233     }
1234 
1235     @Test
testIsItPossibleToCreateIface()1236     public void testIsItPossibleToCreateIface() {
1237         // HAL not started
1238         when(mWifiVendorHal.isHalStarted()).thenReturn(false);
1239         // Using any() here since SparseArray doesn't support Object.equals().
1240         when(mWifiVendorHal.canDeviceSupportCreateTypeCombo(any())).thenReturn(true);
1241         when(mWifiVendorHal.isItPossibleToCreateStaIface(any())).thenReturn(false);
1242         assertTrue(mWifiNative.isItPossibleToCreateStaIface(new WorkSource()));
1243 
1244         when(mWifiVendorHal.isItPossibleToCreateApIface(any())).thenReturn(false);
1245         assertTrue(mWifiNative.isItPossibleToCreateApIface(new WorkSource()));
1246 
1247         when(mWifiVendorHal.isItPossibleToCreateBridgedApIface(any())).thenReturn(false);
1248         assertTrue(mWifiNative.isItPossibleToCreateBridgedApIface(new WorkSource()));
1249 
1250         // HAL started
1251         when(mWifiVendorHal.isHalStarted()).thenReturn(true);
1252         when(mWifiVendorHal.isItPossibleToCreateStaIface(any())).thenReturn(true);
1253         assertTrue(mWifiNative.isItPossibleToCreateStaIface(new WorkSource()));
1254 
1255         when(mWifiVendorHal.isItPossibleToCreateApIface(any())).thenReturn(true);
1256         assertTrue(mWifiNative.isItPossibleToCreateApIface(new WorkSource()));
1257 
1258         when(mWifiVendorHal.isItPossibleToCreateBridgedApIface(any())).thenReturn(true);
1259         assertTrue(mWifiNative.isItPossibleToCreateBridgedApIface(new WorkSource()));
1260     }
1261 
1262     @Test
testReplaceStaIfaceRequestorWs()1263     public void testReplaceStaIfaceRequestorWs() {
1264         assertEquals(WIFI_IFACE_NAME,
1265                 mWifiNative.setupInterfaceForClientInConnectivityMode(
1266                         mInterfaceCallback, TEST_WORKSOURCE));
1267         when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE2))
1268                 .thenReturn(true);
1269 
1270         assertTrue(mWifiNative.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE2));
1271         verify(mWifiVendorHal).replaceStaIfaceRequestorWs(
1272                 eq(WIFI_IFACE_NAME), same(TEST_WORKSOURCE2));
1273     }
1274 
1275     /**
1276      * Verifies that updateLinkedNetworks() calls underlying SupplicantStaIfaceHal.
1277      */
1278     @Test
testUpdateLinkedNetworks()1279     public void testUpdateLinkedNetworks() {
1280         when(mStaIfaceHal.updateLinkedNetworks(any(), anyInt(), any())).thenReturn(true);
1281 
1282         assertTrue(mWifiNative.updateLinkedNetworks(WIFI_IFACE_NAME, 0, null));
1283         verify(mStaIfaceHal).updateLinkedNetworks(WIFI_IFACE_NAME, 0, null);
1284     }
1285 
1286     /**
1287      * Verifies that getEapAnonymousIdentity() works as expected.
1288      */
1289     @Test
testGetEapAnonymousIdentity()1290     public void testGetEapAnonymousIdentity() {
1291         // Verify the empty use case
1292         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1293                 .thenReturn("");
1294         assertTrue(TextUtils.isEmpty(mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME)));
1295 
1296         // Verify with an anonymous identity
1297         final String anonymousId = "anonymous@homerealm.example.org";
1298         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1299                 .thenReturn(anonymousId);
1300         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1301 
1302         // Verify with a pseudonym identity
1303         final String pseudonymId = "a4624bc22490da3@homerealm.example.org";
1304         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1305                 .thenReturn(pseudonymId);
1306         assertEquals(pseudonymId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1307 
1308         // Verify that decorated anonymous identity is truncated
1309         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1310                 .thenReturn("otherrealm.example.net!" + anonymousId);
1311         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1312 
1313         // Verify that recursive decorated anonymous identity is truncated
1314         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1315                 .thenReturn("proxyrealm.example.com!otherrealm.example.net!" + anonymousId);
1316         assertEquals(anonymousId, mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1317 
1318         // Verify an invalid decoration with no identity use cases
1319         when(mStaIfaceHal.getCurrentNetworkEapAnonymousIdentity(WIFI_IFACE_NAME))
1320                 .thenReturn("otherrealm.example.net!");
1321         assertNull(mWifiNative.getEapAnonymousIdentity(WIFI_IFACE_NAME));
1322     }
1323 
1324 
1325     @Test
testCountryCodeChangedListener()1326     public void testCountryCodeChangedListener() {
1327         assumeTrue(SdkLevel.isAtLeastS());
1328         final String testCountryCode = "US";
1329         ArgumentCaptor<WifiNl80211Manager.CountryCodeChangedListener>
1330                 mCountryCodeChangedListenerCaptor = ArgumentCaptor.forClass(
1331                 WifiNl80211Manager.CountryCodeChangedListener.class);
1332         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1333         verify(mWificondControl).registerCountryCodeChangedListener(any(),
1334                 mCountryCodeChangedListenerCaptor.capture());
1335         mCountryCodeChangedListenerCaptor.getValue().onCountryCodeChanged(testCountryCode);
1336         verify(mWifiCountryCodeChangeListener).onDriverCountryCodeChanged(testCountryCode);
1337     }
1338 
1339     @Test
testSetStaCountryCodeSuccessful()1340     public void testSetStaCountryCodeSuccessful() {
1341         when(mStaIfaceHal.setCountryCode(any(), any())).thenReturn(true);
1342         final String testCountryCode = "US";
1343         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1344         mWifiNative.setStaCountryCode(WIFI_IFACE_NAME, testCountryCode);
1345         verify(mStaIfaceHal).setCountryCode(WIFI_IFACE_NAME, testCountryCode);
1346         if (SdkLevel.isAtLeastS()) {
1347             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1348         }
1349     }
1350 
1351     @Test
testSetStaCountryCodeFailure()1352     public void testSetStaCountryCodeFailure() {
1353         when(mStaIfaceHal.setCountryCode(any(), any())).thenReturn(false);
1354         final String testCountryCode = "US";
1355         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1356         mWifiNative.setStaCountryCode(WIFI_IFACE_NAME, testCountryCode);
1357         verify(mStaIfaceHal).setCountryCode(WIFI_IFACE_NAME, testCountryCode);
1358         if (SdkLevel.isAtLeastS()) {
1359             verify(mWifiCountryCodeChangeListener, never())
1360                     .onSetCountryCodeSucceeded(testCountryCode);
1361         }
1362     }
1363 
1364     /**
1365      * Verifies setEapAnonymousIdentity() sunny case.
1366      */
1367     @Test
testSetEapAnonymousIdentitySuccess()1368     public void testSetEapAnonymousIdentitySuccess() throws Exception {
1369         when(mStaIfaceHal.setEapAnonymousIdentity(any(), any())).thenReturn(true);
1370         final String anonymousIdentity = "abc@realm.com";
1371         assertTrue(mWifiNative.setEapAnonymousIdentity(WIFI_IFACE_NAME, anonymousIdentity));
1372         verify(mStaIfaceHal).setEapAnonymousIdentity(eq(WIFI_IFACE_NAME),
1373                 eq(anonymousIdentity));
1374     }
1375 
1376     /**
1377      * Verifies that setEapAnonymousIdentity() fails with null anonymous identity.
1378      */
1379     @Test
testSetEapAnonymousIdentityFailureWithNullString()1380     public void testSetEapAnonymousIdentityFailureWithNullString() throws Exception {
1381         when(mStaIfaceHal.setEapAnonymousIdentity(any(), any())).thenReturn(true);
1382         assertFalse(mWifiNative.setEapAnonymousIdentity(WIFI_IFACE_NAME, null));
1383         verify(mStaIfaceHal, never()).setEapAnonymousIdentity(any(), any());
1384     }
1385 
1386     @Test
testSetApCountryCodeSuccessful()1387     public void testSetApCountryCodeSuccessful() {
1388         when(mWifiVendorHal.setApCountryCode(any(), any())).thenReturn(true);
1389         final String testCountryCode = "US";
1390         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1391         mWifiNative.setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1392         verify(mWifiVendorHal).setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1393         if (SdkLevel.isAtLeastS()) {
1394             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1395         }
1396     }
1397 
1398     @Test
testSetApCountryCodeFailure()1399     public void testSetApCountryCodeFailure() {
1400         when(mWifiVendorHal.setApCountryCode(any(), any())).thenReturn(false);
1401         final String testCountryCode = "US";
1402         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1403         mWifiNative.setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1404         verify(mWifiVendorHal).setApCountryCode(WIFI_IFACE_NAME, testCountryCode);
1405         if (SdkLevel.isAtLeastS()) {
1406             verify(mWifiCountryCodeChangeListener, never())
1407                     .onSetCountryCodeSucceeded(testCountryCode);
1408         }
1409     }
1410 
1411     @Test
testSetChipCountryCodeSuccessful()1412     public void testSetChipCountryCodeSuccessful() {
1413         when(mWifiVendorHal.setChipCountryCode(any())).thenReturn(true);
1414         final String testCountryCode = "US";
1415         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1416         mWifiNative.setChipCountryCode(testCountryCode);
1417         verify(mWifiVendorHal).setChipCountryCode(testCountryCode);
1418         if (SdkLevel.isAtLeastS()) {
1419             verify(mWifiCountryCodeChangeListener).onSetCountryCodeSucceeded(testCountryCode);
1420         }
1421     }
1422 
1423     @Test
testSetChipCountryCodeFailure()1424     public void testSetChipCountryCodeFailure() {
1425         when(mWifiVendorHal.setChipCountryCode(any())).thenReturn(false);
1426         final String testCountryCode = "US";
1427         mWifiNative.registerCountryCodeEventListener(mWifiCountryCodeChangeListener);
1428         mWifiNative.setChipCountryCode(testCountryCode);
1429         verify(mWifiVendorHal).setChipCountryCode(testCountryCode);
1430         if (SdkLevel.isAtLeastS()) {
1431             verify(mWifiCountryCodeChangeListener, never())
1432                 .onSetCountryCodeSucceeded(testCountryCode);
1433         }
1434     }
1435 
1436     /**
1437      * Tests notifyWifiCondCountryCodeChanged
1438      */
1439     @Test
testNotifyWifiCondCountryCodeChanged()1440     public void testNotifyWifiCondCountryCodeChanged() throws Exception {
1441         assumeTrue(SdkLevel.isAtLeastT());
1442         String testCountryCode = "US";
1443         mWifiNative.countryCodeChanged(testCountryCode);
1444         verify(mWificondControl).notifyCountryCodeChanged(testCountryCode);
1445     }
1446 
1447     /**
1448      * Tests that getSupportedFeatureSet() guaranteed to include the feature set stored in config
1449      * store even when interface doesn't exist.
1450      *
1451      */
1452     @Test
testGetSupportedFeatureSetWhenInterfaceDoesntExist()1453     public void testGetSupportedFeatureSetWhenInterfaceDoesntExist() throws Exception {
1454         long featureSet = mWifiNative.getSupportedFeatureSet(null);
1455         assertEquals(featureSet, WIFI_TEST_FEATURE);
1456     }
1457 
1458     /**
1459      * Verifies that isSoftApInstanceDiedHandlerSupported() calls underlying HostapdHal.
1460      */
1461     @Test
testIsSoftApInstanceDiedHandlerSupported()1462     public void testIsSoftApInstanceDiedHandlerSupported() throws Exception {
1463         mWifiNative.isSoftApInstanceDiedHandlerSupported();
1464         verify(mHostapdHal).isSoftApInstanceDiedHandlerSupported();
1465     }
1466 }
1467