WifiStateMachineTest.java revision 9f8586ea6d640e86560efd9a2d9c1909b08a3ef4
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.wifi;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertTrue;
21import static org.mockito.Mockito.any;
22import static org.mockito.Mockito.anyBoolean;
23import static org.mockito.Mockito.anyInt;
24import static org.mockito.Mockito.anyObject;
25import static org.mockito.Mockito.anyString;
26import static org.mockito.Mockito.mock;
27import static org.mockito.Mockito.verify;
28import static org.mockito.Mockito.when;
29import static org.mockito.Mockito.withSettings;
30
31import android.content.ContentResolver;
32import android.content.Context;
33import android.content.pm.PackageManager;
34import android.content.res.Resources;
35import android.net.ConnectivityManager;
36import android.net.DhcpResults;
37import android.net.ip.IpManager;
38import android.net.LinkProperties;
39import android.net.wifi.ScanResult;
40import android.net.wifi.SupplicantState;
41import android.net.wifi.WifiConfiguration;
42import android.net.wifi.WifiManager;
43import android.net.wifi.WifiSsid;
44import android.net.wifi.p2p.IWifiP2pManager;
45import android.os.BatteryStats;
46import android.os.Handler;
47import android.os.HandlerThread;
48import android.os.IBinder;
49import android.os.IInterface;
50import android.os.INetworkManagementService;
51import android.os.IPowerManager;
52import android.os.Looper;
53import android.os.Message;
54import android.os.Messenger;
55import android.os.PowerManager;
56import android.os.UserHandle;
57import android.provider.Settings;
58import android.test.suitebuilder.annotation.SmallTest;
59import android.util.Log;
60
61import com.android.internal.R;
62import com.android.internal.app.IBatteryStats;
63import com.android.internal.util.AsyncChannel;
64import com.android.internal.util.IState;
65import com.android.internal.util.StateMachine;
66import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
67import com.android.server.wifi.hotspot2.NetworkDetail;
68import com.android.server.wifi.hotspot2.Utils;
69import com.android.server.wifi.p2p.WifiP2pServiceImpl;
70
71import org.junit.After;
72import org.junit.Before;
73import org.junit.Test;
74import org.mockito.Mock;
75import org.mockito.Mockito;
76import org.mockito.MockitoAnnotations;
77
78import java.io.ByteArrayOutputStream;
79import java.io.PrintWriter;
80import java.lang.reflect.Field;
81import java.lang.reflect.InvocationTargetException;
82import java.lang.reflect.Method;
83import java.util.ArrayList;
84import java.util.HashMap;
85import java.util.List;
86import java.util.Map;
87
88/**
89 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
90 */
91@SmallTest
92public class WifiStateMachineTest {
93    public static final String TAG = "WifiStateMachineTest";
94
95    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
96        return mock(class1, withSettings().extraInterfaces(interfaces));
97    }
98
99    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
100        T tImpl = mockWithInterfaces(class1, iface);
101        IBinder binder = mock(IBinder.class);
102        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
103        when(binder.queryLocalInterface(iface.getCanonicalName()))
104                .thenReturn((IInterface) tImpl);
105        return binder;
106    }
107
108    private void enableDebugLogs() {
109        mWsm.enableVerboseLogging(1);
110    }
111
112    private class TestIpManager extends IpManager {
113        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
114            // Call test-only superclass constructor.
115            super(ifname, callback);
116        }
117
118        @Override
119        public void startProvisioning() {}
120
121        @Override
122        public void stop() {}
123
124        @Override
125        public void confirmConfiguration() {}
126
127        void injectDhcpSuccess(DhcpResults dhcpResults) {
128            mCallback.onNewDhcpResults(dhcpResults);
129            mCallback.onProvisioningSuccess(new LinkProperties());
130        }
131
132        void injectDhcpFailure() {
133            mCallback.onNewDhcpResults(null);
134            mCallback.onProvisioningFailure(new LinkProperties());
135        }
136    }
137
138    private FrameworkFacade getFrameworkFacade() throws InterruptedException {
139        FrameworkFacade facade = mock(FrameworkFacade.class);
140
141        when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class));
142        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
143                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
144
145        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
146        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
147
148        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
149                IWifiP2pManager.class.getCanonicalName());
150
151        final Object sync = new Object();
152        synchronized (sync) {
153            mP2pThread = new HandlerThread("WifiP2pMockThread") {
154                @Override
155                protected void onLooperPrepared() {
156                    synchronized (sync) {
157                        sync.notifyAll();
158                    }
159                }
160            };
161
162            mP2pThread.start();
163            sync.wait();
164        }
165
166        Handler handler = new Handler(mP2pThread.getLooper());
167        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
168
169        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
170        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);
171
172        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
173                .then(new AnswerWithArguments() {
174                    public IpManager answer(
175                            Context context, String ifname, IpManager.Callback callback) {
176                        mTestIpManager = new TestIpManager(context, ifname, callback);
177                        return mTestIpManager;
178                    }
179                });
180
181        return facade;
182    }
183
184    private Context getContext() throws Exception {
185        PackageManager pkgMgr = mock(PackageManager.class);
186        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
187
188        Context context = mock(Context.class);
189        when(context.getPackageManager()).thenReturn(pkgMgr);
190        when(context.getContentResolver()).thenReturn(mock(ContentResolver.class));
191
192        MockResources resources = new com.android.server.wifi.MockResources();
193        when(context.getResources()).thenReturn(resources);
194
195        ContentResolver cr = mock(ContentResolver.class);
196        when(context.getContentResolver()).thenReturn(cr);
197
198        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
199                new PowerManager(context, mock(IPowerManager.class), new Handler()));
200
201        mAlarmManager = new MockAlarmManager();
202        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
203                mAlarmManager.getAlarmManager());
204
205        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
206                mock(ConnectivityManager.class));
207
208        return context;
209    }
210
211    private Resources getMockResources() {
212        MockResources resources = new MockResources();
213        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
214        return resources;
215    }
216
217    private IState getCurrentState() throws
218            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
219        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
220        method.setAccessible(true);
221        return (IState) method.invoke(mWsm);
222    }
223
224    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
225            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
226        Field field = StateMachine.class.getDeclaredField("mSmThread");
227        field.setAccessible(true);
228        return (HandlerThread) field.get(wsm);
229    }
230
231    private static void stopLooper(final Looper looper) throws Exception {
232        new Handler(looper).post(new Runnable() {
233            @Override
234            public void run() {
235                looper.quitSafely();
236            }
237        });
238    }
239
240    private void wait(int delayInMs) throws InterruptedException {
241        Looper looper = mWsmThread.getLooper();
242        final Handler handler = new Handler(looper);
243        synchronized (handler) {
244            handler.postDelayed(new Runnable() {
245                @Override
246                public void run() {
247                    synchronized (handler) {
248                        handler.notifyAll();
249                    }
250                }
251            }, delayInMs);
252
253            handler.wait();
254        }
255    }
256
257    private void dumpState() {
258        ByteArrayOutputStream stream = new ByteArrayOutputStream();
259        PrintWriter writer = new PrintWriter(stream);
260        mWsm.dump(null, writer, null);
261        writer.flush();
262        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
263    }
264
265    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
266        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
267        ie[0] = ScanResults.generateSsidIe(sSSID);
268        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
269        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
270                Long.MAX_VALUE /* needed so that scan results aren't rejected because
271                                  there older than scan start */);
272        return detail;
273    }
274
275    private ArrayList<ScanDetail> getMockScanResults() {
276        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
277        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
278
279        int rssi = -65;
280        list.add(getGoogleGuestScanDetail(rssi));
281        return list;
282    }
283
284    static final String   sSSID = "\"GoogleGuest\"";
285    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
286    static final String   sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
287    static final String   sBSSID = "01:02:03:04:05:06";
288    static final int      sFreq = 2437;
289
290    WifiStateMachine mWsm;
291    HandlerThread mWsmThread;
292    HandlerThread mP2pThread;
293    HandlerThread mSyncThread;
294    AsyncChannel  mWsmAsyncChannel;
295    MockAlarmManager mAlarmManager;
296    MockWifiMonitor mWifiMonitor;
297    TestIpManager mTestIpManager;
298
299    @Mock WifiNative mWifiNative;
300    @Mock SupplicantStateTracker mSupplicantStateTracker;
301    @Mock WifiMetrics mWifiMetrics;
302
303    public WifiStateMachineTest() throws Exception {
304    }
305
306    @Before
307    public void setUp() throws Exception {
308        Log.d(TAG, "Setting up ...");
309
310        // Ensure looper exists
311        MockLooper looper = new MockLooper();
312
313        MockitoAnnotations.initMocks(this);
314
315        /** uncomment this to enable logs from WifiStateMachines */
316        // enableDebugLogs();
317
318        TestUtil.installWlanWifiNative(mWifiNative);
319        mWifiMonitor = new MockWifiMonitor();
320        mWifiMetrics = mock(WifiMetrics.class);
321        FrameworkFacade factory = getFrameworkFacade();
322        Context context = getContext();
323
324        Resources resources = getMockResources();
325        when(context.getResources()).thenReturn(resources);
326
327        when(factory.getIntegerSetting(context,
328                Settings.Global.WIFI_FREQUENCY_BAND,
329                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
330                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
331
332        when(factory.makeApConfigStore(Mockito.eq(context)))
333                .thenCallRealMethod();
334
335        when(factory.makeSupplicantStateTracker(
336                any(Context.class), any(WifiStateMachine.class), any(WifiConfigStore.class),
337                any(Handler.class))).thenReturn(mSupplicantStateTracker);
338
339        mWsm = new WifiStateMachine(context, null, factory, mWifiMetrics);
340        mWsmThread = getWsmHandlerThread(mWsm);
341
342        final Object sync = new Object();
343        synchronized (sync) {
344            mSyncThread = new HandlerThread("SynchronizationThread");
345            final AsyncChannel channel = new AsyncChannel();
346            mSyncThread.start();
347            Handler handler = new Handler(mSyncThread.getLooper()) {
348                @Override
349                public void handleMessage(Message msg) {
350                    switch (msg.what) {
351                        case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
352                            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
353                                mWsmAsyncChannel = channel;
354                                synchronized (sync) {
355                                    sync.notifyAll();
356                                    Log.d(TAG, "Successfully connected " + this);
357                                }
358                            } else {
359                                Log.d(TAG, "Failed to connect Command channel " + this);
360                            }
361                            break;
362                        case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
363                            Log.d(TAG, "Command channel disconnected" + this);
364                            break;
365                    }
366                }
367            };
368
369            channel.connect(context, handler, mWsm.getMessenger());
370            sync.wait();
371        }
372
373        /* Now channel is supposed to be connected */
374    }
375
376    @After
377    public void cleanUp() throws Exception {
378
379        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
380        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
381        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
382
383        mWsmThread = null;
384        mP2pThread = null;
385        mSyncThread = null;
386        mWsmAsyncChannel = null;
387        mWsm = null;
388    }
389
390    @Test
391    public void createNew() throws Exception {
392        assertEquals("InitialState", getCurrentState().getName());
393
394        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
395        wait(200);
396        assertEquals("InitialState", getCurrentState().getName());
397    }
398
399    @Test
400    public void loadComponents() throws Exception {
401
402        when(mWifiNative.loadDriver()).thenReturn(true);
403        when(mWifiNative.startHal()).thenReturn(true);
404        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
405
406        mWsm.setSupplicantRunning(true);
407        wait(200);
408        assertEquals("SupplicantStartingState", getCurrentState().getName());
409
410        when(mWifiNative.setBand(anyInt())).thenReturn(true);
411        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
412        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
413        when(mWifiNative.setModelName(anyString())).thenReturn(true);
414        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
415        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
416        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
417        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
418        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
419        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
420        when(mWifiNative.enableBackgroundScan(anyBoolean(),
421                any(ArrayList.class))).thenReturn(true);
422
423        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
424        wait(200);
425        assertEquals("DisconnectedState", getCurrentState().getName());
426    }
427
428    @Test
429    public void loadComponentsFailure() throws Exception {
430        when(mWifiNative.loadDriver()).thenReturn(false);
431        when(mWifiNative.startHal()).thenReturn(false);
432        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false);
433
434        mWsm.setSupplicantRunning(true);
435        wait(200);
436        assertEquals("InitialState", getCurrentState().getName());
437
438        when(mWifiNative.loadDriver()).thenReturn(true);
439        mWsm.setSupplicantRunning(true);
440        wait(200);
441        assertEquals("InitialState", getCurrentState().getName());
442
443        when(mWifiNative.startHal()).thenReturn(true);
444        mWsm.setSupplicantRunning(true);
445        wait(200);
446        assertEquals("InitialState", getCurrentState().getName());
447    }
448
449    @Test
450    public void addNetwork() throws Exception {
451
452        loadComponents();
453
454        final HashMap<String, String> nameToValue = new HashMap<String, String>();
455
456        when(mWifiNative.addNetwork()).thenReturn(0);
457        when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString()))
458                .then(new AnswerWithArguments() {
459                    public boolean answer(int netId, String name, String value) {
460                        if (netId != 0) {
461                            Log.d(TAG, "Can't set var " + name + " for " + netId);
462                            return false;
463                        }
464
465                        Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId);
466                        nameToValue.put(name, value);
467                        return true;
468                    }
469                });
470
471        when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject()))
472                .then(new AnswerWithArguments() {
473                    public boolean answer(int netId, String name, Map<String, String> values) {
474                        if (netId != 0) {
475                            Log.d(TAG, "Can't set extra " + name + " for " + netId);
476                            return false;
477                        }
478
479                        Log.d(TAG, "Setting extra for " + netId);
480                        return true;
481                    }
482                });
483
484        when(mWifiNative.getNetworkVariable(anyInt(), anyString()))
485                .then(new AnswerWithArguments() {
486                    public String answer(int netId, String name) throws Throwable {
487                        if (netId != 0) {
488                            Log.d(TAG, "Can't find var " + name + " for " + netId);
489                            return null;
490                        }
491                        String value = nameToValue.get(name);
492                        if (value != null) {
493                            Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId);
494                        } else {
495                            Log.d(TAG, "Can't find var " + name + " for " + netId);
496                        }
497                        return value;
498                    }
499                });
500
501        WifiConfiguration config = new WifiConfiguration();
502        config.SSID = sSSID;
503        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
504        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
505        wait(200);
506
507        verify(mWifiNative).addNetwork();
508        verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID);
509
510        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
511        assertEquals(1, configs.size());
512
513        WifiConfiguration config2 = configs.get(0);
514        assertEquals("\"GoogleGuest\"", config2.SSID);
515        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
516    }
517
518    @Test
519    public void scan() throws Exception {
520
521        addNetwork();
522
523        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
524
525        mWsm.startScan(-1, 0, null, null);
526        wait(200);
527
528        verify(mWifiNative).scan(null);
529
530        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
531        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
532
533        wait(200);
534        List<ScanResult> results = mWsm.syncGetScanResultsList();
535        assertEquals(8, results.size());
536    }
537
538    @Test
539    public void connect() throws Exception {
540
541        addNetwork();
542
543        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
544        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
545        wait(200);
546
547        verify(mWifiNative).enableNetwork(0, true);
548
549        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
550        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
551                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
552        wait(200);
553
554        assertEquals("ObtainingIpState", getCurrentState().getName());
555
556        DhcpResults dhcpResults = new DhcpResults();
557        dhcpResults.setGateway("1.2.3.4");
558        dhcpResults.setIpAddress("192.168.1.100", 0);
559        dhcpResults.addDns("8.8.8.8");
560        dhcpResults.setLeaseDuration(3600);
561
562        mTestIpManager.injectDhcpSuccess(dhcpResults);
563        wait(200);
564
565        assertEquals("ConnectedState", getCurrentState().getName());
566    }
567
568    @Test
569    public void testDhcpFailure() throws Exception {
570        addNetwork();
571
572        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
573        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
574        wait(200);
575
576        verify(mWifiNative).enableNetwork(0, true);
577
578        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
579
580        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
581                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
582        wait(200);
583
584        assertEquals("ObtainingIpState", getCurrentState().getName());
585
586        mTestIpManager.injectDhcpFailure();
587        wait(200);
588
589        assertEquals("DisconnectingState", getCurrentState().getName());
590    }
591
592    @Test
593    public void testBadNetworkEvent() throws Exception {
594        addNetwork();
595
596        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
597        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
598        wait(200);
599
600        verify(mWifiNative).enableNetwork(0, true);
601
602        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
603
604        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
605                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
606        wait(200);
607
608        assertEquals("DisconnectedState", getCurrentState().getName());
609    }
610
611
612    @Test
613    public void disconnect() throws Exception {
614        connect();
615
616        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
617        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
618                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
619        wait(200);
620
621        assertEquals("DisconnectedState", getCurrentState().getName());
622    }
623
624    @Test
625    public void handleUserSwitch() throws Exception {
626        assertEquals(UserHandle.USER_SYSTEM, mWsm.getCurrentUserId());
627
628        mWsm.handleUserSwitch(10);
629        wait(200);
630
631        assertEquals(10, mWsm.getCurrentUserId());
632    }
633
634    @Test
635    public void iconQueryTest() throws Exception {
636        /* enable wi-fi */
637        addNetwork();
638
639        long bssid = 0x1234567800FFL;
640        String filename = "iconFileName.png";
641        String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename;
642
643        when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK");
644
645        boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename);
646
647        verify(mWifiNative).doCustomSupplicantCommand(command);
648        assertEquals(true, result);
649    }
650}
651