1 /*
2  * Copyright (C) 2017 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 package com.android.server.wifi;
17 
18 import static org.junit.Assert.*;
19 import static org.junit.Assume.assumeTrue;
20 import static org.mockito.Matchers.any;
21 import static org.mockito.Matchers.anyLong;
22 import static org.mockito.Matchers.anyString;
23 import static org.mockito.Matchers.eq;
24 import static org.mockito.Mockito.*;
25 
26 import android.app.test.MockAnswerUtil;
27 import android.content.Context;
28 import android.hardware.wifi.hostapd.V1_0.HostapdStatus;
29 import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode;
30 import android.hardware.wifi.hostapd.V1_0.IHostapd;
31 import android.hardware.wifi.hostapd.V1_1.IHostapdCallback;
32 import android.hardware.wifi.hostapd.V1_2.DebugLevel;
33 import android.hardware.wifi.hostapd.V1_3.Bandwidth;
34 import android.hardware.wifi.hostapd.V1_3.Generation;
35 import android.hidl.manager.V1_0.IServiceManager;
36 import android.hidl.manager.V1_0.IServiceNotification;
37 import android.net.MacAddress;
38 import android.net.wifi.SoftApConfiguration;
39 import android.net.wifi.SoftApConfiguration.Builder;
40 import android.net.wifi.WifiManager;
41 import android.os.Handler;
42 import android.os.IHwBinder;
43 import android.os.RemoteException;
44 import android.os.test.TestLooper;
45 import android.util.SparseIntArray;
46 
47 import androidx.test.filters.SmallTest;
48 
49 import com.android.modules.utils.build.SdkLevel;
50 import com.android.server.wifi.util.ApConfigUtil;
51 import com.android.server.wifi.util.NativeUtil;
52 import com.android.wifi.resources.R;
53 
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.mockito.ArgumentCaptor;
57 import org.mockito.InOrder;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 
61 import java.util.ArrayList;
62 
63 /**
64  * Unit tests for HostapdHal
65  */
66 @SmallTest
67 public class HostapdHalTest extends WifiBaseTest {
68     private static final String IFACE_NAME = "mock-wlan0";
69     private static final String NETWORK_SSID = "test-ssid";
70     private static final String NETWORK_PSK = "test-psk";
71     private static final String TEST_CLIENT_MAC = "11:22:33:44:55:66";
72     private static final String TEST_AP_INSTANCE = "instance-wlan0";
73 
74     private final int mBand256G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ
75             | SoftApConfiguration.BAND_6GHZ;
76 
77     private @Mock Context mContext;
78     private @Mock IServiceManager mServiceManagerMock;
79     private @Mock IHostapd mIHostapdMock;
80     private @Mock WifiNative.HostapdDeathEventHandler mHostapdHalDeathHandler;
81     private @Mock WifiNative.SoftApListener mSoftApListener;
82     private android.hardware.wifi.hostapd.V1_1.IHostapd mIHostapdMockV11;
83     private android.hardware.wifi.hostapd.V1_2.IHostapd mIHostapdMockV12;
84     private android.hardware.wifi.hostapd.V1_3.IHostapd mIHostapdMockV13;
85     private IHostapdCallback mIHostapdCallback;
86     private android.hardware.wifi.hostapd.V1_3.IHostapdCallback mIHostapdCallback13;
87     private MockResources mResources;
88     HostapdStatus mStatusSuccess;
89     HostapdStatus mStatusFailure;
90     android.hardware.wifi.hostapd.V1_2.HostapdStatus mStatusSuccess12;
91     android.hardware.wifi.hostapd.V1_2.HostapdStatus mStatusFailure12;
92     private TestLooper mLooper = new TestLooper();
93     private HostapdHal mHostapdHal;
94     private ArgumentCaptor<IHwBinder.DeathRecipient> mServiceManagerDeathCaptor =
95             ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
96     private ArgumentCaptor<IHwBinder.DeathRecipient> mHostapdDeathCaptor =
97             ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
98     private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor =
99             ArgumentCaptor.forClass(IServiceNotification.Stub.class);
100     private ArgumentCaptor<IHostapd.IfaceParams> mIfaceParamsCaptor =
101             ArgumentCaptor.forClass(IHostapd.IfaceParams.class);
102     private ArgumentCaptor<android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams>
103             mIfaceParamsCaptorV1_1 =
104             ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_1.IHostapd.IfaceParams.class);
105     private ArgumentCaptor<android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams>
106             mIfaceParamsCaptorV12 =
107             ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_2.IHostapd.IfaceParams.class);
108     private ArgumentCaptor<android.hardware.wifi.hostapd.V1_3.IHostapd.IfaceParams>
109             mIfaceParamsCaptorV13 =
110             ArgumentCaptor.forClass(android.hardware.wifi.hostapd.V1_3.IHostapd.IfaceParams.class);
111     private ArgumentCaptor<IHostapd.NetworkParams> mNetworkParamsCaptor =
112             ArgumentCaptor.forClass(IHostapd.NetworkParams.class);
113     private ArgumentCaptor<android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams>
114             mNetworkParamsV12Captor = ArgumentCaptor.forClass(
115             android.hardware.wifi.hostapd.V1_2.IHostapd.NetworkParams.class);
116     private ArgumentCaptor<android.hardware.wifi.hostapd.V1_3.IHostapd.NetworkParams>
117             mNetworkParamsV13Captor = ArgumentCaptor.forClass(
118             android.hardware.wifi.hostapd.V1_3.IHostapd.NetworkParams.class);
119     private ArgumentCaptor<Long> mDeathRecipientCookieCaptor = ArgumentCaptor.forClass(Long.class);
120     private InOrder mInOrder;
121 
122     private class HostapdHalSpy extends HostapdHal {
HostapdHalSpy()123         HostapdHalSpy() {
124             super(mContext, new Handler(mLooper.getLooper()));
125         }
126 
127         @Override
getServiceManagerMockable()128         protected IServiceManager getServiceManagerMockable() throws RemoteException {
129             return mServiceManagerMock;
130         }
131 
132         @Override
getHostapdMockable()133         protected IHostapd getHostapdMockable() throws RemoteException {
134             return mIHostapdMock;
135         }
136 
137         @Override
getHostapdMockableV1_1()138         protected android.hardware.wifi.hostapd.V1_1.IHostapd getHostapdMockableV1_1()
139                 throws RemoteException {
140             return mIHostapdMockV11;
141         }
142 
143         @Override
getHostapdMockableV1_2()144         protected android.hardware.wifi.hostapd.V1_2.IHostapd getHostapdMockableV1_2()
145                 throws RemoteException {
146             return mIHostapdMockV12;
147         }
148 
149         @Override
getHostapdMockableV1_3()150         protected android.hardware.wifi.hostapd.V1_3.IHostapd getHostapdMockableV1_3()
151                 throws RemoteException {
152             return mIHostapdMockV13;
153         }
154     }
155 
156     @Before
setUp()157     public void setUp() throws Exception {
158         MockitoAnnotations.initMocks(this);
159         mResources = new MockResources();
160         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
161         mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, false);
162         mResources.setBoolean(R.bool.config_wifiSoftapIeee80211axSupported, false);
163         mResources.setBoolean(R.bool.config_wifiSoftap6ghzSupported, false);
164         mResources.setBoolean(R.bool.config_wifiSoftapAcsIncludeDfs, false);
165         mResources.setString(R.string.config_wifiSoftap2gChannelList, "");
166         mResources.setString(R.string.config_wifiSoftap5gChannelList, "");
167         mResources.setString(R.string.config_wifiSoftap6gChannelList, "");
168 
169         mStatusSuccess = createHostapdStatus(HostapdStatusCode.SUCCESS);
170         mStatusFailure = createHostapdStatus(HostapdStatusCode.FAILURE_UNKNOWN);
171 
172 
173         mStatusSuccess12 = createHostapdStatus_1_2(HostapdStatusCode.SUCCESS);
174         mStatusFailure12 = createHostapdStatus_1_2(HostapdStatusCode.FAILURE_UNKNOWN);
175 
176         when(mContext.getResources()).thenReturn(mResources);
177         when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
178                 anyLong())).thenReturn(true);
179         when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
180                 any(IServiceNotification.Stub.class))).thenReturn(true);
181         when(mServiceManagerMock.getTransport(anyString(), anyString()))
182                 .thenReturn(IServiceManager.Transport.EMPTY);
183         when(mIHostapdMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
184                 anyLong())).thenReturn(true);
185         when(mIHostapdMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
186                 anyLong())).thenReturn(true);
187         when(mIHostapdMock.addAccessPoint(
188                 mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture()))
189                 .thenReturn(mStatusSuccess);
190         when(mIHostapdMock.removeAccessPoint(any())).thenReturn(mStatusSuccess);
191         mHostapdHal = new HostapdHalSpy();
192     }
193 
194     /**
195      * Sunny day scenario for HostapdHal initialization
196      * Asserts successful initialization
197      */
198     @Test
testInitialize_success()199     public void testInitialize_success() throws Exception {
200         executeAndValidateInitializationSequence(false, false);
201     }
202 
203     /**
204      * Failure scenario for HostapdHal initialization
205      */
206     @Test
testInitialize_registerException()207     public void testInitialize_registerException() throws Exception {
208         executeAndValidateInitializationSequence(true, false);
209     }
210 
211     /**
212      * Failure scenario for HostapdHal initialization
213      */
214     @Test
testInitialize_registerFailure()215     public void testInitialize_registerFailure() throws Exception {
216         executeAndValidateInitializationSequence(false, true);
217     }
218 
219     /**
220      * Sunny day scenario for V1.1 HostapdHal initialization
221      * Asserts successful initialization
222      */
223     @Test
testInitialize_successV1_1()224     public void testInitialize_successV1_1() throws Exception {
225         when(mServiceManagerMock.getTransport(eq(
226                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
227                 .thenReturn(IServiceManager.Transport.HWBINDER);
228         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
229         executeAndValidateInitializationSequenceV1_1(false);
230     }
231 
232     /**
233      * Failure scenario for V1.1 HostapdHal initialization
234      */
235     @Test
testInitialize_registerCallbackFailureV1_1()236     public void testInitialize_registerCallbackFailureV1_1() throws Exception {
237         when(mServiceManagerMock.getTransport(eq(
238                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
239                 .thenReturn(IServiceManager.Transport.HWBINDER);
240         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
241         executeAndValidateInitializationSequenceV1_1(true);
242     }
243 
244     /**
245      * Verifies the hostapd death handling.
246      */
247     @Test
testDeathHandling()248     public void testDeathHandling() throws Exception {
249         executeAndValidateInitializationSequence();
250 
251         mHostapdHal.registerDeathHandler(mHostapdHalDeathHandler);
252         mHostapdDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue());
253         mLooper.dispatchAll();
254         verify(mHostapdHalDeathHandler).onDeath();
255     }
256 
257     /**
258      * Verifies the hostapd death handling.
259      */
260     @Test
testStaleDeathHandling()261     public void testStaleDeathHandling() throws Exception {
262         executeAndValidateInitializationSequence();
263 
264         mHostapdHal.registerDeathHandler(mHostapdHalDeathHandler);
265         mHostapdDeathCaptor.getValue().serviceDied(mDeathRecipientCookieCaptor.getValue() - 1);
266         mLooper.dispatchAll();
267         verify(mHostapdHalDeathHandler, never()).onDeath();
268     }
269 
270     /**
271      * Verifies the successful addition of access point.
272      */
273     @Test
testAddAccessPointSuccess_Psk_Band2G()274     public void testAddAccessPointSuccess_Psk_Band2G() throws Exception {
275         executeAndValidateInitializationSequence();
276         final int apChannel = 6;
277 
278         Builder configurationBuilder = new SoftApConfiguration.Builder();
279         configurationBuilder.setSsid(NETWORK_SSID);
280         configurationBuilder.setHiddenSsid(false);
281         configurationBuilder.setPassphrase(NETWORK_PSK,
282                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
283         configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
284 
285         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
286                 configurationBuilder.build(), true,
287                 () -> mSoftApListener.onFailure()));
288         verify(mIHostapdMock).addAccessPoint(any(), any());
289 
290         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
291         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
292         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
293         assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band);
294         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
295         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
296         assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel);
297 
298         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
299                 mNetworkParamsCaptor.getValue().ssid);
300         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
301         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
302         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
303     }
304 
305     /**
306      * Verifies the successful addition of access point.
307      */
308     @Test
testAddAccessPointSuccess_Open_Band5G()309     public void testAddAccessPointSuccess_Open_Band5G() throws Exception {
310         executeAndValidateInitializationSequence();
311         final int apChannel = 149;
312 
313         Builder configurationBuilder = new SoftApConfiguration.Builder();
314         configurationBuilder.setSsid(NETWORK_SSID);
315         configurationBuilder.setHiddenSsid(true);
316         configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
317 
318         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
319                 configurationBuilder.build(), true,
320                 () -> mSoftApListener.onFailure()));
321         verify(mIHostapdMock).addAccessPoint(any(), any());
322 
323         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
324         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
325         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
326         assertEquals(IHostapd.Band.BAND_5_GHZ, mIfaceParamsCaptor.getValue().channelParams.band);
327         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
328         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
329         assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel);
330 
331         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
332                 mNetworkParamsCaptor.getValue().ssid);
333         assertTrue(mNetworkParamsCaptor.getValue().isHidden);
334         assertEquals(IHostapd.EncryptionType.NONE, mNetworkParamsCaptor.getValue().encryptionType);
335         assertNotNull(mNetworkParamsCaptor.getValue().pskPassphrase);
336     }
337 
338     /**
339      * Verifies the successful addition of access point.
340      */
341     @Test
testAddAccessPointSuccess_Psk_Band5G_Hidden()342     public void testAddAccessPointSuccess_Psk_Band5G_Hidden() throws Exception {
343         executeAndValidateInitializationSequence();
344         final int apChannel = 149;
345 
346         Builder configurationBuilder = new SoftApConfiguration.Builder();
347         configurationBuilder.setSsid(NETWORK_SSID);
348         configurationBuilder.setHiddenSsid(true);
349         configurationBuilder.setPassphrase(NETWORK_PSK,
350                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
351         configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_5GHZ);
352 
353         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
354                 configurationBuilder.build(), true,
355                 () -> mSoftApListener.onFailure()));
356         verify(mIHostapdMock).addAccessPoint(any(), any());
357 
358         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
359         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
360         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
361         assertEquals(IHostapd.Band.BAND_5_GHZ, mIfaceParamsCaptor.getValue().channelParams.band);
362         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
363         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
364         assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel);
365 
366         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
367                 mNetworkParamsCaptor.getValue().ssid);
368         assertTrue(mNetworkParamsCaptor.getValue().isHidden);
369         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
370         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
371     }
372 
373     /**
374      * Verifies the successful addition of access point.
375      */
376     @Test
testAddAccessPointSuccess_Psk_Band2G_WithACS()377     public void testAddAccessPointSuccess_Psk_Band2G_WithACS() throws Exception {
378         // Enable ACS in the config.
379         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
380         mHostapdHal = new HostapdHalSpy();
381 
382         executeAndValidateInitializationSequence();
383         final int apChannel = 6;
384 
385         Builder configurationBuilder = new SoftApConfiguration.Builder();
386         configurationBuilder.setSsid(NETWORK_SSID);
387         configurationBuilder.setHiddenSsid(false);
388         configurationBuilder.setPassphrase(NETWORK_PSK,
389                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
390         configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
391 
392         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
393                 configurationBuilder.build(), true,
394                 () -> mSoftApListener.onFailure()));
395         verify(mIHostapdMock).addAccessPoint(any(), any());
396 
397         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
398         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
399         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
400         assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band);
401         assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel);
402         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
403         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
404 
405         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
406                 mNetworkParamsCaptor.getValue().ssid);
407         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
408         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
409         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
410     }
411 
412     /**
413      * Verifies the successful addition of access point.
414      */
415     @Test
testAddAccessPointSuccess_Psk_Band2G_WithIeee80211AC()416     public void testAddAccessPointSuccess_Psk_Band2G_WithIeee80211AC() throws Exception {
417         // Enable ACS & 80211AC in the config.
418         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
419         mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, true);
420         mHostapdHal = new HostapdHalSpy();
421 
422         executeAndValidateInitializationSequence();
423         final int apChannel = 6;
424 
425         Builder configurationBuilder = new SoftApConfiguration.Builder();
426         configurationBuilder.setSsid(NETWORK_SSID);
427         configurationBuilder.setHiddenSsid(false);
428         configurationBuilder.setPassphrase(NETWORK_PSK,
429                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
430         configurationBuilder.setChannel(apChannel, SoftApConfiguration.BAND_2GHZ);
431 
432         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
433                 configurationBuilder.build(), true,
434                 () -> mSoftApListener.onFailure()));
435         verify(mIHostapdMock).addAccessPoint(any(), any());
436 
437         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
438         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
439         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
440         assertEquals(IHostapd.Band.BAND_2_4_GHZ, mIfaceParamsCaptor.getValue().channelParams.band);
441         assertEquals(apChannel, mIfaceParamsCaptor.getValue().channelParams.channel);
442         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
443         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
444 
445         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
446                 mNetworkParamsCaptor.getValue().ssid);
447         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
448         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
449         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
450     }
451 
452     /**
453      * Verifies the successful addition of access point.
454      */
455     @Test
testAddAccessPointSuccess_Psk_BandAny_WithACS()456     public void testAddAccessPointSuccess_Psk_BandAny_WithACS() throws Exception {
457         // Enable ACS in the config.
458         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
459         mHostapdHal = new HostapdHalSpy();
460 
461         executeAndValidateInitializationSequence();
462 
463         Builder configurationBuilder = new SoftApConfiguration.Builder();
464         configurationBuilder.setSsid(NETWORK_SSID);
465         configurationBuilder.setHiddenSsid(false);
466         configurationBuilder.setPassphrase(NETWORK_PSK,
467                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
468         configurationBuilder.setBand(mBand256G);
469 
470         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
471                 configurationBuilder.build(), true,
472                 () -> mSoftApListener.onFailure()));
473         verify(mIHostapdMock).addAccessPoint(any(), any());
474 
475         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
476         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
477         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
478         assertEquals(IHostapd.Band.BAND_ANY, mIfaceParamsCaptor.getValue().channelParams.band);
479         assertTrue(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
480         assertTrue(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
481 
482         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
483                 mNetworkParamsCaptor.getValue().ssid);
484         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
485         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
486         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
487     }
488 
489     /**
490      * Verifies the successful addition of access point.
491      */
492     @Test
testAddAccessPointSuccess_Psk_WithoutACS()493     public void testAddAccessPointSuccess_Psk_WithoutACS() throws Exception {
494         // Disable ACS in the config.
495         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
496         mHostapdHal = new HostapdHalSpy();
497 
498         executeAndValidateInitializationSequence();
499 
500         Builder configurationBuilder = new SoftApConfiguration.Builder();
501         configurationBuilder.setSsid(NETWORK_SSID);
502         configurationBuilder.setHiddenSsid(false);
503         configurationBuilder.setPassphrase(NETWORK_PSK,
504                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
505         configurationBuilder.setBand(mBand256G);
506 
507         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
508                 configurationBuilder.build(), true,
509                 () -> mSoftApListener.onFailure()));
510         verify(mIHostapdMock).addAccessPoint(any(), any());
511 
512         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
513         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
514         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
515         assertFalse(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
516 
517         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
518                 mNetworkParamsCaptor.getValue().ssid);
519         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
520         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
521         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
522     }
523 
524     /**
525      * Verifies the successful addition of access point.
526      * Verifies that channel info for ACS is handled.
527      */
528     @Test
testAddAccessPointSuccess_Psk_BandAny_WithACS_AcsChannels()529     public void testAddAccessPointSuccess_Psk_BandAny_WithACS_AcsChannels() throws Exception {
530         when(mServiceManagerMock.getTransport(eq(
531                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
532                 .thenReturn(IServiceManager.Transport.HWBINDER);
533         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
534         // Enable ACS and set available channels in the config.
535         final String acsChannelStr2g = "1,6,11-13";
536         final String acsChannelStr5g = "40";
537         final String acsChannelStr6g = "";
538         android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange1 =
539                 new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
540         android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange2 =
541                 new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
542         android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange3 =
543                 new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
544         android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange channelRange4 =
545                 new android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange();
546         channelRange1.start = channelRange1.end = 1;
547         channelRange2.start = channelRange2.end = 6;
548         channelRange3.start = 11;
549         channelRange3.end = 13;
550         channelRange4.start = channelRange4.end = 40;
551         ArrayList<android.hardware.wifi.hostapd.V1_1.IHostapd.AcsChannelRange> acsChannelRanges =
552                 new ArrayList<>();
553         acsChannelRanges.add(channelRange1);
554         acsChannelRanges.add(channelRange2);
555         acsChannelRanges.add(channelRange3);
556         acsChannelRanges.add(channelRange4);
557         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
558         mResources.setString(R.string.config_wifiSoftap2gChannelList, acsChannelStr2g);
559         mResources.setString(R.string.config_wifiSoftap5gChannelList, acsChannelStr5g);
560         mResources.setString(R.string.config_wifiSoftap6gChannelList, acsChannelStr6g);
561         mHostapdHal = new HostapdHalSpy();
562 
563         when(mIHostapdMockV11.addAccessPoint_1_1(
564                 mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture()))
565                 .thenReturn(mStatusSuccess);
566 
567         executeAndValidateInitializationSequenceV1_1(false);
568 
569         Builder configurationBuilder = new SoftApConfiguration.Builder();
570         configurationBuilder.setSsid(NETWORK_SSID);
571         configurationBuilder.setHiddenSsid(false);
572         configurationBuilder.setPassphrase(NETWORK_PSK,
573                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
574         configurationBuilder.setBand(mBand256G);
575 
576         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
577                 configurationBuilder.build(), true,
578                 () -> mSoftApListener.onFailure()));
579         verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any());
580 
581         assertEquals(IFACE_NAME, mIfaceParamsCaptorV1_1.getValue().V1_0.ifaceName);
582         assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211N);
583         assertFalse(mIfaceParamsCaptorV1_1.getValue().V1_0.hwModeParams.enable80211AC);
584         assertEquals(IHostapd.Band.BAND_ANY,
585                 mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.band);
586         assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.enableAcs);
587         assertTrue(mIfaceParamsCaptorV1_1.getValue().V1_0.channelParams.acsShouldExcludeDfs);
588         assertEquals(acsChannelRanges,
589                 mIfaceParamsCaptorV1_1.getValue().channelParams.acsChannelRanges);
590 
591         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
592                 mNetworkParamsCaptor.getValue().ssid);
593         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
594         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
595         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
596     }
597 
598     /**
599      * Verifies the failure handling in addition of access point.
600      */
601     @Test
testAddAccessPointFailure()602     public void testAddAccessPointFailure() throws Exception {
603         executeAndValidateInitializationSequence();
604         when(mIHostapdMock.addAccessPoint(any(), any())).thenReturn(mStatusFailure);
605 
606         Builder configurationBuilder = new SoftApConfiguration.Builder();
607         configurationBuilder.setSsid(NETWORK_SSID);
608         configurationBuilder.setHiddenSsid(true);
609         configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
610 
611         assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
612                 configurationBuilder.build(), true,
613                 () -> mSoftApListener.onFailure()));
614         verify(mIHostapdMock).addAccessPoint(any(), any());
615     }
616 
617     /**
618      * Verifies the failure handling in addition of access point.
619      */
620     @Test
testAddAccessPointRemoteException()621     public void testAddAccessPointRemoteException() throws Exception {
622         executeAndValidateInitializationSequence();
623         doThrow(new RemoteException()).when(mIHostapdMock).addAccessPoint(any(), any());
624 
625         Builder configurationBuilder = new SoftApConfiguration.Builder();
626         configurationBuilder.setSsid(NETWORK_SSID);
627         configurationBuilder.setHiddenSsid(true);
628         configurationBuilder.setChannel(6, SoftApConfiguration.BAND_2GHZ);
629 
630         assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
631                 configurationBuilder.build(), true,
632                 () -> mSoftApListener.onFailure()));
633         verify(mIHostapdMock).addAccessPoint(any(), any());
634     }
635 
636     /**
637      * Verifies the successful removal of access point.
638      */
639     @Test
testRemoveAccessPointSuccess()640     public void testRemoveAccessPointSuccess() throws Exception {
641         executeAndValidateInitializationSequence();
642 
643         assertTrue(mHostapdHal.removeAccessPoint(IFACE_NAME));
644         verify(mIHostapdMock).removeAccessPoint(any());
645     }
646 
647     /**
648      * Verifies the failure handling in removal of access point.
649      */
650     @Test
testRemoveAccessPointFailure()651     public void testRemoveAccessPointFailure() throws Exception {
652         executeAndValidateInitializationSequence();
653         when(mIHostapdMock.removeAccessPoint(any())).thenReturn(mStatusFailure);
654 
655         assertFalse(mHostapdHal.removeAccessPoint(IFACE_NAME));
656         verify(mIHostapdMock).removeAccessPoint(any());
657     }
658 
659     /**
660      * Verifies the failure handling in addition of access point.
661      */
662     @Test
testRemoveAccessPointRemoteException()663     public void testRemoveAccessPointRemoteException() throws Exception {
664         executeAndValidateInitializationSequence();
665         doThrow(new RemoteException()).when(mIHostapdMock).removeAccessPoint(any());
666 
667         assertFalse(mHostapdHal.removeAccessPoint(IFACE_NAME));
668         verify(mIHostapdMock).removeAccessPoint(any());
669     }
670 
671     /**
672      * Verifies the handling of onFailure callback from hostapd.
673      */
674     @Test
testOnFailureCallbackHandling()675     public void testOnFailureCallbackHandling() throws Exception {
676         when(mServiceManagerMock.getTransport(eq(
677                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
678                 .thenReturn(IServiceManager.Transport.HWBINDER);
679         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
680         when(mIHostapdMockV11.addAccessPoint_1_1(
681                 mIfaceParamsCaptorV1_1.capture(), mNetworkParamsCaptor.capture()))
682                 .thenReturn(mStatusSuccess);
683         executeAndValidateInitializationSequenceV1_1(false);
684 
685         Builder configurationBuilder = new SoftApConfiguration.Builder();
686         configurationBuilder.setSsid(NETWORK_SSID);
687         configurationBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
688 
689         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
690                 configurationBuilder.build(), true,
691                 () -> mSoftApListener.onFailure()));
692         verify(mIHostapdMockV11).addAccessPoint_1_1(any(), any());
693 
694         // Trigger on failure.
695         mIHostapdCallback.onFailure(IFACE_NAME);
696         verify(mSoftApListener).onFailure();
697 
698         // Now remove the access point and ensure that the callback is no longer handled.
699         reset(mSoftApListener);
700         assertTrue(mHostapdHal.removeAccessPoint(IFACE_NAME));
701         mIHostapdCallback.onFailure(IFACE_NAME);
702         verify(mSoftApListener, never()).onFailure();
703     }
704 
executeAndValidateInitializationSequence()705     private void executeAndValidateInitializationSequence() throws Exception {
706         executeAndValidateInitializationSequence(false, false);
707     }
708 
709     /**
710      * Calls.initialize() on HIDL 1.0, mocking various callback answers and verifying flow,
711      * asserting for the expected result. Verifies if IHostapd manager is initialized or reset.
712      */
executeAndValidateInitializationSequence( boolean causeRegisterRemoteException, boolean causeRegisterFailure)713     private void executeAndValidateInitializationSequence(
714             boolean causeRegisterRemoteException, boolean causeRegisterFailure) throws Exception {
715         boolean shouldSucceed = !causeRegisterRemoteException && !causeRegisterFailure;
716         mInOrder = inOrder(mServiceManagerMock, mIHostapdMock);
717         if (causeRegisterFailure) {
718             when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
719                     any(IServiceNotification.Stub.class))).thenReturn(false);
720         } else if (causeRegisterRemoteException) {
721             doThrow(new RemoteException()).when(mServiceManagerMock)
722                     .registerForNotifications(
723                             anyString(), anyString(), any(IServiceNotification.Stub.class));
724         }
725         // Initialize HostapdHal, should call serviceManager.registerForNotifications
726         assertEquals(shouldSucceed, mHostapdHal.initialize());
727         // verify: service manager initialization sequence
728         mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
729                 anyLong());
730         mInOrder.verify(mServiceManagerMock).registerForNotifications(
731                 eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
732         if (shouldSucceed) {
733             // act: cause the onRegistration(...) callback to execute
734             mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true);
735             assertTrue(mHostapdHal.isInitializationComplete());
736             mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(),
737                     mDeathRecipientCookieCaptor.capture());
738         } else {
739             assertFalse(mHostapdHal.isInitializationComplete());
740             mInOrder.verify(mIHostapdMock, never()).linkToDeath(
741                     mHostapdDeathCaptor.capture(), anyLong());
742         }
743     }
744 
745     /**
746      * Calls.initialize() on HIDL V1.1, mocking various callback answers and verifying flow,
747      * asserting for the expected result. Verifies if IHostapd manager is initialized or reset.
748      */
executeAndValidateInitializationSequenceV1_1( boolean causeCallbackFailure)749     private void executeAndValidateInitializationSequenceV1_1(
750             boolean causeCallbackFailure) throws Exception {
751         boolean shouldSucceed = !causeCallbackFailure;
752         mInOrder = inOrder(mServiceManagerMock, mIHostapdMock);
753         if (causeCallbackFailure) {
754             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
755                 public HostapdStatus answer(IHostapdCallback cb)
756                         throws RemoteException {
757                     return mStatusFailure;
758                 }
759             }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
760         } else {
761             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
762                 public HostapdStatus answer(IHostapdCallback cb)
763                         throws RemoteException {
764                     mIHostapdCallback = cb;
765                     return mStatusSuccess;
766                 }
767             }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
768         }
769         // Initialize HostapdHal, should call serviceManager.registerForNotifications
770         assertTrue(mHostapdHal.initialize());
771         // verify: service manager initialization sequence
772         mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
773                 anyLong());
774         mInOrder.verify(mServiceManagerMock).registerForNotifications(
775                 eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
776         // act: cause the onRegistration(...) callback to execute
777         mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true);
778         assertEquals(shouldSucceed, mHostapdHal.isInitializationComplete());
779         mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), anyLong());
780         verify(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
781     }
782 
783     /**
784      * Calls.initialize() on HIDL 1.2, mocking various callback answers and verifying flow,
785      * asserting for the expected result. Verifies if IHostapd manager is initialized or reset.
786      */
executeAndValidateInitializationSequenceV1_2( boolean causeCallbackFailure)787     private void executeAndValidateInitializationSequenceV1_2(
788             boolean causeCallbackFailure) throws Exception {
789         boolean shouldSucceed = !causeCallbackFailure;
790         mInOrder = inOrder(mServiceManagerMock, mIHostapdMock);
791         when(mIHostapdMockV12.setDebugParams(anyInt()))
792                 .thenReturn(mStatusSuccess12);
793         if (causeCallbackFailure) {
794             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
795                 public HostapdStatus answer(IHostapdCallback cb)
796                         throws RemoteException {
797                     return mStatusFailure;
798                 }
799             }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
800         } else {
801             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
802                 public HostapdStatus answer(IHostapdCallback cb)
803                         throws RemoteException {
804                     mIHostapdCallback = cb;
805                     return mStatusSuccess;
806                 }
807             }).when(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
808         }
809         // Initialize HostapdHal, should call serviceManager.registerForNotifications
810         assertTrue(mHostapdHal.initialize());
811         // verify: service manager initialization sequence
812         mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
813                 anyLong());
814         mInOrder.verify(mServiceManagerMock).registerForNotifications(
815                 eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
816         // act: cause the onRegistration(...) callback to execute
817         mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true);
818         assertEquals(shouldSucceed, mHostapdHal.isInitializationComplete());
819         mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), anyLong());
820         verify(mIHostapdMockV11).registerCallback(any(IHostapdCallback.class));
821     }
822 
823     /**
824      * Calls.initialize() on HIDL 1.3, mocking various callback answers and verifying flow,
825      * asserting for the expected result. Verifies if IHostapd manager is initialized or reset.
826      */
executeAndValidateInitializationSequenceV1_3( boolean causeCallbackFailure)827     private void executeAndValidateInitializationSequenceV1_3(
828             boolean causeCallbackFailure) throws Exception {
829         boolean shouldSucceed = !causeCallbackFailure;
830         mInOrder = inOrder(mServiceManagerMock, mIHostapdMock);
831         when(mIHostapdMockV12.setDebugParams(anyInt()))
832                 .thenReturn(mStatusSuccess12);
833         if (causeCallbackFailure) {
834             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
835                 public android.hardware.wifi.hostapd.V1_2.HostapdStatus answer(
836                         android.hardware.wifi.hostapd.V1_3.IHostapdCallback cb)
837                         throws RemoteException {
838                     return mStatusFailure12;
839                 }
840             }).when(mIHostapdMockV13).registerCallback_1_3(
841                     any(android.hardware.wifi.hostapd.V1_3.IHostapdCallback.class));
842         } else {
843             doAnswer(new MockAnswerUtil.AnswerWithArguments() {
844                 public android.hardware.wifi.hostapd.V1_2.HostapdStatus answer(
845                         android.hardware.wifi.hostapd.V1_3.IHostapdCallback cb)
846                         throws RemoteException {
847                     mIHostapdCallback13 = cb;
848                     return mStatusSuccess12;
849                 }
850             }).when(mIHostapdMockV13).registerCallback_1_3(
851                     any(android.hardware.wifi.hostapd.V1_3.IHostapdCallback.class));
852         }
853         // Initialize HostapdHal, should call serviceManager.registerForNotifications
854         assertTrue(mHostapdHal.initialize());
855         // verify: service manager initialization sequence
856         mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
857                 anyLong());
858         mInOrder.verify(mServiceManagerMock).registerForNotifications(
859                 eq(IHostapd.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
860         // act: cause the onRegistration(...) callback to execute
861         mServiceNotificationCaptor.getValue().onRegistration(IHostapd.kInterfaceName, "", true);
862         assertEquals(shouldSucceed, mHostapdHal.isInitializationComplete());
863         mInOrder.verify(mIHostapdMock).linkToDeath(mHostapdDeathCaptor.capture(), anyLong());
864         verify(mIHostapdMockV11, never()).registerCallback(any(IHostapdCallback.class));
865         verify(mIHostapdMockV13).registerCallback_1_3(
866                 any(android.hardware.wifi.hostapd.V1_3.IHostapdCallback.class));
867     }
868 
869     /**
870      * Calls.initialize() on last HIDL, mocking various callback answers and verifying flow,
871      * asserting for the expected result. Verifies if IHostapd manager is initialized or reset.
872      */
executeAndValidateInitializationSequenceOnLastHIDL( boolean causeCallbackFailure)873     private void executeAndValidateInitializationSequenceOnLastHIDL(
874             boolean causeCallbackFailure) throws Exception {
875         executeAndValidateInitializationSequenceV1_3(causeCallbackFailure);
876     }
877 
createHostapdStatus(int code)878     private HostapdStatus createHostapdStatus(int code) {
879         HostapdStatus status = new HostapdStatus();
880         status.code = code;
881         return status;
882     }
883 
createHostapdStatus_1_2(int code)884     private android.hardware.wifi.hostapd.V1_2.HostapdStatus createHostapdStatus_1_2(int code) {
885         android.hardware.wifi.hostapd.V1_2.HostapdStatus status =
886                 new android.hardware.wifi.hostapd.V1_2.HostapdStatus();
887         status.code = code;
888         return status;
889     }
890 
891     /**
892      * Verifies the successful execute forceClientDisconnect.
893      */
894     @Test
testForceClientDisconnectSuccess()895     public void testForceClientDisconnectSuccess() throws Exception {
896         executeAndValidateInitializationSequence();
897         when(mServiceManagerMock.getTransport(anyString(), anyString()))
898                 .thenReturn(IServiceManager.Transport.HWBINDER);
899         MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0");
900         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
901         when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort()))
902                 .thenReturn(mStatusSuccess12);
903 
904         assertTrue(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client,
905                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER));
906         verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort());
907     }
908 
909     @Test
testForceClientDisconnectFailureDueToInvalidArg()910     public void testForceClientDisconnectFailureDueToInvalidArg() throws Exception {
911         executeAndValidateInitializationSequence();
912         when(mServiceManagerMock.getTransport(anyString(), anyString()))
913                 .thenReturn(IServiceManager.Transport.HWBINDER);
914         MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0");
915         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
916         when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort()))
917                 .thenReturn(mStatusSuccess12);
918 
919         try {
920             mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, -1);
921             fail();
922         } catch (IllegalArgumentException e) {
923         }
924     }
925 
926     /**
927      * Verifies the failure handling in forceClientDisconnect.
928      */
929     @Test
testForceClientDisconnectFailure()930     public void testForceClientDisconnectFailure() throws Exception {
931         executeAndValidateInitializationSequence();
932         when(mServiceManagerMock.getTransport(anyString(), anyString()))
933                 .thenReturn(IServiceManager.Transport.HWBINDER);
934         MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0");
935         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
936         when(mIHostapdMockV12.forceClientDisconnect(any(), any(), anyShort()))
937                 .thenReturn(mStatusFailure12);
938 
939         assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client,
940                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER));
941         verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort());
942     }
943 
944     /**
945      * Verifies the exception handling in forceClientDisconnect.
946      */
947     @Test
testforceClientDisconnectRemoteException()948     public void testforceClientDisconnectRemoteException() throws Exception {
949         executeAndValidateInitializationSequence();
950         when(mServiceManagerMock.getTransport(anyString(), anyString()))
951                 .thenReturn(IServiceManager.Transport.HWBINDER);
952         MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0");
953         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
954         doThrow(new RemoteException()).when(mIHostapdMockV12)
955                 .forceClientDisconnect(any(), any(), anyShort());
956 
957         assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, 0));
958         verify(mIHostapdMockV12).forceClientDisconnect(any(), any(), anyShort());
959     }
960 
961     /**
962      * Verifies the HIDL not support handling in forceClientDisconnect.
963      */
964     @Test
testforceClientDisconnectHIDLNotSupport()965     public void testforceClientDisconnectHIDLNotSupport() throws Exception {
966         executeAndValidateInitializationSequence();
967         MacAddress test_client = MacAddress.fromString("da:a1:19:0:0:0");
968 
969         assertFalse(mHostapdHal.forceClientDisconnect(IFACE_NAME, test_client, 0));
970     }
971 
972     /**
973      * Verifies the setting of log level.
974      */
975     @Test
testSetLogLevel()976     public void testSetLogLevel() throws Exception {
977         executeAndValidateInitializationSequence();
978         when(mServiceManagerMock.getTransport(anyString(), anyString()))
979                 .thenReturn(IServiceManager.Transport.HWBINDER);
980         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
981         when(mIHostapdMockV12.setDebugParams(anyInt()))
982                 .thenReturn(mStatusSuccess12);
983 
984         mHostapdHal.enableVerboseLogging(true);
985         verify(mIHostapdMockV12)
986                 .setDebugParams(eq(DebugLevel.DEBUG));
987 
988         mHostapdHal.enableVerboseLogging(false);
989         verify(mIHostapdMockV12)
990                 .setDebugParams(eq(DebugLevel.INFO));
991     }
992 
993     /*
994      * Sunny day scenario for V1.2 HostapdHal initialization
995      * Asserts successful initialization
996      */
997     @Test
testInitialize_successV1_2()998     public void testInitialize_successV1_2() throws Exception {
999         when(mServiceManagerMock.getTransport(eq(
1000                 android.hardware.wifi.hostapd.V1_0.IHostapd.kInterfaceName), anyString()))
1001                 .thenReturn(IServiceManager.Transport.HWBINDER);
1002         when(mServiceManagerMock.getTransport(eq(
1003                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
1004                 .thenReturn(IServiceManager.Transport.HWBINDER);
1005         when(mServiceManagerMock.getTransport(eq(
1006                 android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName), anyString()))
1007                 .thenReturn(IServiceManager.Transport.HWBINDER);
1008         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1009         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1010         executeAndValidateInitializationSequenceV1_2(false);
1011     }
1012 
1013     /*
1014      * Sunny day scenario for V1.3 HostapdHal initialization
1015      * Asserts successful initialization
1016      */
1017     @Test
testInitialize_successV1_3()1018     public void testInitialize_successV1_3() throws Exception {
1019         when(mServiceManagerMock.getTransport(eq(
1020                 android.hardware.wifi.hostapd.V1_0.IHostapd.kInterfaceName), anyString()))
1021                 .thenReturn(IServiceManager.Transport.HWBINDER);
1022         when(mServiceManagerMock.getTransport(eq(
1023                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
1024                 .thenReturn(IServiceManager.Transport.HWBINDER);
1025         when(mServiceManagerMock.getTransport(eq(
1026                 android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName), anyString()))
1027                 .thenReturn(IServiceManager.Transport.HWBINDER);
1028         when(mServiceManagerMock.getTransport(eq(
1029                 android.hardware.wifi.hostapd.V1_3.IHostapd.kInterfaceName), anyString()))
1030                 .thenReturn(IServiceManager.Transport.HWBINDER);
1031         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1032         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1033         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1034         executeAndValidateInitializationSequenceV1_3(false);
1035     }
1036 
1037     /**
1038      * Failure scenario for V1.1 HostapdHal initialization
1039      */
1040     @Test
testInitialize_registerCallbackFailureV1_3()1041     public void testInitialize_registerCallbackFailureV1_3() throws Exception {
1042         when(mServiceManagerMock.getTransport(eq(
1043                 android.hardware.wifi.hostapd.V1_0.IHostapd.kInterfaceName), anyString()))
1044                 .thenReturn(IServiceManager.Transport.HWBINDER);
1045         when(mServiceManagerMock.getTransport(eq(
1046                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
1047                 .thenReturn(IServiceManager.Transport.HWBINDER);
1048         when(mServiceManagerMock.getTransport(eq(
1049                 android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName), anyString()))
1050                 .thenReturn(IServiceManager.Transport.HWBINDER);
1051         when(mServiceManagerMock.getTransport(eq(
1052                 android.hardware.wifi.hostapd.V1_3.IHostapd.kInterfaceName), anyString()))
1053                 .thenReturn(IServiceManager.Transport.HWBINDER);
1054         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1055         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1056         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1057         executeAndValidateInitializationSequenceV1_3(true);
1058     }
1059 
1060     /**
1061      * Verifies the successful addition of access point with SAE.
1062      */
1063     @Test
testAddAccessPointSuccess_SAE_WithoutACS()1064     public void testAddAccessPointSuccess_SAE_WithoutACS() throws Exception {
1065         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1066                 .thenReturn(IServiceManager.Transport.HWBINDER);
1067         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1068         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1069         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1070         // Disable ACS in the config.
1071         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
1072         mHostapdHal = new HostapdHalSpy();
1073 
1074         executeAndValidateInitializationSequenceOnLastHIDL(false);
1075 
1076         Builder configurationBuilder = new SoftApConfiguration.Builder();
1077         configurationBuilder.setSsid(NETWORK_SSID);
1078         configurationBuilder.setHiddenSsid(false);
1079         configurationBuilder.setPassphrase(NETWORK_PSK,
1080                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1081         configurationBuilder.setBand(mBand256G);
1082 
1083         when(mIHostapdMockV13.addAccessPoint_1_3(
1084                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1085                 .thenReturn(mStatusSuccess12);
1086 
1087 
1088         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1089                 configurationBuilder.build(), true,
1090                 () -> mSoftApListener.onFailure()));
1091         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1092 
1093         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1094         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1095         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1096         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1097 
1098         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1099                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1100         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1101         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1102                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1103         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1104         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1105     }
1106 
1107     /**
1108      * Verifies the successful addition of access point with SAE Transition.
1109      */
1110     @Test
testAddAccessPointSuccess_SAE_Transition_WithoutACS()1111     public void testAddAccessPointSuccess_SAE_Transition_WithoutACS() throws Exception {
1112         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1113                 .thenReturn(IServiceManager.Transport.HWBINDER);
1114         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1115         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1116         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1117         // Disable ACS in the config.
1118         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
1119         mHostapdHal = new HostapdHalSpy();
1120 
1121         executeAndValidateInitializationSequenceOnLastHIDL(false);
1122 
1123         Builder configurationBuilder = new SoftApConfiguration.Builder();
1124         configurationBuilder.setSsid(NETWORK_SSID);
1125         configurationBuilder.setHiddenSsid(false);
1126         configurationBuilder.setPassphrase(NETWORK_PSK,
1127                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
1128         configurationBuilder.setBand(mBand256G);
1129 
1130         when(mIHostapdMockV13.addAccessPoint_1_3(
1131                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1132                 .thenReturn(mStatusSuccess12);
1133 
1134 
1135         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1136                 configurationBuilder.build(), true,
1137                 () -> mSoftApListener.onFailure()));
1138         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1139 
1140         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1141         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1142         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1143         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1144 
1145         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1146                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1147         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1148         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE_TRANSITION,
1149                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1150         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1151         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1152     }
1153 
1154     /**
1155      * Verifies the failure handling addition of access point with SAE Transition in old hal.
1156      */
1157     @Test
testAddAccessPointFailure_SAEWithOldHal()1158     public void testAddAccessPointFailure_SAEWithOldHal() throws Exception {
1159         when(mServiceManagerMock.getTransport(eq(
1160                 android.hardware.wifi.hostapd.V1_0.IHostapd.kInterfaceName), anyString()))
1161                 .thenReturn(IServiceManager.Transport.HWBINDER);
1162         when(mServiceManagerMock.getTransport(eq(
1163                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
1164                 .thenReturn(IServiceManager.Transport.HWBINDER);
1165         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1166         // Disable ACS in the config.
1167         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false);
1168         mHostapdHal = new HostapdHalSpy();
1169 
1170         executeAndValidateInitializationSequenceV1_1(false);
1171 
1172         Builder configurationBuilder = new SoftApConfiguration.Builder();
1173         configurationBuilder.setSsid(NETWORK_SSID);
1174         configurationBuilder.setHiddenSsid(false);
1175         configurationBuilder.setPassphrase(NETWORK_PSK,
1176                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1177         configurationBuilder.setBand(mBand256G);
1178 
1179         assertFalse(mHostapdHal.addAccessPoint(IFACE_NAME,
1180                 configurationBuilder.build(), true,
1181                 () -> mSoftApListener.onFailure()));
1182     }
1183 
1184     /**
1185      * Verifies the successful addition of access point when ACS is allowed to include DFS channels.
1186      */
1187     @Test
testAddAccessPointSuccess_WithACS_IncludeDFSChannels()1188     public void testAddAccessPointSuccess_WithACS_IncludeDFSChannels() throws Exception {
1189         // Enable ACS in the config.
1190         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1191         mResources.setBoolean(R.bool.config_wifiSoftapAcsIncludeDfs, true);
1192         mHostapdHal = new HostapdHalSpy();
1193 
1194         executeAndValidateInitializationSequence();
1195 
1196         Builder configurationBuilder = new SoftApConfiguration.Builder();
1197         configurationBuilder.setSsid(NETWORK_SSID);
1198         configurationBuilder.setHiddenSsid(false);
1199         configurationBuilder.setPassphrase(NETWORK_PSK,
1200                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
1201         configurationBuilder.setBand(mBand256G);
1202 
1203         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1204                 configurationBuilder.build(), true,
1205                 () -> mSoftApListener.onFailure()));
1206         verify(mIHostapdMock).addAccessPoint(any(), any());
1207 
1208         assertEquals(IFACE_NAME, mIfaceParamsCaptor.getValue().ifaceName);
1209         assertTrue(mIfaceParamsCaptor.getValue().hwModeParams.enable80211N);
1210         assertFalse(mIfaceParamsCaptor.getValue().hwModeParams.enable80211AC);
1211         assertEquals(IHostapd.Band.BAND_ANY, mIfaceParamsCaptor.getValue().channelParams.band);
1212         assertTrue(mIfaceParamsCaptor.getValue().channelParams.enableAcs);
1213         assertFalse(mIfaceParamsCaptor.getValue().channelParams.acsShouldExcludeDfs);
1214 
1215         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1216                 mNetworkParamsCaptor.getValue().ssid);
1217         assertFalse(mNetworkParamsCaptor.getValue().isHidden);
1218         assertEquals(IHostapd.EncryptionType.WPA2, mNetworkParamsCaptor.getValue().encryptionType);
1219         assertEquals(NETWORK_PSK, mNetworkParamsCaptor.getValue().pskPassphrase);
1220     }
1221 
1222 
1223     /*
1224      * Sunny day scenario for V1.3 HostapdHal initialization
1225      * Asserts successful initialization
1226      */
1227     @Test
testHostapdCallbackEventAfter1_3()1228     public void testHostapdCallbackEventAfter1_3() throws Exception {
1229         when(mServiceManagerMock.getTransport(eq(
1230                 android.hardware.wifi.hostapd.V1_0.IHostapd.kInterfaceName), anyString()))
1231                 .thenReturn(IServiceManager.Transport.HWBINDER);
1232         when(mServiceManagerMock.getTransport(eq(
1233                 android.hardware.wifi.hostapd.V1_1.IHostapd.kInterfaceName), anyString()))
1234                 .thenReturn(IServiceManager.Transport.HWBINDER);
1235         when(mServiceManagerMock.getTransport(eq(
1236                 android.hardware.wifi.hostapd.V1_2.IHostapd.kInterfaceName), anyString()))
1237                 .thenReturn(IServiceManager.Transport.HWBINDER);
1238         when(mServiceManagerMock.getTransport(eq(
1239                 android.hardware.wifi.hostapd.V1_3.IHostapd.kInterfaceName), anyString()))
1240                 .thenReturn(IServiceManager.Transport.HWBINDER);
1241         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1242         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1243         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1244         executeAndValidateInitializationSequenceV1_3(false);
1245         Builder configurationBuilder = new SoftApConfiguration.Builder();
1246         configurationBuilder.setSsid(NETWORK_SSID);
1247         configurationBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
1248 
1249         when(mIHostapdMockV13.addAccessPoint_1_3(any(), any()))
1250                 .thenReturn(mStatusSuccess12);
1251         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1252                 configurationBuilder.build(), true,
1253                 () -> mSoftApListener.onFailure()));
1254         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1255 
1256         // Trigger on failure.
1257         mIHostapdCallback13.onFailure(IFACE_NAME);
1258         verify(mSoftApListener).onFailure();
1259         // Register SoftApManager callback
1260         mHostapdHal.registerApCallback(IFACE_NAME, mSoftApListener);
1261 
1262         int testFreq = 2412;
1263         int testBandwidth = Bandwidth.WIFI_BANDWIDTH_20;
1264         int testGeneration = Generation.WIFI_STANDARD_11N;
1265         // Trigger on info changed.
1266         mIHostapdCallback13.onApInstanceInfoChanged(IFACE_NAME, TEST_AP_INSTANCE,
1267                 testFreq, testBandwidth, testGeneration,
1268                 MacAddress.fromString(TEST_CLIENT_MAC).toByteArray());
1269         verify(mSoftApListener).onInfoChanged(eq(TEST_AP_INSTANCE), eq(testFreq),
1270                 eq(mHostapdHal.mapHalBandwidthToSoftApInfo(testBandwidth)),
1271                 eq(mHostapdHal.mapHalGenerationToWifiStandard(testGeneration)),
1272                 eq(MacAddress.fromString(TEST_CLIENT_MAC)));
1273 
1274         // Trigger on client connected.
1275         mIHostapdCallback13.onConnectedClientsChanged(IFACE_NAME, TEST_AP_INSTANCE,
1276                 MacAddress.fromString(TEST_CLIENT_MAC).toByteArray(), true);
1277         verify(mSoftApListener).onConnectedClientsChanged(eq(TEST_AP_INSTANCE),
1278                 eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true));
1279     }
1280 
1281     /**
1282      * Verifies the successful addition of access point with SAE with metered indication.
1283      */
1284     @Test
testAddAccessPointSuccess_WithMeteredSAE()1285     public void testAddAccessPointSuccess_WithMeteredSAE() throws Exception {
1286         boolean isMetered = true;
1287         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1288         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1289                 .thenReturn(IServiceManager.Transport.HWBINDER);
1290         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1291         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1292         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1293         mHostapdHal = new HostapdHalSpy();
1294 
1295         executeAndValidateInitializationSequenceOnLastHIDL(false);
1296 
1297         Builder configurationBuilder = new SoftApConfiguration.Builder();
1298         configurationBuilder.setSsid(NETWORK_SSID);
1299         configurationBuilder.setHiddenSsid(false);
1300         configurationBuilder.setPassphrase(NETWORK_PSK,
1301                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1302         configurationBuilder.setBand(mBand256G);
1303 
1304         when(mIHostapdMockV13.addAccessPoint_1_3(
1305                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1306                 .thenReturn(mStatusSuccess12);
1307 
1308 
1309         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1310                 configurationBuilder.build(), isMetered,
1311                 () -> mSoftApListener.onFailure()));
1312         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1313 
1314         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1315         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1316         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1317         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1318 
1319         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1320                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1321         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1322         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1323                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1324         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1325         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1326         assertTrue(mNetworkParamsV13Captor.getValue().isMetered);
1327     }
1328 
1329     /**
1330      * Verifies the successful addition of access point with SAE with non metered indication.
1331      */
1332     @Test
testAddAccessPointSuccess_WithNonMeteredSAE()1333     public void testAddAccessPointSuccess_WithNonMeteredSAE() throws Exception {
1334         boolean isMetered = false;
1335         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1336         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1337                 .thenReturn(IServiceManager.Transport.HWBINDER);
1338         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1339         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1340         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1341         mHostapdHal = new HostapdHalSpy();
1342 
1343         executeAndValidateInitializationSequenceOnLastHIDL(false);
1344 
1345         Builder configurationBuilder = new SoftApConfiguration.Builder();
1346         configurationBuilder.setSsid(NETWORK_SSID);
1347         configurationBuilder.setHiddenSsid(false);
1348         configurationBuilder.setPassphrase(NETWORK_PSK,
1349                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1350         configurationBuilder.setBand(mBand256G);
1351 
1352         when(mIHostapdMockV13.addAccessPoint_1_3(
1353                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1354                 .thenReturn(mStatusSuccess12);
1355 
1356 
1357         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1358                 configurationBuilder.build(), isMetered,
1359                 () -> mSoftApListener.onFailure()));
1360         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1361 
1362         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1363         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1364         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1365         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1366 
1367         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1368                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1369         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1370         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1371                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1372         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1373         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1374         assertFalse(mNetworkParamsV13Captor.getValue().isMetered);
1375     }
1376 
1377     /**
1378      * Verifies the successful addition of access point with Dual channel config.
1379      */
1380     @Test
testAddAccessPointSuccess_DualBandConfig()1381     public void testAddAccessPointSuccess_DualBandConfig() throws Exception {
1382         assumeTrue(SdkLevel.isAtLeastS()); // dual band supported on S.
1383         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1384         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1385                 .thenReturn(IServiceManager.Transport.HWBINDER);
1386         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1387         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1388         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1389         // Enable ACS and set available channels in the config.
1390         final String acsChannelStr2g = "1,6,11-13";
1391         final String acsChannelStr5g = "40";
1392         final String acsChannelStr6g = "";
1393         mResources.setString(R.string.config_wifiSoftap2gChannelList, acsChannelStr2g);
1394         mResources.setString(R.string.config_wifiSoftap5gChannelList, acsChannelStr5g);
1395         mResources.setString(R.string.config_wifiSoftap6gChannelList, acsChannelStr6g);
1396 
1397         android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange freqRange1 =
1398                 new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange();
1399         android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange freqRange2 =
1400                 new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange();
1401         android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange freqRange3 =
1402                 new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange();
1403         android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange freqRange4 =
1404                 new android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange();
1405 
1406         freqRange1.start = freqRange1.end = ApConfigUtil.convertChannelToFrequency(
1407                 1, SoftApConfiguration.BAND_2GHZ);
1408         freqRange2.start = freqRange2.end = ApConfigUtil.convertChannelToFrequency(
1409                 6, SoftApConfiguration.BAND_2GHZ);
1410         freqRange3.start = ApConfigUtil.convertChannelToFrequency(11,
1411                 SoftApConfiguration.BAND_2GHZ);
1412         freqRange3.end = ApConfigUtil.convertChannelToFrequency(13, SoftApConfiguration.BAND_2GHZ);
1413         ArrayList<android.hardware.wifi.hostapd.V1_2.IHostapd.AcsFrequencyRange> acsFreqRanges =
1414                 new ArrayList<>();
1415         acsFreqRanges.add(freqRange1);
1416         acsFreqRanges.add(freqRange2);
1417         acsFreqRanges.add(freqRange3);
1418 
1419         mHostapdHal = new HostapdHalSpy();
1420 
1421         executeAndValidateInitializationSequenceOnLastHIDL(false);
1422 
1423         SparseIntArray dual_channels = new SparseIntArray(2);
1424         dual_channels.put(SoftApConfiguration.BAND_5GHZ, 149);
1425         dual_channels.put(SoftApConfiguration.BAND_2GHZ, 0);
1426 
1427         Builder configurationBuilder = new SoftApConfiguration.Builder();
1428         configurationBuilder.setSsid(NETWORK_SSID);
1429         configurationBuilder.setHiddenSsid(false);
1430         configurationBuilder.setPassphrase(NETWORK_PSK,
1431                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1432         configurationBuilder.setChannels(dual_channels);
1433 
1434         when(mIHostapdMockV13.addAccessPoint_1_3(
1435                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1436                 .thenReturn(mStatusSuccess12);
1437 
1438 
1439         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1440                 configurationBuilder.build(), true,
1441                 () -> mSoftApListener.onFailure()));
1442         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1443 
1444         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1445         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1446         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1447         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.hwModeParams.enable80211AX);
1448         // 2.4G band, ACS case.
1449         assertTrue(mIfaceParamsCaptorV13.getValue().channelParamsList.get(0).enableAcs);
1450         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(0).V1_2.bandMask,
1451                 android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_2_GHZ);
1452         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(0).channel, 0);
1453         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(0)
1454                 .V1_2.acsChannelFreqRangesMhz, acsFreqRanges);
1455         // 5G band, specific channel.
1456         assertFalse(mIfaceParamsCaptorV13.getValue().channelParamsList.get(1).enableAcs);
1457         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(1).V1_2.bandMask,
1458                 android.hardware.wifi.hostapd.V1_2.IHostapd.BandMask.BAND_5_GHZ);
1459         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(1).channel, 149);
1460         // No acsChannelFreqRangesMh
1461         assertEquals(mIfaceParamsCaptorV13.getValue().channelParamsList.get(1)
1462                 .V1_2.acsChannelFreqRangesMhz.size(), 0);
1463 
1464         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1465                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1466         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1467         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1468                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1469         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1470         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1471     }
1472 
1473     /**
1474      * Verifies the successful addition of access point with metered SAE indication on the 80211ax
1475      * supported device.
1476      */
1477     @Test
testAddAccessPointSuccess_WithMeteredSAEOn11AXSupportedDevice()1478     public void testAddAccessPointSuccess_WithMeteredSAEOn11AXSupportedDevice()
1479             throws Exception {
1480         boolean isMetered = true;
1481         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1482         mResources.setBoolean(R.bool.config_wifiSoftapIeee80211axSupported, true);
1483         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1484                 .thenReturn(IServiceManager.Transport.HWBINDER);
1485         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1486         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1487         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1488         mHostapdHal = new HostapdHalSpy();
1489 
1490         executeAndValidateInitializationSequenceOnLastHIDL(false);
1491 
1492         Builder configurationBuilder = new SoftApConfiguration.Builder();
1493         configurationBuilder.setSsid(NETWORK_SSID);
1494         configurationBuilder.setHiddenSsid(false);
1495         configurationBuilder.setPassphrase(NETWORK_PSK,
1496                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1497         configurationBuilder.setBand(mBand256G);
1498 
1499         when(mIHostapdMockV13.addAccessPoint_1_3(
1500                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1501                 .thenReturn(mStatusSuccess12);
1502 
1503 
1504         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1505                 configurationBuilder.build(), isMetered,
1506                 () -> mSoftApListener.onFailure()));
1507         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1508 
1509         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1510         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1511         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1512         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.hwModeParams.enable80211AX);
1513         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1514 
1515         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1516                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1517         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1518         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1519                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1520         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1521         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1522         assertTrue(mNetworkParamsV13Captor.getValue().isMetered);
1523     }
1524 
1525     /**
1526      * Verifies the successful addition of access point with metered SAE indication on the 80211ax
1527      * supported device but 80211ax is disabled in configuration.
1528      */
1529     @Test
testAddAccessPointSuccess_WithMeteredSAEOn11AXSupportedDeviceBut11AXDisabled()1530     public void testAddAccessPointSuccess_WithMeteredSAEOn11AXSupportedDeviceBut11AXDisabled()
1531             throws Exception {
1532         assumeTrue(SdkLevel.isAtLeastS()); // setIeee80211axEnabled() added on Android S.
1533         boolean isMetered = true;
1534         mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, true);
1535         mResources.setBoolean(R.bool.config_wifiSoftapIeee80211axSupported, true);
1536         when(mServiceManagerMock.getTransport(anyString(), anyString()))
1537                 .thenReturn(IServiceManager.Transport.HWBINDER);
1538         mIHostapdMockV11 = mock(android.hardware.wifi.hostapd.V1_1.IHostapd.class);
1539         mIHostapdMockV12 = mock(android.hardware.wifi.hostapd.V1_2.IHostapd.class);
1540         mIHostapdMockV13 = mock(android.hardware.wifi.hostapd.V1_3.IHostapd.class);
1541         mHostapdHal = new HostapdHalSpy();
1542 
1543         executeAndValidateInitializationSequenceOnLastHIDL(false);
1544 
1545         Builder configurationBuilder = new SoftApConfiguration.Builder();
1546         configurationBuilder.setSsid(NETWORK_SSID);
1547         configurationBuilder.setHiddenSsid(false);
1548         configurationBuilder.setPassphrase(NETWORK_PSK,
1549                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
1550         configurationBuilder.setBand(mBand256G);
1551         configurationBuilder.setIeee80211axEnabled(false);
1552 
1553         when(mIHostapdMockV13.addAccessPoint_1_3(
1554                 mIfaceParamsCaptorV13.capture(), mNetworkParamsV13Captor.capture()))
1555                 .thenReturn(mStatusSuccess12);
1556 
1557 
1558         assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME,
1559                 configurationBuilder.build(), isMetered,
1560                 () -> mSoftApListener.onFailure()));
1561         verify(mIHostapdMockV13).addAccessPoint_1_3(any(), any());
1562 
1563         assertEquals(IFACE_NAME, mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.ifaceName);
1564         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211N);
1565         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.hwModeParams.enable80211AC);
1566         assertFalse(mIfaceParamsCaptorV13.getValue().V1_2.hwModeParams.enable80211AX);
1567         assertTrue(mIfaceParamsCaptorV13.getValue().V1_2.V1_1.V1_0.channelParams.enableAcs);
1568 
1569         assertEquals(NativeUtil.stringToByteArrayList(NETWORK_SSID),
1570                 mNetworkParamsV13Captor.getValue().V1_2.V1_0.ssid);
1571         assertFalse(mNetworkParamsV13Captor.getValue().V1_2.V1_0.isHidden);
1572         assertEquals(android.hardware.wifi.hostapd.V1_2.IHostapd.EncryptionType.WPA3_SAE,
1573                 mNetworkParamsV13Captor.getValue().V1_2.encryptionType);
1574         assertEquals(NETWORK_PSK, mNetworkParamsV13Captor.getValue().V1_2.passphrase);
1575         assertEquals("", mNetworkParamsV13Captor.getValue().V1_2.V1_0.pskPassphrase);
1576         assertTrue(mNetworkParamsV13Captor.getValue().isMetered);
1577     }
1578 }
1579 
1580