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 
17 package com.android.server.wifi;
18 
19 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
20 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
21 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
22 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE;
23 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
24 
25 import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION;
26 
27 import static org.junit.Assert.assertArrayEquals;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertNotEquals;
31 import static org.junit.Assert.assertNotNull;
32 import static org.junit.Assert.assertNull;
33 import static org.junit.Assert.assertTrue;
34 import static org.mockito.Mockito.any;
35 import static org.mockito.Mockito.anyBoolean;
36 import static org.mockito.Mockito.anyByte;
37 import static org.mockito.Mockito.anyInt;
38 import static org.mockito.Mockito.anyLong;
39 import static org.mockito.Mockito.anyObject;
40 import static org.mockito.Mockito.anyString;
41 import static org.mockito.Mockito.argThat;
42 import static org.mockito.Mockito.atLeastOnce;
43 import static org.mockito.Mockito.doAnswer;
44 import static org.mockito.Mockito.doReturn;
45 import static org.mockito.Mockito.eq;
46 import static org.mockito.Mockito.inOrder;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.never;
49 import static org.mockito.Mockito.reset;
50 import static org.mockito.Mockito.spy;
51 import static org.mockito.Mockito.times;
52 import static org.mockito.Mockito.verify;
53 import static org.mockito.Mockito.verifyNoMoreInteractions;
54 import static org.mockito.Mockito.when;
55 import static org.mockito.Mockito.withSettings;
56 
57 import android.app.ActivityManager;
58 import android.app.test.MockAnswerUtil.AnswerWithArguments;
59 import android.app.test.TestAlarmManager;
60 import android.bluetooth.BluetoothAdapter;
61 import android.content.Context;
62 import android.content.Intent;
63 import android.content.pm.PackageManager;
64 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
65 import android.net.ConnectivityManager;
66 import android.net.DhcpResultsParcelable;
67 import android.net.InetAddresses;
68 import android.net.Layer2InformationParcelable;
69 import android.net.Layer2PacketParcelable;
70 import android.net.LinkAddress;
71 import android.net.LinkProperties;
72 import android.net.MacAddress;
73 import android.net.Network;
74 import android.net.NetworkAgent;
75 import android.net.NetworkAgentConfig;
76 import android.net.NetworkCapabilities;
77 import android.net.NetworkInfo;
78 import android.net.NetworkSpecifier;
79 import android.net.StaticIpConfiguration;
80 import android.net.ip.IIpClient;
81 import android.net.ip.IpClientCallbacks;
82 import android.net.wifi.IActionListener;
83 import android.net.wifi.ScanResult;
84 import android.net.wifi.SupplicantState;
85 import android.net.wifi.WifiConfiguration;
86 import android.net.wifi.WifiConfiguration.KeyMgmt;
87 import android.net.wifi.WifiEnterpriseConfig;
88 import android.net.wifi.WifiInfo;
89 import android.net.wifi.WifiManager;
90 import android.net.wifi.WifiNetworkAgentSpecifier;
91 import android.net.wifi.WifiScanner;
92 import android.net.wifi.WifiSsid;
93 import android.net.wifi.hotspot2.IProvisioningCallback;
94 import android.net.wifi.hotspot2.OsuProvider;
95 import android.net.wifi.nl80211.WifiNl80211Manager;
96 import android.net.wifi.p2p.WifiP2pManager;
97 import android.os.BatteryStatsManager;
98 import android.os.Binder;
99 import android.os.Bundle;
100 import android.os.Handler;
101 import android.os.HandlerThread;
102 import android.os.IBinder;
103 import android.os.IPowerManager;
104 import android.os.IThermalService;
105 import android.os.Looper;
106 import android.os.Message;
107 import android.os.Messenger;
108 import android.os.PowerManager;
109 import android.os.Process;
110 import android.os.UserManager;
111 import android.os.test.TestLooper;
112 import android.provider.Settings;
113 import android.telephony.SubscriptionInfo;
114 import android.telephony.SubscriptionManager;
115 import android.telephony.TelephonyManager;
116 import android.test.mock.MockContentProvider;
117 import android.test.mock.MockContentResolver;
118 import android.util.Log;
119 import android.util.Pair;
120 
121 import androidx.test.filters.SmallTest;
122 
123 import com.android.dx.mockito.inline.extended.ExtendedMockito;
124 import com.android.internal.util.AsyncChannel;
125 import com.android.internal.util.IState;
126 import com.android.internal.util.StateMachine;
127 import com.android.server.wifi.hotspot2.NetworkDetail;
128 import com.android.server.wifi.hotspot2.PasspointManager;
129 import com.android.server.wifi.hotspot2.PasspointProvisioningTestUtil;
130 import com.android.server.wifi.proto.nano.WifiMetricsProto;
131 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
132 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
133 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
134 import com.android.server.wifi.util.RssiUtilTest;
135 import com.android.server.wifi.util.ScanResultUtil;
136 import com.android.server.wifi.util.WifiPermissionsUtil;
137 import com.android.server.wifi.util.WifiPermissionsWrapper;
138 import com.android.wifi.resources.R;
139 
140 import org.junit.After;
141 import org.junit.Before;
142 import org.junit.Test;
143 import org.mockito.ArgumentCaptor;
144 import org.mockito.ArgumentMatcher;
145 import org.mockito.InOrder;
146 import org.mockito.Mock;
147 import org.mockito.MockitoAnnotations;
148 import org.mockito.MockitoSession;
149 import org.mockito.quality.Strictness;
150 
151 import java.io.ByteArrayOutputStream;
152 import java.io.PrintWriter;
153 import java.lang.reflect.Field;
154 import java.lang.reflect.InvocationTargetException;
155 import java.lang.reflect.Method;
156 import java.nio.charset.StandardCharsets;
157 import java.util.ArrayList;
158 import java.util.Arrays;
159 import java.util.BitSet;
160 import java.util.Collections;
161 import java.util.List;
162 import java.util.concurrent.CountDownLatch;
163 import java.util.function.Consumer;
164 
165 /**
166  * Unit tests for {@link com.android.server.wifi.ClientModeImpl}.
167  */
168 @SmallTest
169 public class ClientModeImplTest extends WifiBaseTest {
170     public static final String TAG = "ClientModeImplTest";
171 
172     private static final int MANAGED_PROFILE_UID = 1100000;
173     private static final int OTHER_USER_UID = 1200000;
174     private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
175             (ActivityManager.isLowRamDeviceStatic()
176                     ? ClientModeImpl.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
177                     : ClientModeImpl.NUM_LOG_RECS_VERBOSE);
178     private static final int FRAMEWORK_NETWORK_ID = 0;
179     private static final int PASSPOINT_NETWORK_ID = 1;
180     private static final int TEST_RSSI = -54;
181     private static final int TEST_NETWORK_ID = 54;
182     private static final int WPS_SUPPLICANT_NETWORK_ID = 5;
183     private static final int WPS_FRAMEWORK_NETWORK_ID = 10;
184     private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
185     private static final String OP_PACKAGE_NAME = "com.xxx";
186     private static final int TEST_UID = Process.SYSTEM_UID + 1000;
187     private static final MacAddress TEST_GLOBAL_MAC_ADDRESS =
188             MacAddress.fromString("10:22:34:56:78:92");
189     private static final MacAddress TEST_LOCAL_MAC_ADDRESS =
190             MacAddress.fromString("2a:53:43:c3:56:21");
191     private static final MacAddress TEST_DEFAULT_MAC_ADDRESS =
192             MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
193 
194     // NetworkAgent creates threshold ranges with Integers
195     private static final int RSSI_THRESHOLD_MAX = -30;
196     private static final int RSSI_THRESHOLD_MIN = -76;
197     // Threshold breach callbacks are called with bytes
198     private static final byte RSSI_THRESHOLD_BREACH_MIN = -80;
199     private static final byte RSSI_THRESHOLD_BREACH_MAX = -20;
200 
201     private static final int DATA_SUBID = 1;
202     private static final int CARRIER_ID_1 = 100;
203 
204     private long mBinderToken;
205     private MockitoSession mSession;
206 
mockWithInterfaces(Class<T> class1, Class<?>... interfaces)207     private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
208         return mock(class1, withSettings().extraInterfaces(interfaces));
209     }
210 
enableDebugLogs()211     private void enableDebugLogs() {
212         mCmi.enableVerboseLogging(1);
213     }
214 
getFrameworkFacade()215     private FrameworkFacade getFrameworkFacade() throws Exception {
216         FrameworkFacade facade = mock(FrameworkFacade.class);
217 
218         doAnswer(new AnswerWithArguments() {
219             public void answer(
220                     Context context, String ifname, IpClientCallbacks callback) {
221                 mIpClientCallback = callback;
222                 callback.onIpClientCreated(mIpClient);
223             }
224         }).when(facade).makeIpClient(any(), anyString(), any());
225 
226         return facade;
227     }
228 
getContext()229     private Context getContext() throws Exception {
230         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
231 
232         Context context = mock(Context.class);
233         when(context.getPackageManager()).thenReturn(mPackageManager);
234 
235         MockContentResolver mockContentResolver = new MockContentResolver();
236         mockContentResolver.addProvider(Settings.AUTHORITY,
237                 new MockContentProvider(context) {
238                     @Override
239                     public Bundle call(String method, String arg, Bundle extras) {
240                         return new Bundle();
241                     }
242                 });
243         when(context.getContentResolver()).thenReturn(mockContentResolver);
244 
245         when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
246                 new PowerManager(context, mock(IPowerManager.class), mock(IThermalService.class),
247                     new Handler()));
248 
249         mAlarmManager = new TestAlarmManager();
250         when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
251                 mAlarmManager.getAlarmManager());
252 
253         when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
254                 mConnectivityManager);
255 
256         when(context.getOpPackageName()).thenReturn(OP_PACKAGE_NAME);
257 
258         when(context.getSystemService(ActivityManager.class)).thenReturn(
259                 mock(ActivityManager.class));
260 
261         WifiP2pManager p2pm = mock(WifiP2pManager.class);
262         when(context.getSystemService(WifiP2pManager.class)).thenReturn(p2pm);
263         final CountDownLatch untilDone = new CountDownLatch(1);
264         mP2pThread = new HandlerThread("WifiP2pMockThread") {
265             @Override
266             protected void onLooperPrepared() {
267                 untilDone.countDown();
268             }
269         };
270         mP2pThread.start();
271         untilDone.await();
272         Handler handler = new Handler(mP2pThread.getLooper());
273         when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
274 
275         return context;
276     }
277 
getMockResources()278     private MockResources getMockResources() {
279         MockResources resources = new MockResources();
280         return resources;
281     }
282 
getCurrentState()283     private IState getCurrentState() throws
284             NoSuchMethodException, InvocationTargetException, IllegalAccessException {
285         Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
286         method.setAccessible(true);
287         return (IState) method.invoke(mCmi);
288     }
289 
getCmiHandlerThread(ClientModeImpl cmi)290     private static HandlerThread getCmiHandlerThread(ClientModeImpl cmi) throws
291             NoSuchFieldException, InvocationTargetException, IllegalAccessException {
292         Field field = StateMachine.class.getDeclaredField("mSmThread");
293         field.setAccessible(true);
294         return (HandlerThread) field.get(cmi);
295     }
296 
stopLooper(final Looper looper)297     private static void stopLooper(final Looper looper) throws Exception {
298         new Handler(looper).post(new Runnable() {
299             @Override
300             public void run() {
301                 looper.quitSafely();
302             }
303         });
304     }
305 
dumpState()306     private void dumpState() {
307         ByteArrayOutputStream stream = new ByteArrayOutputStream();
308         PrintWriter writer = new PrintWriter(stream);
309         mCmi.dump(null, writer, null);
310         writer.flush();
311         Log.d(TAG, "ClientModeImpl state -" + stream.toString());
312     }
313 
getGoogleGuestScanDetail(int rssi, String bssid, int freq)314     private static ScanDetail getGoogleGuestScanDetail(int rssi, String bssid, int freq) {
315         ScanResult.InformationElement[] ie = new ScanResult.InformationElement[1];
316         ie[0] = ScanResults.generateSsidIe(sSSID);
317         NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
318         ScanDetail detail = new ScanDetail(nd, sWifiSsid, bssid, "", rssi, freq,
319                 Long.MAX_VALUE, /* needed so that scan results aren't rejected because
320                                    there older than scan start */
321                 ie, new ArrayList<String>(), ScanResults.generateIERawDatafromScanResultIE(ie));
322 
323         return detail;
324     }
325 
getMockScanResults()326     private ArrayList<ScanDetail> getMockScanResults() {
327         ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
328         ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
329 
330         list.add(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
331         return list;
332     }
333 
injectDhcpSuccess(DhcpResultsParcelable dhcpResults)334     private void injectDhcpSuccess(DhcpResultsParcelable dhcpResults) {
335         mIpClientCallback.onNewDhcpResults(dhcpResults);
336         mIpClientCallback.onProvisioningSuccess(new LinkProperties());
337     }
338 
injectDhcpFailure()339     private void injectDhcpFailure() {
340         mIpClientCallback.onNewDhcpResults((DhcpResultsParcelable) null);
341         mIpClientCallback.onProvisioningFailure(new LinkProperties());
342     }
343 
344     static final String   sSSID = "\"GoogleGuest\"";
345     static final String   SSID_NO_QUOTE = sSSID.replace("\"", "");
346     static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(SSID_NO_QUOTE);
347     static final String   sBSSID = "01:02:03:04:05:06";
348     static final String   sBSSID1 = "02:01:04:03:06:05";
349     static final int      sFreq = 2437;
350     static final int      sFreq1 = 5240;
351     static final String   WIFI_IFACE_NAME = "mockWlan";
352     static final String sFilsSsid = "FILS-AP";
353 
354     ClientModeImpl mCmi;
355     HandlerThread mWifiCoreThread;
356     HandlerThread mP2pThread;
357     HandlerThread mSyncThread;
358     AsyncChannel  mCmiAsyncChannel;
359     AsyncChannel  mNetworkAgentAsyncChannel;
360     TestAlarmManager mAlarmManager;
361     MockWifiMonitor mWifiMonitor;
362     TestLooper mLooper;
363     Context mContext;
364     MockResources mResources;
365     FrameworkFacade mFrameworkFacade;
366     IpClientCallbacks mIpClientCallback;
367     OsuProvider mOsuProvider;
368     WifiConfiguration mConnectedNetwork;
369     WifiCarrierInfoManager mWifiCarrierInfoManager;
370 
371     @Mock WifiScanner mWifiScanner;
372     @Mock SupplicantStateTracker mSupplicantStateTracker;
373     @Mock WifiMetrics mWifiMetrics;
374     @Mock UserManager mUserManager;
375     @Mock BackupManagerProxy mBackupManagerProxy;
376     @Mock WifiCountryCode mCountryCode;
377     @Mock WifiInjector mWifiInjector;
378     @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
379     @Mock BssidBlocklistMonitor mBssidBlocklistMonitor;
380     @Mock PropertyService mPropertyService;
381     @Mock BuildProperties mBuildProperties;
382     @Mock IBinder mPackageManagerBinder;
383     @Mock SarManager mSarManager;
384     @Mock WifiConfigManager mWifiConfigManager;
385     @Mock WifiNative mWifiNative;
386     @Mock WifiScoreCard mWifiScoreCard;
387     @Mock WifiHealthMonitor mWifiHealthMonitor;
388     @Mock WifiTrafficPoller mWifiTrafficPoller;
389     @Mock WifiConnectivityManager mWifiConnectivityManager;
390     @Mock WifiStateTracker mWifiStateTracker;
391     @Mock PasspointManager mPasspointManager;
392     @Mock SelfRecovery mSelfRecovery;
393     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
394     @Mock IIpClient mIpClient;
395     @Mock TelephonyManager mTelephonyManager;
396     @Mock TelephonyManager mDataTelephonyManager;
397     @Mock WrongPasswordNotifier mWrongPasswordNotifier;
398     @Mock Clock mClock;
399     @Mock ScanDetailCache mScanDetailCache;
400     @Mock BaseWifiDiagnostics mWifiDiagnostics;
401     @Mock ConnectivityManager mConnectivityManager;
402     @Mock IProvisioningCallback mProvisioningCallback;
403     @Mock HandlerThread mWifiHandlerThread;
404     @Mock WifiPermissionsWrapper mWifiPermissionsWrapper;
405     @Mock WakeupController mWakeupController;
406     @Mock WifiDataStall mWifiDataStall;
407     @Mock WifiNetworkFactory mWifiNetworkFactory;
408     @Mock UntrustedWifiNetworkFactory mUntrustedWifiNetworkFactory;
409     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
410     @Mock LinkProbeManager mLinkProbeManager;
411     @Mock PackageManager mPackageManager;
412     @Mock WifiLockManager mWifiLockManager;
413     @Mock AsyncChannel mNullAsyncChannel;
414     @Mock Handler mNetworkAgentHandler;
415     @Mock BatteryStatsManager mBatteryStatsManager;
416     @Mock MboOceController mMboOceController;
417     @Mock SubscriptionManager mSubscriptionManager;
418     @Mock ConnectionFailureNotifier mConnectionFailureNotifier;
419     @Mock EapFailureNotifier mEapFailureNotifier;
420     @Mock SimRequiredNotifier mSimRequiredNotifier;
421     @Mock ThroughputPredictor mThroughputPredictor;
422     @Mock ScanRequestProxy mScanRequestProxy;
423     @Mock DeviceConfigFacade mDeviceConfigFacade;
424     @Mock Network mNetwork;
425 
426     final ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mConfigUpdateListenerCaptor =
427             ArgumentCaptor.forClass(WifiConfigManager.OnNetworkUpdateListener.class);
428 
ClientModeImplTest()429     public ClientModeImplTest() throws Exception {
430     }
431 
432     @Before
setUp()433     public void setUp() throws Exception {
434         Log.d(TAG, "Setting up ...");
435 
436         // Ensure looper exists
437         mLooper = new TestLooper();
438 
439         MockitoAnnotations.initMocks(this);
440 
441         /** uncomment this to enable logs from ClientModeImpls */
442         // enableDebugLogs();
443         mWifiMonitor = new MockWifiMonitor();
444         when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
445         when(mWifiInjector.getClock()).thenReturn(new Clock());
446         when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
447         when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
448         when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
449         when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class));
450         when(mWifiInjector.getWifiDiagnostics()).thenReturn(mWifiDiagnostics);
451         when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
452         when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
453         when(mWifiInjector.makeWifiConnectivityManager(any()))
454                 .thenReturn(mWifiConnectivityManager);
455         when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
456         when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker);
457         when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor);
458         when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
459         when(mWifiInjector.getWifiTrafficPoller()).thenReturn(mWifiTrafficPoller);
460         when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery);
461         when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil);
462         when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager);
463         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
464         when(mWifiInjector.getClock()).thenReturn(mClock);
465         when(mWifiHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
466         when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread);
467         when(mWifiInjector.getWifiPermissionsWrapper()).thenReturn(mWifiPermissionsWrapper);
468         when(mWifiInjector.getWakeupController()).thenReturn(mWakeupController);
469         when(mWifiInjector.getScoringParams()).thenReturn(new ScoringParams());
470         when(mWifiInjector.getWifiDataStall()).thenReturn(mWifiDataStall);
471         when(mWifiInjector.makeWifiNetworkFactory(any(), any())).thenReturn(mWifiNetworkFactory);
472         when(mWifiInjector.makeUntrustedWifiNetworkFactory(any(), any()))
473                 .thenReturn(mUntrustedWifiNetworkFactory);
474         when(mWifiInjector.getWifiNetworkSuggestionsManager())
475                 .thenReturn(mWifiNetworkSuggestionsManager);
476         when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
477         when(mWifiInjector.getWifiHealthMonitor()).thenReturn(mWifiHealthMonitor);
478         when(mWifiInjector.getWifiLockManager()).thenReturn(mWifiLockManager);
479         when(mWifiInjector.getWifiThreadRunner())
480                 .thenReturn(new WifiThreadRunner(new Handler(mLooper.getLooper())));
481         when(mWifiInjector.makeConnectionFailureNotifier(any()))
482                 .thenReturn(mConnectionFailureNotifier);
483         when(mWifiInjector.getBssidBlocklistMonitor()).thenReturn(mBssidBlocklistMonitor);
484         when(mWifiInjector.getThroughputPredictor()).thenReturn(mThroughputPredictor);
485         when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy);
486         when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
487         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any()))
488                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
489         when(mWifiNative.initialize()).thenReturn(true);
490         when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(
491                 TEST_GLOBAL_MAC_ADDRESS);
492         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
493                 .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString());
494         WifiNative.ConnectionCapabilities cap = new WifiNative.ConnectionCapabilities();
495         cap.wifiStandard = ScanResult.WIFI_STANDARD_11AC;
496         when(mWifiNative.getConnectionCapabilities(WIFI_IFACE_NAME)).thenReturn(cap);
497         when(mWifiNative.setMacAddress(eq(WIFI_IFACE_NAME), anyObject()))
498                 .then(new AnswerWithArguments() {
499                     public boolean answer(String iface, MacAddress mac) {
500                         when(mWifiNative.getMacAddress(iface)).thenReturn(mac.toString());
501                         return true;
502                     }
503                 });
504         doAnswer(new AnswerWithArguments() {
505             public MacAddress answer(
506                     WifiConfiguration config) {
507                 return config.getRandomizedMacAddress();
508             }
509         }).when(mWifiConfigManager).getRandomizedMacAndUpdateIfNeeded(any());
510         when(mWifiNative.connectToNetwork(any(), any())).thenReturn(true);
511 
512         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(true);
513         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(true);
514 
515         mFrameworkFacade = getFrameworkFacade();
516         mContext = getContext();
517 
518         mResources = getMockResources();
519         mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, true);
520         mResources.setIntArray(R.array.config_wifiRssiLevelThresholds,
521                 RssiUtilTest.RSSI_THRESHOLDS);
522         mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 3000);
523         when(mContext.getResources()).thenReturn(mResources);
524         when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext);
525 
526         when(mFrameworkFacade.getIntegerSetting(mContext,
527                 Settings.Global.WIFI_FREQUENCY_BAND,
528                 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
529                 WifiManager.WIFI_FREQUENCY_BAND_AUTO);
530         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
531         when(mWifiPermissionsWrapper.getLocalMacAddressPermission(anyInt()))
532                 .thenReturn(PackageManager.PERMISSION_DENIED);
533         doAnswer(inv -> {
534             mIpClientCallback.onQuit();
535             return null;
536         }).when(mIpClient).shutdown();
537         when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(), anyInt(), any(),
538                 anyInt())).thenReturn(mNetwork);
539         List<SubscriptionInfo> subList = Arrays.asList(mock(SubscriptionInfo.class));
540         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subList);
541         when(mSubscriptionManager.getActiveSubscriptionIdList())
542                 .thenReturn(new int[]{DATA_SUBID});
543 
544         WifiCarrierInfoManager tu = new WifiCarrierInfoManager(mTelephonyManager,
545                 mSubscriptionManager, mWifiInjector, mock(FrameworkFacade.class),
546                 mock(WifiContext.class), mock(WifiConfigStore.class), mock(Handler.class),
547                 mWifiMetrics);
548         mWifiCarrierInfoManager = spy(tu);
549         // static mocking
550         mSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
551                 .spyStatic(MacAddress.class)
552                 .startMocking();
553         initializeCmi();
554 
555         mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
556         mConnectedNetwork = spy(WifiConfigurationTestUtil.createOpenNetwork());
557         when(mNullAsyncChannel.sendMessageSynchronously(any())).thenReturn(null);
558         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(new Pair<>(null, null));
559         when(mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()).thenReturn(true);
560         when(mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()).thenReturn(true);
561         when(mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()).thenReturn(true);
562         when(mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()).thenReturn(
563                 DeviceConfigFacade.DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS);
564         when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
565                 .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
566         when(mWifiScoreCard.detectAbnormalDisconnection())
567                 .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
568         when(mThroughputPredictor.predictMaxTxThroughput(any())).thenReturn(90);
569         when(mThroughputPredictor.predictMaxRxThroughput(any())).thenReturn(80);
570     }
571 
registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger, Handler wrappedHandler)572     private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger,
573             Handler wrappedHandler) {
574         final AsyncChannel channel = new AsyncChannel();
575         Handler handler = new Handler(mLooper.getLooper()) {
576             @Override
577             public void handleMessage(Message msg) {
578                 switch (msg.what) {
579                     case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
580                         if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
581                             consumer.accept(channel);
582                         } else {
583                             Log.d(TAG, "Failed to connect Command channel " + this);
584                         }
585                         break;
586                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
587                         Log.d(TAG, "Command channel disconnected " + this);
588                         break;
589                     case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
590                         Log.d(TAG, "Command channel fully connected " + this);
591                         break;
592                     default:
593                         if (wrappedHandler != null) {
594                             wrappedHandler.handleMessage(msg);
595                         }
596                         break;
597                 }
598             }
599         };
600 
601         channel.connect(mContext, handler, messenger);
602         mLooper.dispatchAll();
603     }
604 
registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger)605     private void registerAsyncChannel(Consumer<AsyncChannel> consumer, Messenger messenger) {
606         registerAsyncChannel(consumer, messenger, null /* wrappedHandler */);
607     }
608 
initializeCmi()609     private void initializeCmi() throws Exception {
610         mCmi = new ClientModeImpl(mContext, mFrameworkFacade, mLooper.getLooper(),
611                 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative,
612                 mWrongPasswordNotifier, mSarManager, mWifiTrafficPoller, mLinkProbeManager,
613                 mBatteryStatsManager, mSupplicantStateTracker, mMboOceController,
614                 mWifiCarrierInfoManager, mEapFailureNotifier, mSimRequiredNotifier);
615         mCmi.start();
616         mWifiCoreThread = getCmiHandlerThread(mCmi);
617 
618         registerAsyncChannel((x) -> {
619             mCmiAsyncChannel = x;
620         }, mCmi.getMessenger());
621 
622         mBinderToken = Binder.clearCallingIdentity();
623 
624         /* Send the BOOT_COMPLETED message to setup some CMI state. */
625         mCmi.handleBootCompleted();
626         mLooper.dispatchAll();
627 
628         verify(mWifiNetworkFactory, atLeastOnce()).register();
629         verify(mUntrustedWifiNetworkFactory, atLeastOnce()).register();
630         verify(mWifiConfigManager, atLeastOnce()).addOnNetworkUpdateListener(
631                 mConfigUpdateListenerCaptor.capture());
632         assertNotNull(mConfigUpdateListenerCaptor.getValue());
633 
634         mCmi.initialize();
635         mLooper.dispatchAll();
636     }
637 
638     @After
cleanUp()639     public void cleanUp() throws Exception {
640         Binder.restoreCallingIdentity(mBinderToken);
641 
642         if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
643         if (mWifiCoreThread != null) stopLooper(mWifiCoreThread.getLooper());
644         if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
645 
646         mWifiCoreThread = null;
647         mP2pThread = null;
648         mSyncThread = null;
649         mCmiAsyncChannel = null;
650         mNetworkAgentAsyncChannel = null;
651         mNetworkAgentHandler = null;
652         mCmi = null;
653         mSession.finishMocking();
654     }
655 
656     @Test
createNew()657     public void createNew() throws Exception {
658         assertEquals("DefaultState", getCurrentState().getName());
659 
660         mCmi.handleBootCompleted();
661         mLooper.dispatchAll();
662         assertEquals("DefaultState", getCurrentState().getName());
663     }
664 
665     @Test
loadComponentsInStaMode()666     public void loadComponentsInStaMode() throws Exception {
667         startSupplicantAndDispatchMessages();
668         assertEquals("DisconnectedState", getCurrentState().getName());
669     }
670 
671     @Test
checkInitialStateStickyWhenDisabledMode()672     public void checkInitialStateStickyWhenDisabledMode() throws Exception {
673         mLooper.dispatchAll();
674         assertEquals("DefaultState", getCurrentState().getName());
675         assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest());
676 
677         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
678         mLooper.dispatchAll();
679         assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest());
680         assertEquals("DefaultState", getCurrentState().getName());
681     }
682 
683     @Test
shouldStartSupplicantWhenConnectModeRequested()684     public void shouldStartSupplicantWhenConnectModeRequested() throws Exception {
685         // The first time we start out in DefaultState, we sit around here.
686         mLooper.dispatchAll();
687         assertEquals("DefaultState", getCurrentState().getName());
688         assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest());
689 
690         // But if someone tells us to enter connect mode, we start up supplicant
691         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
692         mLooper.dispatchAll();
693         assertEquals("DisconnectedState", getCurrentState().getName());
694     }
695 
696     /**
697      *  Test that mode changes accurately reflect the value for isWifiEnabled.
698      */
699     @Test
checkIsWifiEnabledForModeChanges()700     public void checkIsWifiEnabledForModeChanges() throws Exception {
701         // Check initial state
702         mLooper.dispatchAll();
703         assertEquals("DefaultState", getCurrentState().getName());
704         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
705 
706         // switch to connect mode and verify wifi is reported as enabled
707         startSupplicantAndDispatchMessages();
708 
709         assertEquals("DisconnectedState", getCurrentState().getName());
710         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
711         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
712         assertEquals("enabled", mCmi.syncGetWifiStateByName());
713 
714         // now disable wifi and verify the reported wifi state
715         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED);
716         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
717         mLooper.dispatchAll();
718         assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest());
719         assertEquals("DefaultState", getCurrentState().getName());
720         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
721         assertEquals("disabled", mCmi.syncGetWifiStateByName());
722         verify(mContext, never()).sendStickyBroadcastAsUser(
723                 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());
724     }
725 
726     private class WifiEnablingStateIntentMatcher implements ArgumentMatcher<Intent> {
727         @Override
matches(Intent intent)728         public boolean matches(Intent intent) {
729             if (WifiManager.WIFI_STATE_CHANGED_ACTION != intent.getAction()) {
730                 // not the correct type
731                 return false;
732             }
733             return WifiManager.WIFI_STATE_ENABLING
734                     == intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
735                                           WifiManager.WIFI_STATE_DISABLED);
736         }
737     }
738 
canForgetNetwork()739     private void canForgetNetwork() throws Exception {
740         when(mWifiConfigManager.removeNetwork(eq(0), anyInt(), any())).thenReturn(true);
741         IActionListener connectActionListener = mock(IActionListener.class);
742         mCmi.forget(0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
743         mLooper.dispatchAll();
744         verify(connectActionListener).onSuccess();
745         verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt(), any());
746     }
747 
748     /**
749      * Verifies that configs can be removed when not in client mode.
750      */
751     @Test
canForgetNetworkConfigWhenWifiDisabled()752     public void canForgetNetworkConfigWhenWifiDisabled() throws Exception {
753         canForgetNetwork();
754     }
755 
756     /**
757      * Verifies that configs can be forgotten when in client mode.
758      */
759     @Test
canForgetNetworkConfigInClientMode()760     public void canForgetNetworkConfigInClientMode() throws Exception {
761         initializeAndAddNetworkAndVerifySuccess();
762         canForgetNetwork();
763     }
764 
canSaveNetworkConfig()765     private void canSaveNetworkConfig() throws Exception {
766         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
767 
768         int networkId = TEST_NETWORK_ID;
769         when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
770                 .thenReturn(new NetworkUpdateResult(networkId));
771         when(mWifiConfigManager.enableNetwork(eq(networkId), eq(false), anyInt(), any()))
772                 .thenReturn(true);
773 
774         IActionListener connectActionListener = mock(IActionListener.class);
775         mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
776         mLooper.dispatchAll();
777         verify(connectActionListener).onSuccess();
778 
779         verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt());
780         verify(mWifiConfigManager).enableNetwork(eq(networkId), eq(false), anyInt(), any());
781     }
782 
783     /**
784      * Verifies that configs can be saved when not in client mode.
785      */
786     @Test
canSaveNetworkConfigWhenWifiDisabled()787     public void canSaveNetworkConfigWhenWifiDisabled() throws Exception {
788         canSaveNetworkConfig();
789     }
790 
791     /**
792      * Verifies that configs can be saved when in client mode.
793      */
794     @Test
canSaveNetworkConfigInClientMode()795     public void canSaveNetworkConfigInClientMode() throws Exception {
796         loadComponentsInStaMode();
797         canSaveNetworkConfig();
798     }
799 
800     /**
801      * Verifies that null configs are rejected in SAVE_NETWORK message.
802      */
803     @Test
saveNetworkConfigFailsWithNullConfig()804     public void saveNetworkConfigFailsWithNullConfig() throws Exception {
805         IActionListener connectActionListener = mock(IActionListener.class);
806         mCmi.save(null, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
807         mLooper.dispatchAll();
808         verify(connectActionListener).onFailure(WifiManager.ERROR);
809 
810         verify(mWifiConfigManager, never())
811                 .addOrUpdateNetwork(any(WifiConfiguration.class), anyInt());
812         verify(mWifiConfigManager, never())
813                 .enableNetwork(anyInt(), anyBoolean(), anyInt(), any());
814     }
815 
816     /**
817      * Verifies that configs save fails when the addition of network fails.
818      */
819     @Test
saveNetworkConfigFailsWithConfigAddFailure()820     public void saveNetworkConfigFailsWithConfigAddFailure() throws Exception {
821         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
822 
823         when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
824                 .thenReturn(new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID));
825 
826         IActionListener connectActionListener = mock(IActionListener.class);
827         mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
828         mLooper.dispatchAll();
829         verify(connectActionListener).onFailure(WifiManager.ERROR);
830 
831         verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt());
832         verify(mWifiConfigManager, never())
833                 .enableNetwork(anyInt(), anyBoolean(), anyInt(), any());
834     }
835 
836     /**
837      * Verifies that configs save fails when the enable of network fails.
838      */
839     @Test
saveNetworkConfigFailsWithConfigEnableFailure()840     public void saveNetworkConfigFailsWithConfigEnableFailure() throws Exception {
841         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
842 
843         int networkId = 5;
844         when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
845                 .thenReturn(new NetworkUpdateResult(networkId));
846         when(mWifiConfigManager.enableNetwork(eq(networkId), eq(false), anyInt(), any()))
847                 .thenReturn(false);
848 
849         IActionListener connectActionListener = mock(IActionListener.class);
850         mCmi.save(config, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
851         mLooper.dispatchAll();
852         verify(connectActionListener).onFailure(WifiManager.ERROR);
853 
854         verify(mWifiConfigManager).addOrUpdateNetwork(any(WifiConfiguration.class), anyInt());
855         verify(mWifiConfigManager).enableNetwork(eq(networkId), eq(false), anyInt(), any());
856     }
857 
858     /**
859      * Helper method to move through startup states.
860      */
startSupplicantAndDispatchMessages()861     private void startSupplicantAndDispatchMessages() throws Exception {
862         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLED);
863         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
864 
865         mLooper.dispatchAll();
866 
867         verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts();
868 
869         assertEquals("DisconnectedState", getCurrentState().getName());
870     }
871 
initializeMocksForAddedNetwork(boolean isHidden)872     private void initializeMocksForAddedNetwork(boolean isHidden) throws Exception {
873         WifiConfiguration config = new WifiConfiguration();
874         config.networkId = FRAMEWORK_NETWORK_ID;
875         config.SSID = sSSID;
876         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
877         config.hiddenSSID = isHidden;
878 
879         when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Arrays.asList(config));
880         when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
881         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
882     }
883 
initializeAndAddNetworkAndVerifySuccess()884     private void initializeAndAddNetworkAndVerifySuccess() throws Exception {
885         initializeAndAddNetworkAndVerifySuccess(false);
886     }
887 
initializeAndAddNetworkAndVerifySuccess(boolean isHidden)888     private void initializeAndAddNetworkAndVerifySuccess(boolean isHidden) throws Exception {
889         loadComponentsInStaMode();
890         initializeMocksForAddedNetwork(isHidden);
891     }
892 
setupAndStartConnectSequence(WifiConfiguration config)893     private void setupAndStartConnectSequence(WifiConfiguration config) throws Exception {
894         when(mWifiConfigManager.enableNetwork(
895                 eq(config.networkId), eq(true), anyInt(), any()))
896                 .thenReturn(true);
897         when(mWifiConfigManager.updateLastConnectUid(eq(config.networkId), anyInt()))
898                 .thenReturn(true);
899         when(mWifiConfigManager.getConfiguredNetwork(eq(config.networkId)))
900                 .thenReturn(config);
901         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(
902                 eq(config.networkId))).thenReturn(config);
903 
904         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
905 
906         IActionListener connectActionListener = mock(IActionListener.class);
907         mCmi.connect(null, config.networkId, mock(Binder.class), connectActionListener, 0,
908                 Binder.getCallingUid());
909         mLooper.dispatchAll();
910         verify(mWifiConfigManager).userEnabledNetwork(config.networkId);
911         verify(connectActionListener).onSuccess();
912     }
913 
validateSuccessfulConnectSequence(WifiConfiguration config)914     private void validateSuccessfulConnectSequence(WifiConfiguration config) {
915         verify(mWifiConfigManager).enableNetwork(
916                 eq(config.networkId), eq(true), anyInt(), any());
917         verify(mWifiConnectivityManager).setUserConnectChoice(eq(config.networkId));
918         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
919         verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId));
920         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
921     }
922 
validateFailureConnectSequence(WifiConfiguration config)923     private void validateFailureConnectSequence(WifiConfiguration config) {
924         verify(mWifiConfigManager).enableNetwork(
925                 eq(config.networkId), eq(true), anyInt(), any());
926         verify(mWifiConnectivityManager).setUserConnectChoice(eq(config.networkId));
927         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
928         verify(mWifiConfigManager, never())
929                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
930         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
931     }
932 
933     /**
934      * Tests the network connection initiation sequence with the default network request pending
935      * from WifiNetworkFactory.
936      * This simulates the connect sequence using the public
937      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
938      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
939      */
940     @Test
triggerConnect()941     public void triggerConnect() throws Exception {
942         loadComponentsInStaMode();
943         WifiConfiguration config = mConnectedNetwork;
944         config.networkId = FRAMEWORK_NETWORK_ID;
945         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
946         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
947         setupAndStartConnectSequence(config);
948         validateSuccessfulConnectSequence(config);
949     }
950 
951     /**
952      * Tests the network connection initiation sequence with the default network request pending
953      * from WifiNetworkFactory.
954      * This simulates the connect sequence using the public
955      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
956      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
957      */
958     @Test
triggerConnectFromNonSettingsApp()959     public void triggerConnectFromNonSettingsApp() throws Exception {
960         loadComponentsInStaMode();
961         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
962         config.networkId = FRAMEWORK_NETWORK_ID;
963         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(Process.myUid()))
964                 .thenReturn(false);
965         setupAndStartConnectSequence(config);
966         verify(mWifiConfigManager).enableNetwork(
967                 eq(config.networkId), eq(true), anyInt(), any());
968         verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(config.networkId));
969         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
970         verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId));
971         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
972     }
973 
974     /**
975      * Tests the network connection initiation sequence with no network request pending from
976      * from WifiNetworkFactory.
977      * This simulates the connect sequence using the public
978      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke
979      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
980      */
981     @Test
triggerConnectWithNoNetworkRequest()982     public void triggerConnectWithNoNetworkRequest() throws Exception {
983         loadComponentsInStaMode();
984         // Remove the network requests.
985         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
986         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
987 
988         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
989         config.networkId = FRAMEWORK_NETWORK_ID;
990         setupAndStartConnectSequence(config);
991         validateFailureConnectSequence(config);
992     }
993 
994     /**
995      * Tests the entire successful network connection flow.
996      */
997     @Test
connect()998     public void connect() throws Exception {
999         triggerConnect();
1000         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID);
1001         config.carrierId = CARRIER_ID_1;
1002         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1003                 .thenReturn(mScanDetailCache);
1004 
1005         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
1006                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
1007         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
1008                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
1009 
1010         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1011                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED));
1012         mLooper.dispatchAll();
1013 
1014         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1015         mLooper.dispatchAll();
1016 
1017         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1018                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1019         mLooper.dispatchAll();
1020 
1021         assertEquals("ObtainingIpState", getCurrentState().getName());
1022 
1023         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
1024         dhcpResults.baseConfiguration = new StaticIpConfiguration();
1025         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
1026         dhcpResults.baseConfiguration.ipAddress =
1027                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
1028         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
1029         dhcpResults.leaseDuration = 3600;
1030 
1031         injectDhcpSuccess(dhcpResults);
1032         mLooper.dispatchAll();
1033 
1034         // Verify WifiMetrics logging for metered metrics based on DHCP results
1035         verify(mWifiMetrics).addMeteredStat(any(), anyBoolean());
1036         WifiInfo wifiInfo = mCmi.getWifiInfo();
1037         assertNotNull(wifiInfo);
1038         assertEquals(sBSSID, wifiInfo.getBSSID());
1039         assertEquals(sFreq, wifiInfo.getFrequency());
1040         assertTrue(sWifiSsid.equals(wifiInfo.getWifiSsid()));
1041         assertNull(wifiInfo.getPasspointProviderFriendlyName());
1042         // Ensure the connection stats for the network is updated.
1043         verify(mWifiConfigManager).updateNetworkAfterConnect(FRAMEWORK_NETWORK_ID);
1044         verify(mWifiConfigManager).updateRandomizedMacExpireTime(any(), anyLong());
1045 
1046         // Anonymous Identity is not set.
1047         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1048         verify(mWifiStateTracker).updateState(eq(WifiStateTracker.CONNECTED));
1049         assertEquals("ConnectedState", getCurrentState().getName());
1050         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionSuccess();
1051         verify(mWifiLockManager).updateWifiClientConnected(true);
1052         verify(mWifiNative).getConnectionCapabilities(any());
1053         verify(mThroughputPredictor).predictMaxTxThroughput(any());
1054         verify(mWifiMetrics).setConnectionMaxSupportedLinkSpeedMbps(90, 80);
1055         verify(mWifiDataStall).setConnectionCapabilities(any());
1056         assertEquals(90, wifiInfo.getMaxSupportedTxLinkSpeedMbps());
1057     }
1058 
setupEapSimConnection()1059     private void setupEapSimConnection() throws Exception {
1060         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1061                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1062         mConnectedNetwork.carrierId = CARRIER_ID_1;
1063         doReturn(DATA_SUBID).when(mWifiCarrierInfoManager)
1064                 .getBestMatchSubscriptionId(any(WifiConfiguration.class));
1065         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
1066         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
1067         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1068 
1069         triggerConnect();
1070 
1071         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1072                 .thenReturn(mScanDetailCache);
1073         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
1074                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
1075         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
1076                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
1077 
1078         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1079         mLooper.dispatchAll();
1080         assertEquals("ObtainingIpState", getCurrentState().getName());
1081     }
1082 
1083     /**
1084      * When the SIM card was removed, if the current wifi connection is not using it, the connection
1085      * should be kept.
1086      */
1087     @Test
testResetSimWhenNonConnectedSimRemoved()1088     public void testResetSimWhenNonConnectedSimRemoved() throws Exception {
1089         setupEapSimConnection();
1090         doReturn(true).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID));
1091         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1092                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
1093         mLooper.dispatchAll();
1094 
1095         verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any());
1096 
1097         assertEquals("ObtainingIpState", getCurrentState().getName());
1098     }
1099 
1100     /**
1101      * When the SIM card was removed, if the current wifi connection is using it, the connection
1102      * should be disconnected, otherwise, the connection shouldn't be impacted.
1103      */
1104     @Test
testResetSimWhenConnectedSimRemoved()1105     public void testResetSimWhenConnectedSimRemoved() throws Exception {
1106         setupEapSimConnection();
1107         doReturn(false).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID));
1108         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1109                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
1110         mLooper.dispatchAll();
1111 
1112         verify(mSimRequiredNotifier).showSimRequiredNotification(any(), any());
1113         assertEquals("DisconnectingState", getCurrentState().getName());
1114     }
1115 
1116     /**
1117      * When the default data SIM is changed, if the current wifi connection is carrier wifi,
1118      * the connection should be disconnected.
1119      */
1120     @Test
testResetSimWhenDefaultDataSimChanged()1121     public void testResetSimWhenDefaultDataSimChanged() throws Exception {
1122         setupEapSimConnection();
1123         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1124                 ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED);
1125         mLooper.dispatchAll();
1126 
1127         assertEquals("DisconnectingState", getCurrentState().getName());
1128     }
1129 
1130     /**
1131      * Tests anonymous identity is set again whenever a connection is established for the carrier
1132      * that supports encrypted IMSI and anonymous identity and no real pseudonym was provided.
1133      */
1134     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedNoPseudonym()1135     public void testSetAnonymousIdentityWhenConnectionIsEstablishedNoPseudonym() throws Exception {
1136         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1137                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1138         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
1139         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
1140         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1141 
1142         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
1143         MockitoSession mockSession = ExtendedMockito.mockitoSession()
1144                 .mockStatic(SubscriptionManager.class)
1145                 .startMocking();
1146         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
1147         doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
1148 
1149         // Initial value should be "not set"
1150         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1151 
1152         triggerConnect();
1153 
1154         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1155         assertEquals(expectedAnonymousIdentity,
1156                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1157 
1158         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1159                 .thenReturn(mScanDetailCache);
1160         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
1161                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
1162         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
1163                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
1164         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1165                 .thenReturn(expectedAnonymousIdentity);
1166 
1167         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1168         mLooper.dispatchAll();
1169 
1170         verify(mWifiNative).getEapAnonymousIdentity(any());
1171 
1172         // Post connection value should remain "not set"
1173         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1174         // verify that WifiConfigManager#addOrUpdateNetwork() was called to clear any previously
1175         // stored pseudonym. i.e. to enable Encrypted IMSI for subsequent connections.
1176         // Note: This test will fail if future logic will have additional conditions that would
1177         // trigger "add or update network" operation. The test needs to be updated to account for
1178         // this change.
1179         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1180         mockSession.finishMocking();
1181     }
1182 
1183     /**
1184      * Tests anonymous identity is set again whenever a connection is established for the carrier
1185      * that supports encrypted IMSI and anonymous identity but real pseudonym was provided for
1186      * subsequent connections.
1187      */
1188     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonym()1189     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonym()
1190             throws Exception {
1191         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1192                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1193         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
1194         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
1195         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1196 
1197         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
1198         String pseudonym = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org";
1199         MockitoSession mockSession = ExtendedMockito.mockitoSession()
1200                 .mockStatic(SubscriptionManager.class)
1201                 .startMocking();
1202         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
1203         doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
1204 
1205         triggerConnect();
1206 
1207         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1208         assertEquals(expectedAnonymousIdentity,
1209                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1210 
1211         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1212                 .thenReturn(mScanDetailCache);
1213         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
1214                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
1215         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
1216                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
1217         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1218                 .thenReturn(pseudonym);
1219 
1220         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1221         mLooper.dispatchAll();
1222 
1223         verify(mWifiNative).getEapAnonymousIdentity(any());
1224         assertEquals(pseudonym,
1225                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1226         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
1227         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
1228         // pseudonym usage in all subsequent connections.
1229         // Note: This test will fail if future logic will have additional conditions that would
1230         // trigger "add or update network" operation. The test needs to be updated to account for
1231         // this change.
1232         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1233         mockSession.finishMocking();
1234     }
1235 
1236     /**
1237      * Tests anonymous identity is set again whenever a connection is established for the carrier
1238      * that supports encrypted IMSI and anonymous identity but real but not decorated pseudonym was
1239      * provided for subsequent connections.
1240      */
1241     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym()1242     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym()
1243             throws Exception {
1244         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1245                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1246         when(mDataTelephonyManager.getSimOperator()).thenReturn("123456");
1247         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
1248         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1249 
1250         String realm = "wlan.mnc456.mcc123.3gppnetwork.org";
1251         String expectedAnonymousIdentity = "anonymous";
1252         String pseudonym = "83bcca9384fca";
1253         MockitoSession mockSession = ExtendedMockito.mockitoSession()
1254                 .mockStatic(SubscriptionManager.class)
1255                 .startMocking();
1256         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
1257         doReturn(true).when(mWifiCarrierInfoManager).isImsiEncryptionInfoAvailable(anyInt());
1258 
1259         triggerConnect();
1260 
1261         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1262         assertEquals(expectedAnonymousIdentity + "@" + realm,
1263                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1264 
1265         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1266                 .thenReturn(mScanDetailCache);
1267         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
1268                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
1269         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
1270                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
1271         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1272                 .thenReturn(pseudonym);
1273 
1274         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1275         mLooper.dispatchAll();
1276 
1277         verify(mWifiNative).getEapAnonymousIdentity(any());
1278         assertEquals(pseudonym + "@" + realm,
1279                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1280         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
1281         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
1282         // pseudonym usage in all subsequent connections.
1283         // Note: This test will fail if future logic will have additional conditions that would
1284         // trigger "add or update network" operation. The test needs to be updated to account for
1285         // this change.
1286         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1287         mockSession.finishMocking();
1288     }
1289     /**
1290      * Tests the Passpoint information is set in WifiInfo for Passpoint AP connection.
1291      */
1292     @Test
connectPasspointAp()1293     public void connectPasspointAp() throws Exception {
1294         loadComponentsInStaMode();
1295         WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork());
1296         config.SSID = sWifiSsid.toString();
1297         config.BSSID = sBSSID;
1298         config.networkId = FRAMEWORK_NETWORK_ID;
1299         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1300         setupAndStartConnectSequence(config);
1301         validateSuccessfulConnectSequence(config);
1302 
1303         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1304                 new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
1305                         SupplicantState.ASSOCIATING));
1306         mLooper.dispatchAll();
1307 
1308         WifiInfo wifiInfo = mCmi.getWifiInfo();
1309         assertNotNull(wifiInfo);
1310         assertEquals(WifiConfigurationTestUtil.TEST_FQDN, wifiInfo.getPasspointFqdn());
1311         assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME,
1312                 wifiInfo.getPasspointProviderFriendlyName());
1313     }
1314 
1315     /**
1316      * Tests that Passpoint fields in WifiInfo are reset when connecting to a non-Passpoint network
1317      * during DisconnectedState.
1318      * @throws Exception
1319      */
1320     @Test
testResetWifiInfoPasspointFields()1321     public void testResetWifiInfoPasspointFields() throws Exception {
1322         loadComponentsInStaMode();
1323         WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork());
1324         config.SSID = sWifiSsid.toString();
1325         config.BSSID = sBSSID;
1326         config.networkId = PASSPOINT_NETWORK_ID;
1327         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1328         setupAndStartConnectSequence(config);
1329         validateSuccessfulConnectSequence(config);
1330 
1331         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1332                 new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID,
1333                         SupplicantState.ASSOCIATING));
1334         mLooper.dispatchAll();
1335 
1336         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1337                 new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
1338                         SupplicantState.ASSOCIATING));
1339         mLooper.dispatchAll();
1340 
1341         WifiInfo wifiInfo = mCmi.getWifiInfo();
1342         assertNotNull(wifiInfo);
1343         assertNull(wifiInfo.getPasspointFqdn());
1344         assertNull(wifiInfo.getPasspointProviderFriendlyName());
1345     }
1346 
1347     /**
1348      * Tests the OSU information is set in WifiInfo for OSU AP connection.
1349      */
1350     @Test
connectOsuAp()1351     public void connectOsuAp() throws Exception {
1352         loadComponentsInStaMode();
1353         WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork());
1354         osuConfig.SSID = sWifiSsid.toString();
1355         osuConfig.BSSID = sBSSID;
1356         osuConfig.osu = true;
1357         osuConfig.networkId = FRAMEWORK_NETWORK_ID;
1358         osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
1359         osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1360         setupAndStartConnectSequence(osuConfig);
1361         validateSuccessfulConnectSequence(osuConfig);
1362 
1363         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1364                 new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
1365                         SupplicantState.ASSOCIATING));
1366         mLooper.dispatchAll();
1367 
1368         WifiInfo wifiInfo = mCmi.getWifiInfo();
1369         assertNotNull(wifiInfo);
1370         assertTrue(wifiInfo.isOsuAp());
1371         assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME,
1372                 wifiInfo.getPasspointProviderFriendlyName());
1373     }
1374 
1375     /**
1376      * Tests that OSU fields in WifiInfo are reset when connecting to a non-OSU network during
1377      * DisconnectedState.
1378      * @throws Exception
1379      */
1380     @Test
testResetWifiInfoOsuFields()1381     public void testResetWifiInfoOsuFields() throws Exception {
1382         loadComponentsInStaMode();
1383         WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork());
1384         osuConfig.SSID = sWifiSsid.toString();
1385         osuConfig.BSSID = sBSSID;
1386         osuConfig.osu = true;
1387         osuConfig.networkId = PASSPOINT_NETWORK_ID;
1388         osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
1389         osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
1390         setupAndStartConnectSequence(osuConfig);
1391         validateSuccessfulConnectSequence(osuConfig);
1392 
1393         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1394                 new StateChangeResult(PASSPOINT_NETWORK_ID, sWifiSsid, sBSSID,
1395                         SupplicantState.ASSOCIATING));
1396         mLooper.dispatchAll();
1397 
1398         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1399                 new StateChangeResult(FRAMEWORK_NETWORK_ID, sWifiSsid, sBSSID,
1400                         SupplicantState.ASSOCIATING));
1401         mLooper.dispatchAll();
1402 
1403         WifiInfo wifiInfo = mCmi.getWifiInfo();
1404         assertNotNull(wifiInfo);
1405         assertFalse(wifiInfo.isOsuAp());
1406     }
1407 
1408     /**
1409      * Verify that WifiStateTracker is called if wifi is disabled while connected.
1410      */
1411     @Test
verifyWifiStateTrackerUpdatedWhenDisabled()1412     public void verifyWifiStateTrackerUpdatedWhenDisabled() throws Exception {
1413         connect();
1414 
1415         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
1416         mLooper.dispatchAll();
1417         verify(mWifiStateTracker).updateState(eq(WifiStateTracker.DISCONNECTED));
1418     }
1419 
1420     /**
1421      * Tests the network connection initiation sequence with no network request pending from
1422      * from WifiNetworkFactory when we're already connected to a different network.
1423      * This simulates the connect sequence using the public
1424      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
1425      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
1426      */
1427     @Test
triggerConnectWithNoNetworkRequestAndAlreadyConnected()1428     public void triggerConnectWithNoNetworkRequestAndAlreadyConnected() throws Exception {
1429         // Simulate the first connection.
1430         connect();
1431 
1432         // Remove the network requests.
1433         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1434         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1435 
1436         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
1437         config.networkId = FRAMEWORK_NETWORK_ID + 1;
1438         setupAndStartConnectSequence(config);
1439         validateSuccessfulConnectSequence(config);
1440         verify(mWifiPermissionsUtil, atLeastOnce()).checkNetworkSettingsPermission(anyInt());
1441     }
1442 
1443     /**
1444      * Tests the network connection initiation sequence from a non-privileged app with no network
1445      * request pending from from WifiNetworkFactory when we're already connected to a different
1446      * network.
1447      * This simulates the connect sequence using the public
1448      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke
1449      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
1450      */
1451     @Test
triggerConnectWithNoNetworkRequestAndAlreadyConnectedButNonPrivilegedApp()1452     public void triggerConnectWithNoNetworkRequestAndAlreadyConnectedButNonPrivilegedApp()
1453             throws Exception {
1454         // Simulate the first connection.
1455         connect();
1456 
1457         // Remove the network requests.
1458         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1459         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1460 
1461         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
1462 
1463         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
1464         config.networkId = FRAMEWORK_NETWORK_ID + 1;
1465         setupAndStartConnectSequence(config);
1466         verify(mWifiConfigManager).enableNetwork(
1467                 eq(config.networkId), eq(true), anyInt(), any());
1468         verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(config.networkId));
1469         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
1470         verify(mWifiConfigManager, never())
1471                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
1472         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
1473         verify(mWifiPermissionsUtil, times(4)).checkNetworkSettingsPermission(anyInt());
1474     }
1475 
1476     @Test
enableWithInvalidNetworkId()1477     public void enableWithInvalidNetworkId() throws Exception {
1478         initializeAndAddNetworkAndVerifySuccess();
1479         when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null);
1480 
1481         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
1482 
1483         IActionListener connectActionListener = mock(IActionListener.class);
1484         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1485         mLooper.dispatchAll();
1486         verify(connectActionListener).onFailure(anyInt());
1487 
1488         verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt(), any());
1489         verify(mWifiConfigManager, never()).updateLastConnectUid(eq(0), anyInt());
1490     }
1491 
1492     /**
1493      * If caller tries to connect to a network that is already connected, the connection request
1494      * should succeed.
1495      *
1496      * Test: Create and connect to a network, then try to reconnect to the same network. Verify
1497      * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
1498      */
1499     @Test
reconnectToConnectedNetworkWithNetworkId()1500     public void reconnectToConnectedNetworkWithNetworkId() throws Exception {
1501         connect();
1502 
1503         // try to reconnect
1504         IActionListener connectActionListener = mock(IActionListener.class);
1505         mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
1506                 Binder.getCallingUid());
1507         mLooper.dispatchAll();
1508         verify(connectActionListener).onSuccess();
1509 
1510         // Verify that we didn't trigger a second connection.
1511         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1512     }
1513 
1514     /**
1515      * If caller tries to connect to a network that is already connected, the connection request
1516      * should succeed.
1517      *
1518      * Test: Create and connect to a network, then try to reconnect to the same network. Verify
1519      * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
1520      */
1521     @Test
reconnectToConnectedNetworkWithConfig()1522     public void reconnectToConnectedNetworkWithConfig() throws Exception {
1523         connect();
1524 
1525         // try to reconnect
1526         WifiConfiguration config = new WifiConfiguration();
1527         config.networkId = FRAMEWORK_NETWORK_ID;
1528         when(mWifiConfigManager.addOrUpdateNetwork(eq(config), anyInt()))
1529                 .thenReturn(new NetworkUpdateResult(FRAMEWORK_NETWORK_ID));
1530         IActionListener connectActionListener = mock(IActionListener.class);
1531         mCmi.connect(config, WifiConfiguration.INVALID_NETWORK_ID, mock(Binder.class),
1532                 connectActionListener, 0, Binder.getCallingUid());
1533         mLooper.dispatchAll();
1534         verify(connectActionListener).onSuccess();
1535 
1536         // Verify that we didn't trigger a second connection.
1537         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1538     }
1539 
1540     /**
1541      * If caller tries to connect to a network that is already connecting, the connection request
1542      * should succeed.
1543      *
1544      * Test: Create and trigger connect to a network, then try to reconnect to the same network.
1545      * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did not trigger a
1546      * new connection.
1547      */
1548     @Test
reconnectToConnectingNetwork()1549     public void reconnectToConnectingNetwork() throws Exception {
1550         triggerConnect();
1551 
1552         // try to reconnect to the same network (before connection is established).
1553         IActionListener connectActionListener = mock(IActionListener.class);
1554         mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
1555                 Binder.getCallingUid());
1556         mLooper.dispatchAll();
1557         verify(connectActionListener).onSuccess();
1558 
1559         // Verify that we didn't trigger a second connection.
1560         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1561     }
1562 
1563     /**
1564      * If caller tries to connect to a network that is already connecting, the connection request
1565      * should succeed.
1566      *
1567      * Test: Create and trigger connect to a network, then try to reconnect to the same network.
1568      * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did trigger a new
1569      * connection.
1570      */
1571     @Test
reconnectToConnectingNetworkWithCredentialChange()1572     public void reconnectToConnectingNetworkWithCredentialChange() throws Exception {
1573         triggerConnect();
1574 
1575         // try to reconnect to the same network with a credential changed (before connection is
1576         // established).
1577         WifiConfiguration config = new WifiConfiguration();
1578         config.networkId = FRAMEWORK_NETWORK_ID;
1579         NetworkUpdateResult networkUpdateResult =
1580                 new NetworkUpdateResult(false /* ip */, false /* proxy */, true /* credential */);
1581         networkUpdateResult.setNetworkId(FRAMEWORK_NETWORK_ID);
1582         when(mWifiConfigManager.addOrUpdateNetwork(eq(config), anyInt()))
1583                 .thenReturn(networkUpdateResult);
1584         IActionListener connectActionListener = mock(IActionListener.class);
1585         mCmi.connect(config, WifiConfiguration.INVALID_NETWORK_ID, mock(Binder.class),
1586                 connectActionListener, 0, Binder.getCallingUid());
1587         mLooper.dispatchAll();
1588         verify(connectActionListener).onSuccess();
1589 
1590         // Verify that we triggered a second connection.
1591         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1592     }
1593 
1594     /**
1595      * If caller tries to connect to a network that previously failed connection, the connection
1596      * request should succeed.
1597      *
1598      * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect
1599      * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED
1600      * and did trigger a new * connection.
1601      */
1602     @Test
connectAfterAssociationRejection()1603     public void connectAfterAssociationRejection() throws Exception {
1604         triggerConnect();
1605 
1606         // fail the connection.
1607         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0,
1608                 ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID);
1609         mLooper.dispatchAll();
1610 
1611         IActionListener connectActionListener = mock(IActionListener.class);
1612         mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
1613                 Binder.getCallingUid());
1614         mLooper.dispatchAll();
1615         verify(connectActionListener).onSuccess();
1616 
1617         // Verify that we triggered a second connection.
1618         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1619     }
1620 
1621     /**
1622      * If caller tries to connect to a network that previously failed connection, the connection
1623      * request should succeed.
1624      *
1625      * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect
1626      * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED
1627      * and did trigger a new * connection.
1628      */
1629     @Test
connectAfterConnectionFailure()1630     public void connectAfterConnectionFailure() throws Exception {
1631         triggerConnect();
1632 
1633         // fail the connection.
1634         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, FRAMEWORK_NETWORK_ID, 0, sBSSID);
1635         mLooper.dispatchAll();
1636 
1637         IActionListener connectActionListener = mock(IActionListener.class);
1638         mCmi.connect(null, FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
1639                 Binder.getCallingUid());
1640         mLooper.dispatchAll();
1641         verify(connectActionListener).onSuccess();
1642 
1643         // Verify that we triggered a second connection.
1644         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
1645     }
1646 
1647     /**
1648      * If caller tries to connect to a new network while still provisioning the current one,
1649      * the connection attempt should succeed.
1650      */
1651     @Test
connectWhileObtainingIp()1652     public void connectWhileObtainingIp() throws Exception {
1653         initializeAndAddNetworkAndVerifySuccess();
1654 
1655         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
1656 
1657         IActionListener connectActionListener = mock(IActionListener.class);
1658         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1659         mLooper.dispatchAll();
1660         verify(connectActionListener).onSuccess();
1661 
1662         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1663 
1664         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1665         mLooper.dispatchAll();
1666 
1667         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1668                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1669         mLooper.dispatchAll();
1670 
1671         assertEquals("ObtainingIpState", getCurrentState().getName());
1672         reset(mWifiNative);
1673 
1674         // Connect to a different network
1675         WifiConfiguration config = new WifiConfiguration();
1676         config.networkId = TEST_NETWORK_ID;
1677         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
1678 
1679         mCmi.connect(null, TEST_NETWORK_ID, mock(Binder.class), null, 0, Binder.getCallingUid());
1680         mLooper.dispatchAll();
1681 
1682         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1683                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
1684         mLooper.dispatchAll();
1685 
1686         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
1687 
1688     }
1689 
1690     /**
1691      * Tests that manual connection to a network (from settings app) logs the correct nominator ID.
1692      */
1693     @Test
testManualConnectNominator()1694     public void testManualConnectNominator() throws Exception {
1695         initializeAndAddNetworkAndVerifySuccess();
1696 
1697         WifiConfiguration config = new WifiConfiguration();
1698         config.networkId = TEST_NETWORK_ID;
1699         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
1700 
1701         IActionListener connectActionListener = mock(IActionListener.class);
1702         mCmi.connect(null, TEST_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
1703                 Process.SYSTEM_UID);
1704         mLooper.dispatchAll();
1705         verify(connectActionListener).onSuccess();
1706 
1707         verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID,
1708                 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
1709     }
1710 
1711     @Test
testDhcpFailure()1712     public void testDhcpFailure() throws Exception {
1713         initializeAndAddNetworkAndVerifySuccess();
1714 
1715         IActionListener connectActionListener = mock(IActionListener.class);
1716         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1717         mLooper.dispatchAll();
1718         verify(connectActionListener).onSuccess();
1719 
1720         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1721 
1722         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1723                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED));
1724         mLooper.dispatchAll();
1725 
1726         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
1727         mLooper.dispatchAll();
1728         verify(mBssidBlocklistMonitor).handleBssidConnectionSuccess(sBSSID, sSSID);
1729 
1730         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1731                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1732         mLooper.dispatchAll();
1733 
1734         assertEquals("ObtainingIpState", getCurrentState().getName());
1735         injectDhcpFailure();
1736         mLooper.dispatchAll();
1737 
1738         assertEquals("DisconnectingState", getCurrentState().getName());
1739         // Verify this is not counted as a IP renewal failure
1740         verify(mWifiMetrics, never()).incrementIpRenewalFailure();
1741         // Verifies that WifiLastResortWatchdog be notified
1742         // by DHCP failure
1743         verify(mWifiLastResortWatchdog, times(2)).noteConnectionFailureAndTriggerIfNeeded(
1744                 sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP);
1745         verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(sBSSID,
1746                 sSSID, BssidBlocklistMonitor.REASON_DHCP_FAILURE, false);
1747         verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(sBSSID, sSSID,
1748                 BssidBlocklistMonitor.REASON_DHCP_FAILURE, false);
1749         verify(mBssidBlocklistMonitor, never()).handleDhcpProvisioningSuccess(sBSSID, sSSID);
1750         verify(mBssidBlocklistMonitor, never()).handleNetworkValidationSuccess(sBSSID, sSSID);
1751     }
1752 
1753     /**
1754      * Verify that a IP renewal failure is logged when IP provisioning fail in the
1755      * ConnectedState.
1756      */
1757     @Test
testDhcpRenewalMetrics()1758     public void testDhcpRenewalMetrics() throws Exception {
1759         connect();
1760         injectDhcpFailure();
1761         mLooper.dispatchAll();
1762 
1763         verify(mWifiMetrics).incrementIpRenewalFailure();
1764     }
1765 
1766     /**
1767      * Verify that the network selection status will be updated with DISABLED_AUTHENTICATION_FAILURE
1768      * when wrong password authentication failure is detected and the network had been
1769      * connected previously.
1770      */
1771     @Test
testWrongPasswordWithPreviouslyConnected()1772     public void testWrongPasswordWithPreviouslyConnected() throws Exception {
1773         initializeAndAddNetworkAndVerifySuccess();
1774 
1775         IActionListener connectActionListener = mock(IActionListener.class);
1776         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1777         mLooper.dispatchAll();
1778         verify(connectActionListener).onSuccess();
1779 
1780         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1781 
1782         WifiConfiguration config = new WifiConfiguration();
1783         config.getNetworkSelectionStatus().setHasEverConnected(true);
1784         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
1785 
1786         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1787                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
1788         mLooper.dispatchAll();
1789 
1790         verify(mWrongPasswordNotifier, never()).onWrongPasswordError(anyString());
1791         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
1792                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE));
1793 
1794         assertEquals("DisconnectedState", getCurrentState().getName());
1795     }
1796 
1797     /**
1798      * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD
1799      * when wrong password authentication failure is detected and the network has never been
1800      * connected.
1801      */
1802     @Test
testWrongPasswordWithNeverConnected()1803     public void testWrongPasswordWithNeverConnected() throws Exception {
1804         initializeAndAddNetworkAndVerifySuccess();
1805 
1806         IActionListener connectActionListener = mock(IActionListener.class);
1807         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1808         mLooper.dispatchAll();
1809         verify(connectActionListener).onSuccess();
1810 
1811         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1812 
1813         WifiConfiguration config = new WifiConfiguration();
1814         config.SSID = sSSID;
1815         config.getNetworkSelectionStatus().setHasEverConnected(false);
1816         config.carrierId = CARRIER_ID_1;
1817         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
1818 
1819         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1820                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
1821         mLooper.dispatchAll();
1822 
1823         verify(mWrongPasswordNotifier).onWrongPasswordError(eq(sSSID));
1824         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
1825                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));
1826         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionAuthFailure();
1827         assertEquals("DisconnectedState", getCurrentState().getName());
1828     }
1829 
1830     /**
1831      * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD
1832      * when wrong password authentication failure is detected and the network is unknown.
1833      */
1834     @Test
testWrongPasswordWithNullNetwork()1835     public void testWrongPasswordWithNullNetwork() throws Exception {
1836         initializeAndAddNetworkAndVerifySuccess();
1837 
1838         IActionListener connectActionListener = mock(IActionListener.class);
1839         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1840         mLooper.dispatchAll();
1841         verify(connectActionListener).onSuccess();
1842 
1843         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1844 
1845         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
1846 
1847         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1848                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
1849         mLooper.dispatchAll();
1850 
1851         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
1852                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));
1853         assertEquals("DisconnectedState", getCurrentState().getName());
1854     }
1855 
1856     /**
1857      * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager
1858      * is called when a Authentication failure is detected with a vendor specific EAP Error
1859      * of certification expired while using EAP-SIM
1860      * In this test case, it is assumed that the network had been connected previously.
1861      */
1862     @Test
testEapSimErrorVendorSpecific()1863     public void testEapSimErrorVendorSpecific() throws Exception {
1864         when(mWifiMetrics.startConnectionEvent(any(), anyString(), anyInt())).thenReturn(80000);
1865         initializeAndAddNetworkAndVerifySuccess();
1866 
1867         IActionListener connectActionListener = mock(IActionListener.class);
1868         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1869         mLooper.dispatchAll();
1870         verify(connectActionListener).onSuccess();
1871 
1872         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1873 
1874         WifiConfiguration config = new WifiConfiguration();
1875         config.SSID = sSSID;
1876         config.getNetworkSelectionStatus().setHasEverConnected(true);
1877         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
1878         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
1879         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
1880         MockitoSession mockSession = ExtendedMockito.mockitoSession()
1881                 .mockStatic(SubscriptionManager.class)
1882                 .startMocking();
1883         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
1884         when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true);
1885         when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
1886                 .thenReturn(WifiHealthMonitor.REASON_AUTH_FAILURE);
1887 
1888         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1889                 WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
1890                 WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED);
1891         mLooper.dispatchAll();
1892 
1893         verify(mEapFailureNotifier).onEapFailure(
1894                 WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED, config);
1895         verify(mDataTelephonyManager).resetCarrierKeysForImsiEncryption();
1896         mockSession.finishMocking();
1897         verify(mDeviceConfigFacade).isAbnormalConnectionFailureBugreportEnabled();
1898         verify(mWifiScoreCard).detectAbnormalConnectionFailure(anyString());
1899         verify(mWifiDiagnostics, times(2)).takeBugReport(anyString(), anyString());
1900     }
1901 
1902     /**
1903      * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager
1904      * is not called when a Authentication failure is detected with a vendor specific EAP Error
1905      * of certification expired while using other methods than EAP-SIM, EAP-AKA, or EAP-AKA'.
1906      */
1907     @Test
testEapTlsErrorVendorSpecific()1908     public void testEapTlsErrorVendorSpecific() throws Exception {
1909         initializeAndAddNetworkAndVerifySuccess();
1910 
1911         IActionListener connectActionListener = mock(IActionListener.class);
1912         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1913         mLooper.dispatchAll();
1914         verify(connectActionListener).onSuccess();
1915 
1916         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1917 
1918         WifiConfiguration config = new WifiConfiguration();
1919         config.getNetworkSelectionStatus().setHasEverConnected(true);
1920         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1921         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
1922         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
1923 
1924         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1925                 WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
1926                 WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED);
1927         mLooper.dispatchAll();
1928 
1929         verify(mDataTelephonyManager, never()).resetCarrierKeysForImsiEncryption();
1930     }
1931 
1932     /**
1933      * Verify that the network selection status will be updated with
1934      * DISABLED_AUTHENTICATION_NO_SUBSCRIBED when service is not subscribed.
1935      */
1936     @Test
testEapSimNoSubscribedError()1937     public void testEapSimNoSubscribedError() throws Exception {
1938         initializeAndAddNetworkAndVerifySuccess();
1939 
1940         IActionListener connectActionListener = mock(IActionListener.class);
1941         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1942         mLooper.dispatchAll();
1943         verify(connectActionListener).onSuccess();
1944 
1945         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1946 
1947         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
1948 
1949         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
1950                 WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
1951                 WifiNative.EAP_SIM_NOT_SUBSCRIBED);
1952         mLooper.dispatchAll();
1953 
1954         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
1955                 eq(WifiConfiguration.NetworkSelectionStatus
1956                         .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION));
1957     }
1958 
1959     @Test
testBadNetworkEvent()1960     public void testBadNetworkEvent() throws Exception {
1961         initializeAndAddNetworkAndVerifySuccess();
1962 
1963         IActionListener connectActionListener = mock(IActionListener.class);
1964         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
1965         mLooper.dispatchAll();
1966         verify(connectActionListener).onSuccess();
1967 
1968         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
1969 
1970         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
1971         mLooper.dispatchAll();
1972 
1973         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1974                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1975         mLooper.dispatchAll();
1976 
1977         assertEquals("DisconnectedState", getCurrentState().getName());
1978         verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString());
1979     }
1980 
1981 
1982     @Test
getWhatToString()1983     public void getWhatToString() throws Exception {
1984         assertEquals("CMD_CHANNEL_HALF_CONNECTED", mCmi.getWhatToString(
1985                 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
1986         assertEquals("CMD_PRE_DHCP_ACTION", mCmi.getWhatToString(CMD_PRE_DHCP_ACTION));
1987         assertEquals("CMD_IP_REACHABILITY_LOST", mCmi.getWhatToString(
1988                 ClientModeImpl.CMD_IP_REACHABILITY_LOST));
1989     }
1990 
1991     @Test
disconnect()1992     public void disconnect() throws Exception {
1993         when(mWifiScoreCard.detectAbnormalDisconnection())
1994                 .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL);
1995         InOrder inOrderWifiLockManager = inOrder(mWifiLockManager);
1996         connect();
1997         inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(true);
1998 
1999         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, sBSSID);
2000         mLooper.dispatchAll();
2001         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2002                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
2003         mLooper.dispatchAll();
2004 
2005         verify(mWifiStateTracker).updateState(eq(WifiStateTracker.DISCONNECTED));
2006         verify(mWifiNetworkSuggestionsManager).handleDisconnect(any(), any());
2007         assertEquals("DisconnectedState", getCurrentState().getName());
2008         inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(false);
2009         verify(mWifiScoreCard).detectAbnormalDisconnection();
2010         verify(mWifiDiagnostics).takeBugReport(anyString(), anyString());
2011     }
2012 
2013     /**
2014      * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
2015      * to true.
2016      *
2017      * Test: Successfully create and connect to a network. Check the config and verify
2018      * WifiConfiguration.getHasEverConnected() is true.
2019      */
2020     @Test
setHasEverConnectedTrueOnConnect()2021     public void setHasEverConnectedTrueOnConnect() throws Exception {
2022         connect();
2023         verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0);
2024     }
2025 
2026     /**
2027      * Fail network connection attempt and verify HasEverConnected remains false.
2028      *
2029      * Test: Successfully create a network but fail when connecting. Check the config and verify
2030      * WifiConfiguration.getHasEverConnected() is false.
2031      */
2032     @Test
connectionFailureDoesNotSetHasEverConnectedTrue()2033     public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
2034         testDhcpFailure();
2035         verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0);
2036     }
2037 
2038     @Test
iconQueryTest()2039     public void iconQueryTest() throws Exception {
2040         // TODO(b/31065385): Passpoint config management.
2041     }
2042 
2043     @Test
verboseLogRecSizeIsGreaterThanNormalSize()2044     public void verboseLogRecSizeIsGreaterThanNormalSize() {
2045         assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > ClientModeImpl.NUM_LOG_RECS_NORMAL);
2046     }
2047 
2048     /**
2049      * Verifies that, by default, we allow only the "normal" number of log records.
2050      */
2051     @Test
normalLogRecSizeIsUsedByDefault()2052     public void normalLogRecSizeIsUsedByDefault() {
2053         assertEquals(ClientModeImpl.NUM_LOG_RECS_NORMAL, mCmi.getLogRecMaxSize());
2054     }
2055 
2056     /**
2057      * Verifies that, in verbose mode, we allow a larger number of log records.
2058      */
2059     @Test
enablingVerboseLoggingUpdatesLogRecSize()2060     public void enablingVerboseLoggingUpdatesLogRecSize() {
2061         mCmi.enableVerboseLogging(1);
2062         assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mCmi.getLogRecMaxSize());
2063     }
2064 
2065     @Test
disablingVerboseLoggingClearsRecords()2066     public void disablingVerboseLoggingClearsRecords() {
2067         mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT);
2068         mLooper.dispatchAll();
2069         assertTrue(mCmi.getLogRecSize() >= 1);
2070 
2071         mCmi.enableVerboseLogging(0);
2072         assertEquals(0, mCmi.getLogRecSize());
2073     }
2074 
2075     @Test
disablingVerboseLoggingUpdatesLogRecSize()2076     public void disablingVerboseLoggingUpdatesLogRecSize() {
2077         mCmi.enableVerboseLogging(1);
2078         mCmi.enableVerboseLogging(0);
2079         assertEquals(ClientModeImpl.NUM_LOG_RECS_NORMAL, mCmi.getLogRecMaxSize());
2080     }
2081 
2082     @Test
logRecsIncludeDisconnectCommand()2083     public void logRecsIncludeDisconnectCommand() {
2084         // There's nothing special about the DISCONNECT command. It's just representative of
2085         // "normal" commands.
2086         mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT);
2087         mLooper.dispatchAll();
2088         assertEquals(1, mCmi.copyLogRecs()
2089                 .stream()
2090                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_DISCONNECT)
2091                 .count());
2092     }
2093 
2094     @Test
logRecsExcludeRssiPollCommandByDefault()2095     public void logRecsExcludeRssiPollCommandByDefault() {
2096         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL);
2097         mLooper.dispatchAll();
2098         assertEquals(0, mCmi.copyLogRecs()
2099                 .stream()
2100                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL)
2101                 .count());
2102     }
2103 
2104     @Test
logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled()2105     public void logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled() {
2106         mCmi.enableVerboseLogging(1);
2107         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL);
2108         mLooper.dispatchAll();
2109         assertEquals(1, mCmi.copyLogRecs()
2110                 .stream()
2111                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL)
2112                 .count());
2113     }
2114 
2115     /**
2116      * Verify that syncStartSubscriptionProvisioning will redirect calls with right parameters
2117      * to {@link PasspointManager} with expected true being returned when in client mode.
2118      */
2119     @Test
syncStartSubscriptionProvisioningInClientMode()2120     public void syncStartSubscriptionProvisioningInClientMode() throws Exception {
2121         loadComponentsInStaMode();
2122         when(mPasspointManager.startSubscriptionProvisioning(anyInt(),
2123                 any(OsuProvider.class), any(IProvisioningCallback.class))).thenReturn(true);
2124         mLooper.startAutoDispatch();
2125         assertTrue(mCmi.syncStartSubscriptionProvisioning(
2126                 OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel));
2127         verify(mPasspointManager).startSubscriptionProvisioning(OTHER_USER_UID, mOsuProvider,
2128                 mProvisioningCallback);
2129         mLooper.stopAutoDispatch();
2130     }
2131 
2132     /**
2133      * Verify that syncStartSubscriptionProvisioning will be a no-op and return false before
2134      * SUPPLICANT_START command is received by the CMI.
2135      */
2136     @Test
syncStartSubscriptionProvisioningBeforeSupplicantOrAPStart()2137     public void syncStartSubscriptionProvisioningBeforeSupplicantOrAPStart() throws Exception {
2138         mLooper.startAutoDispatch();
2139         assertFalse(mCmi.syncStartSubscriptionProvisioning(
2140                 OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel));
2141         mLooper.stopAutoDispatch();
2142         verify(mPasspointManager, never()).startSubscriptionProvisioning(
2143                 anyInt(), any(OsuProvider.class), any(IProvisioningCallback.class));
2144     }
2145 
2146     /**
2147      * Verify that syncStartSubscriptionProvisioning will be a no-op and return false when not in
2148      * client mode.
2149      */
2150     @Test
syncStartSubscriptionProvisioningNoOpWifiDisabled()2151     public void syncStartSubscriptionProvisioningNoOpWifiDisabled() throws Exception {
2152         mLooper.startAutoDispatch();
2153         assertFalse(mCmi.syncStartSubscriptionProvisioning(
2154                 OTHER_USER_UID, mOsuProvider, mProvisioningCallback, mCmiAsyncChannel));
2155         mLooper.stopAutoDispatch();
2156         verify(mPasspointManager, never()).startSubscriptionProvisioning(
2157                 anyInt(), any(OsuProvider.class), any(IProvisioningCallback.class));
2158     }
2159 
2160     /**
2161      *  Test that we disconnect from a network if it was removed while we are in the
2162      *  ObtainingIpState.
2163      */
2164     @Test
disconnectFromNetworkWhenRemovedWhileObtainingIpAddr()2165     public void disconnectFromNetworkWhenRemovedWhileObtainingIpAddr() throws Exception {
2166         initializeAndAddNetworkAndVerifySuccess();
2167 
2168         when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt(), any()))
2169                 .thenReturn(true);
2170         when(mWifiConfigManager.updateLastConnectUid(eq(0), anyInt())).thenReturn(true);
2171 
2172         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
2173 
2174         IActionListener connectActionListener = mock(IActionListener.class);
2175         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
2176         mLooper.dispatchAll();
2177         verify(connectActionListener).onSuccess();
2178 
2179         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
2180         verify(mWifiConnectivityManager).setUserConnectChoice(eq(0));
2181         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2182                 .thenReturn(mScanDetailCache);
2183 
2184         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
2185                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
2186         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
2187                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
2188 
2189         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
2190         mLooper.dispatchAll();
2191 
2192         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2193                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
2194         mLooper.dispatchAll();
2195 
2196         assertEquals("ObtainingIpState", getCurrentState().getName());
2197 
2198         // now remove the config
2199         reset(connectActionListener);
2200         when(mWifiConfigManager.removeNetwork(eq(FRAMEWORK_NETWORK_ID), anyInt(), any()))
2201                 .thenReturn(true);
2202         mCmi.forget(FRAMEWORK_NETWORK_ID, mock(Binder.class), connectActionListener, 0,
2203                 Binder.getCallingUid());
2204         mLooper.dispatchAll();
2205         verify(connectActionListener).onSuccess();
2206         verify(mWifiConfigManager).removeNetwork(eq(FRAMEWORK_NETWORK_ID), anyInt(), any());
2207         // trigger removal callback to trigger disconnect.
2208         WifiConfiguration removedConfig = new WifiConfiguration();
2209         removedConfig.networkId = FRAMEWORK_NETWORK_ID;
2210         mConfigUpdateListenerCaptor.getValue().onNetworkRemoved(removedConfig);
2211 
2212         reset(mWifiConfigManager);
2213 
2214         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)).thenReturn(null);
2215 
2216         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
2217         dhcpResults.baseConfiguration = new StaticIpConfiguration();
2218         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
2219         dhcpResults.baseConfiguration.ipAddress =
2220                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
2221         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
2222         dhcpResults.leaseDuration = 3600;
2223 
2224         injectDhcpSuccess(dhcpResults);
2225         mLooper.dispatchAll();
2226 
2227         assertEquals("DisconnectingState", getCurrentState().getName());
2228     }
2229 
2230     /**
2231      * Test verifying that interface Supplicant update for inactive driver does not trigger
2232      * SelfRecovery when WifiNative reports the interface is up.
2233      */
2234     @Test
testSupplicantUpdateDriverInactiveIfaceUpClientModeDoesNotTriggerSelfRecovery()2235     public void testSupplicantUpdateDriverInactiveIfaceUpClientModeDoesNotTriggerSelfRecovery()
2236             throws Exception {
2237         // Trigger initialize to capture the death handler registration.
2238         loadComponentsInStaMode();
2239 
2240         when(mWifiNative.isInterfaceUp(eq(WIFI_IFACE_NAME))).thenReturn(true);
2241 
2242         // make sure supplicant has been reported as inactive
2243         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2244                 new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(""), null,
2245                         SupplicantState.INTERFACE_DISABLED));
2246         mLooper.dispatchAll();
2247 
2248         // CMI should trigger self recovery, but not disconnect until externally triggered
2249         verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_STA_IFACE_DOWN));
2250     }
2251 
2252     /**
2253      * Verifies that WifiInfo is updated upon SUPPLICANT_STATE_CHANGE_EVENT.
2254      */
2255     @Test
testWifiInfoUpdatedUponSupplicantStateChangedEvent()2256     public void testWifiInfoUpdatedUponSupplicantStateChangedEvent() throws Exception {
2257         // Connect to network with |sBSSID|, |sFreq|.
2258         connect();
2259 
2260         // Set the scan detail cache for roaming target.
2261         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2262                 .thenReturn(mScanDetailCache);
2263         when(mScanDetailCache.getScanDetail(sBSSID1)).thenReturn(
2264                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1));
2265         when(mScanDetailCache.getScanResult(sBSSID1)).thenReturn(
2266                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1).getScanResult());
2267 
2268         // This simulates the behavior of roaming to network with |sBSSID1|, |sFreq1|.
2269         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated.
2270         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2271                 new StateChangeResult(0, sWifiSsid, sBSSID1, SupplicantState.COMPLETED));
2272         mLooper.dispatchAll();
2273 
2274         WifiInfo wifiInfo = mCmi.getWifiInfo();
2275         assertEquals(sBSSID1, wifiInfo.getBSSID());
2276         assertEquals(sFreq1, wifiInfo.getFrequency());
2277         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
2278 
2279         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2280                 new StateChangeResult(0, sWifiSsid, sBSSID1, SupplicantState.DISCONNECTED));
2281         mLooper.dispatchAll();
2282 
2283         wifiInfo = mCmi.getWifiInfo();
2284         assertNull(wifiInfo.getBSSID());
2285         assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
2286         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiInfo.getNetworkId());
2287         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
2288     }
2289 
2290     /**
2291      * Verifies that WifiInfo is updated upon CMD_ASSOCIATED_BSSID event.
2292      */
2293     @Test
testWifiInfoUpdatedUponAssociatedBSSIDEvent()2294     public void testWifiInfoUpdatedUponAssociatedBSSIDEvent() throws Exception {
2295         // Connect to network with |sBSSID|, |sFreq|.
2296         connect();
2297 
2298         // Set the scan detail cache for roaming target.
2299         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2300                 .thenReturn(mScanDetailCache);
2301         when(mScanDetailCache.getScanDetail(sBSSID1)).thenReturn(
2302                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1));
2303         when(mScanDetailCache.getScanResult(sBSSID1)).thenReturn(
2304                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq1).getScanResult());
2305 
2306         // This simulates the behavior of roaming to network with |sBSSID1|, |sFreq1|.
2307         // Send a CMD_ASSOCIATED_BSSID, verify WifiInfo is updated.
2308         mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, sBSSID1);
2309         mLooper.dispatchAll();
2310 
2311         WifiInfo wifiInfo = mCmi.getWifiInfo();
2312         assertEquals(sBSSID1, wifiInfo.getBSSID());
2313         assertEquals(sFreq1, wifiInfo.getFrequency());
2314         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
2315     }
2316 
2317     /**
2318      * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not
2319      * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState.
2320      * This protects ClientModeImpl from  getting into a bad state where WifiInfo says wifi is
2321      * already Connected or Connecting, (when it is in-fact Disconnected), so
2322      * WifiConnectivityManager does not attempt any new Connections, freezing wifi.
2323      */
2324     @Test
testWifiInfoCleanedUpEnteringExitingConnectModeState()2325     public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception {
2326         InOrder inOrder = inOrder(mWifiConnectivityManager, mWifiNetworkFactory);
2327         InOrder inOrderSarMgr = inOrder(mSarManager);
2328         InOrder inOrderMetrics = inOrder(mWifiMetrics);
2329         Log.i(TAG, mCmi.getCurrentState().getName());
2330         String initialBSSID = "aa:bb:cc:dd:ee:ff";
2331         WifiInfo wifiInfo = mCmi.getWifiInfo();
2332         wifiInfo.setBSSID(initialBSSID);
2333 
2334         // Set CMI to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager
2335         startSupplicantAndDispatchMessages();
2336         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2337         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2338         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
2339         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true));
2340         inOrderMetrics.verify(mWifiMetrics)
2341                 .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
2342         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED);
2343         assertNull(wifiInfo.getBSSID());
2344 
2345         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated
2346         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2347                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
2348         mLooper.dispatchAll();
2349         assertEquals(sBSSID, wifiInfo.getBSSID());
2350         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
2351 
2352         // Set CMI to DISABLED_MODE, verify state and wifi disabled in ConnectivityManager, and
2353         // WifiInfo is reset() and state set to DISCONNECTED
2354         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED);
2355         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
2356         mLooper.dispatchAll();
2357 
2358         assertEquals(ClientModeImpl.DISABLED_MODE, mCmi.getOperationalModeForTest());
2359         assertEquals("DefaultState", getCurrentState().getName());
2360         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
2361         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false));
2362         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(false));
2363         inOrderMetrics.verify(mWifiMetrics).setWifiState(WifiMetricsProto.WifiLog.WIFI_DISABLED);
2364         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_DISABLED);
2365         assertNull(wifiInfo.getBSSID());
2366         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
2367 
2368         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated
2369         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2370                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
2371         mLooper.dispatchAll();
2372         assertNull(wifiInfo.getBSSID());
2373         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
2374 
2375         // Set the bssid to something, so we can verify it is cleared (just in case)
2376         wifiInfo.setBSSID(initialBSSID);
2377 
2378         // Set CMI to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager,
2379         // and WifiInfo has been reset
2380         startSupplicantAndDispatchMessages();
2381 
2382         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2383         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2384         inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
2385         inOrder.verify(mWifiNetworkFactory).setWifiState(eq(true));
2386         inOrderMetrics.verify(mWifiMetrics)
2387                 .setWifiState(WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
2388         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_ENABLED);
2389         assertEquals("DisconnectedState", getCurrentState().getName());
2390         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
2391         assertNull(wifiInfo.getBSSID());
2392     }
2393 
2394     /**
2395      * Test that connected SSID and BSSID are exposed to system server.
2396      * Also tests that {@link ClientModeImpl#syncRequestConnectionInfo()} always
2397      * returns a copy of WifiInfo.
2398      */
2399     @Test
testConnectedIdsAreVisibleFromSystemServer()2400     public void testConnectedIdsAreVisibleFromSystemServer() throws Exception {
2401         WifiInfo wifiInfo = mCmi.getWifiInfo();
2402         // Get into a connected state, with known BSSID and SSID
2403         connect();
2404         assertEquals(sBSSID, wifiInfo.getBSSID());
2405         assertEquals(sWifiSsid, wifiInfo.getWifiSsid());
2406 
2407         WifiInfo connectionInfo = mCmi.syncRequestConnectionInfo();
2408 
2409         assertNotEquals(wifiInfo, connectionInfo);
2410         assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID());
2411         assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID());
2412         assertEquals(wifiInfo.getMacAddress(), connectionInfo.getMacAddress());
2413     }
2414 
2415     /**
2416      * Test that reconnectCommand() triggers connectivity scan when ClientModeImpl
2417      * is in DisconnectedMode.
2418      */
2419     @Test
testReconnectCommandWhenDisconnected()2420     public void testReconnectCommandWhenDisconnected() throws Exception {
2421         // Connect to network with |sBSSID|, |sFreq|, and then disconnect.
2422         disconnect();
2423 
2424         mCmi.reconnectCommand(ClientModeImpl.WIFI_WORK_SOURCE);
2425         mLooper.dispatchAll();
2426         verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
2427     }
2428 
2429     /**
2430      * Test that reconnectCommand() doesn't trigger connectivity scan when ClientModeImpl
2431      * is in ConnectedMode.
2432      */
2433     @Test
testReconnectCommandWhenConnected()2434     public void testReconnectCommandWhenConnected() throws Exception {
2435         // Connect to network with |sBSSID|, |sFreq|.
2436         connect();
2437 
2438         mCmi.reconnectCommand(ClientModeImpl.WIFI_WORK_SOURCE);
2439         mLooper.dispatchAll();
2440         verify(mWifiConnectivityManager, never())
2441                 .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
2442     }
2443 
2444     /**
2445      * Adds the network without putting ClientModeImpl into ConnectMode.
2446      */
2447     @Test
addNetworkInDefaultState()2448     public void addNetworkInDefaultState() throws Exception {
2449         // We should not be in initial state now.
2450         assertTrue("DefaultState".equals(getCurrentState().getName()));
2451         initializeMocksForAddedNetwork(false);
2452         verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0));
2453     }
2454 
2455     /**
2456      * Verifies that ClientModeImpl sets and unsets appropriate 'RecentFailureReason' values
2457      * on a WifiConfiguration when it fails association, authentication, or successfully connects
2458      */
2459     @Test
testExtraFailureReason_ApIsBusy()2460     public void testExtraFailureReason_ApIsBusy() throws Exception {
2461         // Setup CONNECT_MODE & a WifiConfiguration
2462         initializeAndAddNetworkAndVerifySuccess();
2463         // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up
2464         // targetNetworkId state)
2465         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2466         mLooper.dispatchAll();
2467         // Simulate an ASSOCIATION_REJECTION_EVENT, due to the AP being busy
2468         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0,
2469                 ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID);
2470         mLooper.dispatchAll();
2471         verify(mWifiConfigManager).setRecentFailureAssociationStatus(eq(0),
2472                 eq(WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA));
2473         assertEquals("DisconnectedState", getCurrentState().getName());
2474 
2475         // Simulate an AUTHENTICATION_FAILURE_EVENT, which should clear the ExtraFailureReason
2476         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2477         mLooper.dispatchAll();
2478         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 0, null);
2479         mLooper.dispatchAll();
2480         verify(mWifiConfigManager, times(1)).clearRecentFailureReason(eq(0));
2481         verify(mWifiConfigManager, times(1)).setRecentFailureAssociationStatus(anyInt(), anyInt());
2482 
2483         // Simulate a NETWORK_CONNECTION_EVENT which should clear the ExtraFailureReason
2484         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2485         mLooper.dispatchAll();
2486         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
2487         mLooper.dispatchAll();
2488         verify(mWifiConfigManager, times(2)).clearRecentFailureReason(eq(0));
2489         verify(mWifiConfigManager, times(1)).setRecentFailureAssociationStatus(anyInt(), anyInt());
2490     }
2491 
makeLastSelectedWifiConfiguration(int lastSelectedNetworkId, long timeSinceLastSelected)2492     private WifiConfiguration makeLastSelectedWifiConfiguration(int lastSelectedNetworkId,
2493             long timeSinceLastSelected) {
2494         long lastSelectedTimestamp = 45666743454L;
2495 
2496         when(mClock.getElapsedSinceBootMillis()).thenReturn(
2497                 lastSelectedTimestamp + timeSinceLastSelected);
2498         when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp);
2499         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId);
2500 
2501         WifiConfiguration currentConfig = new WifiConfiguration();
2502         currentConfig.networkId = lastSelectedNetworkId;
2503         return currentConfig;
2504     }
2505 
2506     /**
2507      * Test that the helper method
2508      * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
2509      * returns true when we connect to the last selected network before expiration of
2510      * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
2511      */
2512     @Test
testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkNotExpired()2513     public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkNotExpired() {
2514         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
2515                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
2516         assertTrue(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
2517     }
2518 
2519     /**
2520      * Test that the helper method
2521      * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
2522      * returns false when we connect to the last selected network after expiration of
2523      * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
2524      */
2525     @Test
testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkExpired()2526     public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkExpired() {
2527         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
2528                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1);
2529         assertFalse(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
2530     }
2531 
2532     /**
2533      * Test that the helper method
2534      * {@link ClientModeImpl#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
2535      * returns false when we connect to a different network to the last selected network.
2536      */
2537     @Test
testShouldEvaluateWhetherToSendExplicitlySelected_DifferentNetwork()2538     public void testShouldEvaluateWhetherToSendExplicitlySelected_DifferentNetwork() {
2539         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
2540                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
2541         currentConfig.networkId = 4;
2542         assertFalse(mCmi.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
2543     }
2544 
expectRegisterNetworkAgent(Consumer<NetworkAgentConfig> configChecker, Consumer<NetworkCapabilities> networkCapabilitiesChecker)2545     private void expectRegisterNetworkAgent(Consumer<NetworkAgentConfig> configChecker,
2546             Consumer<NetworkCapabilities> networkCapabilitiesChecker) {
2547         // Expects that the code calls registerNetworkAgent and provides a way for the test to
2548         // verify the messages sent through the NetworkAgent to ConnectivityService.
2549         // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI.
2550         // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks.
2551         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
2552         ArgumentCaptor<NetworkAgentConfig> configCaptor =
2553                 ArgumentCaptor.forClass(NetworkAgentConfig.class);
2554         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
2555                 ArgumentCaptor.forClass(NetworkCapabilities.class);
2556         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
2557                 any(NetworkInfo.class), any(LinkProperties.class),
2558                 networkCapabilitiesCaptor.capture(),
2559                 anyInt(), configCaptor.capture(), anyInt());
2560 
2561         registerAsyncChannel((x) -> {
2562             mNetworkAgentAsyncChannel = x;
2563         }, messengerCaptor.getValue(), mNetworkAgentHandler);
2564         configChecker.accept(configCaptor.getValue());
2565         networkCapabilitiesChecker.accept(networkCapabilitiesCaptor.getValue());
2566 
2567         mNetworkAgentAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2568         mLooper.dispatchAll();
2569     }
2570 
expectUnregisterNetworkAgent()2571     private void expectUnregisterNetworkAgent() {
2572         // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI.
2573         // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks.
2574         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
2575         mLooper.dispatchAll();
2576         verify(mNetworkAgentHandler).handleMessage(messageCaptor.capture());
2577         Message message = messageCaptor.getValue();
2578         assertNotNull(message);
2579         assertEquals(NetworkAgent.EVENT_NETWORK_INFO_CHANGED, message.what);
2580         NetworkInfo networkInfo = (NetworkInfo) message.obj;
2581         assertEquals(NetworkInfo.DetailedState.DISCONNECTED, networkInfo.getDetailedState());
2582     }
2583 
expectNetworkAgentUpdateCapabilities( Consumer<NetworkCapabilities> networkCapabilitiesChecker)2584     private void expectNetworkAgentUpdateCapabilities(
2585             Consumer<NetworkCapabilities> networkCapabilitiesChecker) {
2586         // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI.
2587         // TODO (b/134538181): consider exposing WifiNetworkAgent and using mocks.
2588         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
2589         mLooper.dispatchAll();
2590         verify(mNetworkAgentHandler).handleMessage(messageCaptor.capture());
2591         Message message = messageCaptor.getValue();
2592         assertNotNull(message);
2593         assertEquals(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED, message.what);
2594         networkCapabilitiesChecker.accept((NetworkCapabilities) message.obj);
2595     }
2596 
2597     /**
2598      * Verify that when a network is explicitly selected, but noInternetAccessExpected is false,
2599      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
2600      * acceptUnvalidated and acceptPartialConnectivity.
2601      */
2602     @Test
testExplicitlySelected_ExplicitInternetExpected()2603     public void testExplicitlySelected_ExplicitInternetExpected() throws Exception {
2604         // Network is explicitly selected.
2605         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
2606                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
2607         mConnectedNetwork.noInternetAccessExpected = false;
2608 
2609         connect();
2610         expectRegisterNetworkAgent((agentConfig) -> {
2611             assertTrue(agentConfig.explicitlySelected);
2612             assertFalse(agentConfig.acceptUnvalidated);
2613             assertFalse(agentConfig.acceptPartialConnectivity);
2614         }, (cap) -> { });
2615     }
2616 
2617     /**
2618      * Verify that when a network is not explicitly selected, but noInternetAccessExpected is true,
2619      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
2620      * acceptUnvalidated and acceptPartialConnectivity.
2621      */
2622     @Test
testExplicitlySelected_NotExplicitNoInternetExpected()2623     public void testExplicitlySelected_NotExplicitNoInternetExpected() throws Exception {
2624         // Network is no longer explicitly selected.
2625         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
2626                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1);
2627         mConnectedNetwork.noInternetAccessExpected = true;
2628 
2629         connect();
2630         expectRegisterNetworkAgent((agentConfig) -> {
2631             assertFalse(agentConfig.explicitlySelected);
2632             assertFalse(agentConfig.acceptUnvalidated);
2633             assertTrue(agentConfig.acceptPartialConnectivity);
2634         }, (cap) -> { });
2635     }
2636 
2637     /**
2638      * Verify that when a network is explicitly selected, and noInternetAccessExpected is true,
2639      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
2640      * acceptUnvalidated and acceptPartialConnectivity.
2641      */
2642     @Test
testExplicitlySelected_ExplicitNoInternetExpected()2643     public void testExplicitlySelected_ExplicitNoInternetExpected() throws Exception {
2644         // Network is explicitly selected.
2645         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
2646                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
2647         mConnectedNetwork.noInternetAccessExpected = true;
2648 
2649         connect();
2650         expectRegisterNetworkAgent((agentConfig) -> {
2651             assertTrue(agentConfig.explicitlySelected);
2652             assertTrue(agentConfig.acceptUnvalidated);
2653             assertTrue(agentConfig.acceptPartialConnectivity);
2654         }, (cap) -> { });
2655     }
2656 
2657     /**
2658      * Verify that CMI dump includes WakeupController.
2659      */
2660     @Test
testDumpShouldDumpWakeupController()2661     public void testDumpShouldDumpWakeupController() {
2662         ByteArrayOutputStream stream = new ByteArrayOutputStream();
2663         PrintWriter writer = new PrintWriter(stream);
2664         mCmi.dump(null, writer, null);
2665         verify(mWakeupController).dump(null, writer, null);
2666     }
2667 
2668     @Test
takeBugReportCallsWifiDiagnostics()2669     public void takeBugReportCallsWifiDiagnostics() {
2670         mCmi.takeBugReport(anyString(), anyString());
2671         verify(mWifiDiagnostics).takeBugReport(anyString(), anyString());
2672     }
2673 
2674     /**
2675      * Verify that Rssi Monitoring is started and the callback registered after connecting.
2676      */
2677     @Test
verifyRssiMonitoringCallbackIsRegistered()2678     public void verifyRssiMonitoringCallbackIsRegistered() throws Exception {
2679         // Simulate the first connection.
2680         connect();
2681         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
2682         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
2683                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
2684                 anyInt(), any(NetworkAgentConfig.class), anyInt());
2685 
2686         ArrayList<Integer> thresholdsArray = new ArrayList<>();
2687         thresholdsArray.add(RSSI_THRESHOLD_MAX);
2688         thresholdsArray.add(RSSI_THRESHOLD_MIN);
2689         Bundle thresholds = new Bundle();
2690         thresholds.putIntegerArrayList("thresholds", thresholdsArray);
2691         Message message = new Message();
2692         message.what = NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS;
2693         message.obj  = thresholds;
2694         messengerCaptor.getValue().send(message);
2695         mLooper.dispatchAll();
2696 
2697         ArgumentCaptor<WifiNative.WifiRssiEventHandler> rssiEventHandlerCaptor =
2698                 ArgumentCaptor.forClass(WifiNative.WifiRssiEventHandler.class);
2699         verify(mWifiNative).startRssiMonitoring(anyString(), anyByte(), anyByte(),
2700                 rssiEventHandlerCaptor.capture());
2701 
2702         // breach below min
2703         rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MIN);
2704         mLooper.dispatchAll();
2705         WifiInfo wifiInfo = mCmi.getWifiInfo();
2706         assertEquals(RSSI_THRESHOLD_BREACH_MIN, wifiInfo.getRssi());
2707 
2708         // breach above max
2709         rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MAX);
2710         mLooper.dispatchAll();
2711         assertEquals(RSSI_THRESHOLD_BREACH_MAX, wifiInfo.getRssi());
2712     }
2713 
2714     /**
2715      * Verify that RSSI and link layer stats polling works in connected mode
2716      */
2717     @Test
verifyConnectedModeRssiPolling()2718     public void verifyConnectedModeRssiPolling() throws Exception {
2719         final long startMillis = 1_500_000_000_100L;
2720         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
2721         llStats.txmpdu_be = 1000;
2722         llStats.rxmpdu_bk = 2000;
2723         WifiNl80211Manager.SignalPollResult signalPollResult =
2724                 new WifiNl80211Manager.SignalPollResult(-42, 65, 54, sFreq);
2725         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
2726         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult);
2727         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
2728         mCmi.enableRssiPolling(true);
2729         connect();
2730         mLooper.dispatchAll();
2731         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
2732         mLooper.dispatchAll();
2733         WifiInfo wifiInfo = mCmi.getWifiInfo();
2734         assertEquals(llStats.txmpdu_be, wifiInfo.txSuccess);
2735         assertEquals(llStats.rxmpdu_bk, wifiInfo.rxSuccess);
2736         assertEquals(signalPollResult.currentRssiDbm, wifiInfo.getRssi());
2737         assertEquals(signalPollResult.txBitrateMbps, wifiInfo.getLinkSpeed());
2738         assertEquals(signalPollResult.txBitrateMbps, wifiInfo.getTxLinkSpeedMbps());
2739         assertEquals(signalPollResult.rxBitrateMbps, wifiInfo.getRxLinkSpeedMbps());
2740         assertEquals(sFreq, wifiInfo.getFrequency());
2741         verify(mWifiDataStall, atLeastOnce()).getTxThroughputKbps();
2742         verify(mWifiDataStall, atLeastOnce()).getRxThroughputKbps();
2743         verify(mWifiScoreCard).noteSignalPoll(any());
2744     }
2745 
2746     /**
2747      * Verify RSSI polling with verbose logging
2748      */
2749     @Test
verifyConnectedModeRssiPollingWithVerboseLogging()2750     public void verifyConnectedModeRssiPollingWithVerboseLogging() throws Exception {
2751         mCmi.enableVerboseLogging(1);
2752         verifyConnectedModeRssiPolling();
2753     }
2754 
2755     /**
2756      * Verify that calls to start and stop filtering multicast packets are passed on to the IpClient
2757      * instance.
2758      */
2759     @Test
verifyMcastLockManagerFilterControllerCallsUpdateIpClient()2760     public void verifyMcastLockManagerFilterControllerCallsUpdateIpClient() throws Exception {
2761         loadComponentsInStaMode();
2762         reset(mIpClient);
2763         WifiMulticastLockManager.FilterController filterController =
2764                 mCmi.getMcastLockManagerFilterController();
2765         filterController.startFilteringMulticastPackets();
2766         verify(mIpClient).setMulticastFilter(eq(true));
2767         filterController.stopFilteringMulticastPackets();
2768         verify(mIpClient).setMulticastFilter(eq(false));
2769     }
2770 
2771     /**
2772      * Verifies that when
2773      * 1. Global feature support flag is set to false
2774      * 2. connected MAC randomization is on and
2775      * 3. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and
2776      * 4. randomized MAC for the network to connect to is different from the current MAC.
2777      *
2778      * The factory MAC address is used for the connection, and no attempt is made to change it.
2779      */
2780     @Test
testConnectedMacRandomizationNotSupported()2781     public void testConnectedMacRandomizationNotSupported() throws Exception {
2782         mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false);
2783         initializeCmi();
2784         initializeAndAddNetworkAndVerifySuccess();
2785         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2786         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2787 
2788         connect();
2789         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2790         verify(mWifiNative, never()).setMacAddress(any(), any());
2791         verify(mWifiNative, never()).getFactoryMacAddress(any());
2792     }
2793 
2794     /**
2795      * Verifies that when
2796      * 1. connected MAC randomization is on and
2797      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and
2798      * 3. randomized MAC for the network to connect to is different from the current MAC.
2799      *
2800      * Then the current MAC gets set to the randomized MAC when CMD_START_CONNECT executes.
2801      */
2802     @Test
testConnectedMacRandomizationRandomizationPersistentDifferentMac()2803     public void testConnectedMacRandomizationRandomizationPersistentDifferentMac()
2804             throws Exception {
2805         initializeAndAddNetworkAndVerifySuccess();
2806         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2807         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2808 
2809         connect();
2810         verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
2811         verify(mWifiMetrics)
2812                 .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
2813         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2814     }
2815 
2816     /**
2817      * Verifies that when
2818      * 1. connected MAC randomization is on and
2819      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_PERSISTENT and
2820      * 3. randomized MAC for the network to connect to is same as the current MAC.
2821      *
2822      * Then MAC change should not occur when CMD_START_CONNECT executes.
2823      */
2824     @Test
testConnectedMacRandomizationRandomizationPersistentSameMac()2825     public void testConnectedMacRandomizationRandomizationPersistentSameMac() throws Exception {
2826         initializeAndAddNetworkAndVerifySuccess();
2827         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2828         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2829 
2830         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
2831                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
2832 
2833         connect();
2834         verify(mWifiNative, never()).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
2835         verify(mWifiMetrics, never())
2836                 .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
2837         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2838     }
2839 
2840     /**
2841      * Verifies that when
2842      * 1. connected MAC randomization is on and
2843      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and
2844      * 3. current MAC address is not the factory MAC.
2845      *
2846      * Then the current MAC gets set to the factory MAC when CMD_START_CONNECT executes.
2847      * @throws Exception
2848      */
2849     @Test
testConnectedMacRandomizationRandomizationNoneDifferentMac()2850     public void testConnectedMacRandomizationRandomizationNoneDifferentMac() throws Exception {
2851         initializeAndAddNetworkAndVerifySuccess();
2852         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2853         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2854 
2855         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
2856                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
2857 
2858         WifiConfiguration config = new WifiConfiguration();
2859         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
2860         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
2861         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
2862 
2863         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2864         mLooper.dispatchAll();
2865 
2866         verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS);
2867         verify(mWifiMetrics)
2868                 .logStaEvent(eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
2869         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2870     }
2871 
2872     /**
2873      * Verifies that when
2874      * 1. connected MAC randomization is on and
2875      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and
2876      *
2877      * Then the factory MAC should be used to connect to the network.
2878      * @throws Exception
2879      */
2880     @Test
testConnectedMacRandomizationRandomizationNoneSameMac()2881     public void testConnectedMacRandomizationRandomizationNoneSameMac() throws Exception {
2882         initializeAndAddNetworkAndVerifySuccess();
2883         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2884         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2885 
2886         WifiConfiguration config = new WifiConfiguration();
2887         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
2888         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
2889         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
2890 
2891         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2892         mLooper.dispatchAll();
2893 
2894         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2895     }
2896 
2897     /**
2898      * Verifies that WifiInfo returns DEFAULT_MAC_ADDRESS as mac address when Connected MAC
2899      * Randomization is on and the device is not connected to a wifi network.
2900      */
2901     @Test
testWifiInfoReturnDefaultMacWhenDisconnectedWithRandomization()2902     public void testWifiInfoReturnDefaultMacWhenDisconnectedWithRandomization() throws Exception {
2903         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
2904                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
2905 
2906         connect();
2907         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
2908 
2909         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, sBSSID);
2910         mLooper.dispatchAll();
2911         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2912                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
2913         mLooper.dispatchAll();
2914 
2915         assertEquals("DisconnectedState", getCurrentState().getName());
2916         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mCmi.getWifiInfo().getMacAddress());
2917         assertFalse(mCmi.getWifiInfo().hasRealMacAddress());
2918     }
2919 
2920     /**
2921      * Verifies that we don't set MAC address when config returns an invalid MAC address.
2922      */
2923     @Test
testDoNotSetMacWhenInvalid()2924     public void testDoNotSetMacWhenInvalid() throws Exception {
2925         initializeAndAddNetworkAndVerifySuccess();
2926         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2927         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2928 
2929         WifiConfiguration config = new WifiConfiguration();
2930         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
2931         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
2932         config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS));
2933         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
2934 
2935         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
2936         mLooper.dispatchAll();
2937 
2938         // setMacAddress is invoked once when ClientModeImpl starts to prevent leak of factory MAC.
2939         verify(mWifiNative).setMacAddress(eq(WIFI_IFACE_NAME), any(MacAddress.class));
2940     }
2941 
2942     /**
2943      * Verify that we don't crash when WifiNative returns null as the current MAC address.
2944      * @throws Exception
2945      */
2946     @Test
testMacRandomizationWifiNativeReturningNull()2947     public void testMacRandomizationWifiNativeReturningNull() throws Exception {
2948         when(mWifiNative.getMacAddress(anyString())).thenReturn(null);
2949         initializeAndAddNetworkAndVerifySuccess();
2950         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
2951         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
2952 
2953         connect();
2954         verify(mWifiNative).setMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
2955     }
2956 
2957     /**
2958      * Verifies that a notification is posted when a connection failure happens on a network
2959      * in the hotlist. Then verify that tapping on the notification launches an dialog, which
2960      * could be used to set the randomization setting for a network to "Trusted".
2961      */
2962     @Test
testConnectionFailureSendRandomizationSettingsNotification()2963     public void testConnectionFailureSendRandomizationSettingsNotification() throws Exception {
2964         when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true);
2965         // Setup CONNECT_MODE & a WifiConfiguration
2966         initializeAndAddNetworkAndVerifySuccess();
2967         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID);
2968         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
2969                 WifiManager.ERROR_AUTH_FAILURE_TIMEOUT);
2970         mLooper.dispatchAll();
2971 
2972         WifiConfiguration config = mCmi.getCurrentWifiConfiguration();
2973         verify(mConnectionFailureNotifier)
2974                 .showFailedToConnectDueToNoRandomizedMacSupportNotification(FRAMEWORK_NETWORK_ID);
2975     }
2976 
2977     /**
2978      * Verifies that a notification is not posted when a wrong password failure happens on a
2979      * network in the hotlist.
2980      */
2981     @Test
testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword()2982     public void testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword() throws Exception {
2983         when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true);
2984         // Setup CONNECT_MODE & a WifiConfiguration
2985         initializeAndAddNetworkAndVerifySuccess();
2986         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, sBSSID);
2987         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
2988                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
2989         mLooper.dispatchAll();
2990 
2991         verify(mConnectionFailureNotifier, never())
2992                 .showFailedToConnectDueToNoRandomizedMacSupportNotification(anyInt());
2993     }
2994 
2995     /**
2996      * Verifies that CMD_START_CONNECT make WifiDiagnostics report
2997      * CONNECTION_EVENT_STARTED
2998      * @throws Exception
2999      */
3000     @Test
testReportConnectionEventIsCalledAfterCmdStartConnect()3001     public void testReportConnectionEventIsCalledAfterCmdStartConnect() throws Exception {
3002         // Setup CONNECT_MODE & a WifiConfiguration
3003         initializeAndAddNetworkAndVerifySuccess();
3004         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3005         verify(mWifiDiagnostics, never()).reportConnectionEvent(
3006                 eq(WifiDiagnostics.CONNECTION_EVENT_STARTED));
3007         mLooper.dispatchAll();
3008         verify(mWifiDiagnostics).reportConnectionEvent(
3009                 eq(WifiDiagnostics.CONNECTION_EVENT_STARTED));
3010     }
3011 
3012     /**
3013      * Verifies that CMD_DIAG_CONNECT_TIMEOUT is processed after the timeout threshold if we
3014      * start a connection but do not finish it.
3015      * @throws Exception
3016      */
3017     @Test
testCmdDiagsConnectTimeoutIsGeneratedAfterCmdStartConnect()3018     public void testCmdDiagsConnectTimeoutIsGeneratedAfterCmdStartConnect() throws Exception {
3019         // Setup CONNECT_MODE & a WifiConfiguration
3020         initializeAndAddNetworkAndVerifySuccess();
3021         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3022         mLooper.dispatchAll();
3023         mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS);
3024         mLooper.dispatchAll();
3025         verify(mWifiDiagnostics).reportConnectionEvent(
3026                 eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT));
3027     }
3028 
3029     /**
3030      * Verifies that CMD_DIAG_CONNECT_TIMEOUT does not get processed before the timeout threshold.
3031      * @throws Exception
3032      */
3033     @Test
testCmdDiagsConnectTimeoutIsNotProcessedBeforeTimerExpires()3034     public void testCmdDiagsConnectTimeoutIsNotProcessedBeforeTimerExpires() throws Exception {
3035         // Setup CONNECT_MODE & a WifiConfiguration
3036         initializeAndAddNetworkAndVerifySuccess();
3037         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3038         mLooper.dispatchAll();
3039         mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS - 1000);
3040         mLooper.dispatchAll();
3041         verify(mWifiDiagnostics, never()).reportConnectionEvent(
3042                 eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT));
3043     }
3044 
verifyConnectionEventTimeoutDoesNotOccur()3045     private void verifyConnectionEventTimeoutDoesNotOccur() {
3046         mLooper.moveTimeForward(ClientModeImpl.DIAGS_CONNECT_TIMEOUT_MILLIS);
3047         mLooper.dispatchAll();
3048         verify(mWifiDiagnostics, never()).reportConnectionEvent(
3049                 eq(BaseWifiDiagnostics.CONNECTION_EVENT_TIMEOUT));
3050     }
3051 
3052     /**
3053      * Verifies that association failures make WifiDiagnostics report CONNECTION_EVENT_FAILED
3054      * and then cancel any pending timeouts.
3055      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
3056      * @throws Exception
3057      */
3058     @Test
testReportConnectionEventIsCalledAfterAssociationFailure()3059     public void testReportConnectionEventIsCalledAfterAssociationFailure() throws Exception {
3060         mConnectedNetwork.getNetworkSelectionStatus()
3061                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
3062         // Setup CONNECT_MODE & a WifiConfiguration
3063         initializeAndAddNetworkAndVerifySuccess();
3064         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3065         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0,
3066                 ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID);
3067         verify(mWifiDiagnostics, never()).reportConnectionEvent(
3068                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED));
3069         mLooper.dispatchAll();
3070         verify(mWifiDiagnostics).reportConnectionEvent(
3071                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED));
3072         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
3073                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION, sBSSID, sSSID);
3074         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
3075                 eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION),
3076                 any(WifiConfiguration.class));
3077         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
3078                 eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION),
3079                 any(WifiConfiguration.class), eq(null));
3080         verify(mWifiMetrics, never())
3081                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
3082         verifyConnectionEventTimeoutDoesNotOccur();
3083     }
3084 
3085     /**
3086      * Verifies that authentication failures make WifiDiagnostics report
3087      * CONNECTION_EVENT_FAILED and then cancel any pending timeouts.
3088      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
3089      * @throws Exception
3090      */
3091     @Test
testReportConnectionEventIsCalledAfterAuthenticationFailure()3092     public void testReportConnectionEventIsCalledAfterAuthenticationFailure() throws Exception {
3093         mConnectedNetwork.getNetworkSelectionStatus()
3094                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
3095         // Setup CONNECT_MODE & a WifiConfiguration
3096         initializeAndAddNetworkAndVerifySuccess();
3097         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3098         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3099                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
3100         verify(mWifiDiagnostics, never()).reportConnectionEvent(
3101                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED));
3102         mLooper.dispatchAll();
3103         verify(mWifiDiagnostics).reportConnectionEvent(
3104                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED));
3105         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
3106                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE, sBSSID, sSSID);
3107         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
3108                 eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE),
3109                 any(WifiConfiguration.class));
3110         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
3111                 eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE),
3112                 any(WifiConfiguration.class), eq(null));
3113         verify(mWifiMetrics, never())
3114                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
3115         verifyConnectionEventTimeoutDoesNotOccur();
3116     }
3117 
3118     /**
3119      * Verify that if a NETWORK_DISCONNECTION_EVENT is received in ConnectedState, then an
3120      * abnormal disconnect is reported to BssidBlocklistMonitor.
3121      */
3122     @Test
testAbnormalDisconnectNotifiesBssidBlocklistMonitor()3123     public void testAbnormalDisconnectNotifiesBssidBlocklistMonitor() throws Exception {
3124         // trigger RSSI poll to update WifiInfo
3125         mCmi.enableRssiPolling(true);
3126         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
3127         llStats.txmpdu_be = 1000;
3128         llStats.rxmpdu_bk = 2000;
3129         WifiNl80211Manager.SignalPollResult signalPollResult =
3130                 new WifiNl80211Manager.SignalPollResult(TEST_RSSI, 65, 54, sFreq);
3131         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
3132         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult);
3133 
3134         connect();
3135         mLooper.dispatchAll();
3136         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
3137         mLooper.dispatchAll();
3138 
3139         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3140                 BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, false);
3141     }
3142 
3143     /**
3144      * Verify that ClientModeImpl notifies BssidBlocklistMonitor correctly when the RSSI is
3145      * too low.
3146      */
3147     @Test
testNotifiesBssidBlocklistMonitorLowRssi()3148     public void testNotifiesBssidBlocklistMonitorLowRssi() throws Exception {
3149         initializeAndAddNetworkAndVerifySuccess();
3150         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0,
3151                 ClientModeImpl.SUPPLICANT_BSSID_ANY);
3152         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 1, 0, sBSSID);
3153         when(mWifiConfigManager.findScanRssi(eq(FRAMEWORK_NETWORK_ID), anyInt())).thenReturn(-80);
3154         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
3155                 .thenReturn(mScanDetailCache);
3156         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
3157                 getGoogleGuestScanDetail(-80, sBSSID, sFreq));
3158         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
3159                 getGoogleGuestScanDetail(-80, sBSSID, sFreq).getScanResult());
3160         mLooper.dispatchAll();
3161 
3162         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3163                 BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, true);
3164     }
3165 
3166     /**
3167      * Verifies that the BssidBlocklistMonitor is notified, but the WifiLastResortWatchdog is
3168      * not notified of association rejections of type REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA.
3169      * @throws Exception
3170      */
3171     @Test
testAssociationRejectionWithReasonApUnableToHandleNewStaUpdatesWatchdog()3172     public void testAssociationRejectionWithReasonApUnableToHandleNewStaUpdatesWatchdog()
3173             throws Exception {
3174         initializeAndAddNetworkAndVerifySuccess();
3175         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3176         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0,
3177                 ClientModeImpl.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID);
3178         mLooper.dispatchAll();
3179         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
3180                 anyString(), anyString(), anyInt());
3181         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3182                 BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
3183     }
3184 
3185     /**
3186      * Verifies that WifiLastResortWatchdog and BssidBlocklistMonitor is notified of
3187      * general association rejection failures.
3188      * @throws Exception
3189      */
3190     @Test
testAssociationRejectionUpdatesWatchdog()3191     public void testAssociationRejectionUpdatesWatchdog() throws Exception {
3192         initializeAndAddNetworkAndVerifySuccess();
3193         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID);
3194         config.carrierId = CARRIER_ID_1;
3195         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3196         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 0, sBSSID);
3197         mLooper.dispatchAll();
3198         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
3199                 anyString(), anyString(), anyInt());
3200         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3201                 BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION, false);
3202         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionNonAuthFailure();
3203     }
3204 
3205     /**
3206      * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type
3207      * ERROR_AUTH_FAILURE_WRONG_PSWD.
3208      * @throws Exception
3209      */
3210     @Test
testFailureWrongPassIsIgnoredByWatchdog()3211     public void testFailureWrongPassIsIgnoredByWatchdog() throws Exception {
3212         // Setup CONNECT_MODE & a WifiConfiguration
3213         initializeAndAddNetworkAndVerifySuccess();
3214         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3215         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3216                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
3217         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3218                 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
3219         mLooper.dispatchAll();
3220         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
3221                 anyString(), anyString(), anyInt());
3222         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3223                 BssidBlocklistMonitor.REASON_WRONG_PASSWORD, false);
3224     }
3225 
3226     /**
3227      * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type
3228      * ERROR_AUTH_FAILURE_EAP_FAILURE.
3229      * @throws Exception
3230      */
3231     @Test
testEapFailureIsIgnoredByWatchdog()3232     public void testEapFailureIsIgnoredByWatchdog() throws Exception {
3233         // Setup CONNECT_MODE & a WifiConfiguration
3234         initializeAndAddNetworkAndVerifySuccess();
3235         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3236         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3237                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
3238         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3239                 WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE);
3240         mLooper.dispatchAll();
3241         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
3242                 anyString(), anyString(), anyInt());
3243         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3244                 BssidBlocklistMonitor.REASON_EAP_FAILURE, false);
3245     }
3246 
3247     /**
3248      * Verifies that WifiLastResortWatchdog is notified of other types of authentication failures.
3249      * @throws Exception
3250      */
3251     @Test
testAuthenticationFailureUpdatesWatchdog()3252     public void testAuthenticationFailureUpdatesWatchdog() throws Exception {
3253         // Setup CONNECT_MODE & a WifiConfiguration
3254         initializeAndAddNetworkAndVerifySuccess();
3255         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3256         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3257                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
3258         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3259                 WifiManager.ERROR_AUTH_FAILURE_TIMEOUT);
3260         mLooper.dispatchAll();
3261         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
3262                 anyString(), anyString(), anyInt());
3263         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3264                 BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE, false);
3265     }
3266 
3267     /**
3268      * Verify that BssidBlocklistMonitor is notified of the SSID pre-connection so that it could
3269      * send down to firmware the list of blocked BSSIDs.
3270      */
3271     @Test
testBssidBlocklistSentToFirmwareAfterCmdStartConnect()3272     public void testBssidBlocklistSentToFirmwareAfterCmdStartConnect() throws Exception {
3273         initializeAndAddNetworkAndVerifySuccess();
3274         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3275         verify(mBssidBlocklistMonitor, never()).updateFirmwareRoamingConfiguration(sSSID);
3276         mLooper.dispatchAll();
3277         verify(mBssidBlocklistMonitor).updateFirmwareRoamingConfiguration(sSSID);
3278         // But don't expect to see connection success yet
3279         verify(mWifiScoreCard, never()).noteIpConfiguration(any());
3280         // And certainly not validation success
3281         verify(mWifiScoreCard, never()).noteValidationSuccess(any());
3282     }
3283 
3284     /**
3285      * Verifies that dhcp failures make WifiDiagnostics report CONNECTION_EVENT_FAILED and then
3286      * cancel any pending timeouts.
3287      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
3288      * @throws Exception
3289      */
3290     @Test
testReportConnectionEventIsCalledAfterDhcpFailure()3291     public void testReportConnectionEventIsCalledAfterDhcpFailure() throws Exception {
3292         mConnectedNetwork.getNetworkSelectionStatus()
3293                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
3294         testDhcpFailure();
3295         verify(mWifiDiagnostics, atLeastOnce()).reportConnectionEvent(
3296                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED));
3297         verify(mWifiConnectivityManager, atLeastOnce()).handleConnectionAttemptEnded(
3298                 WifiMetrics.ConnectionEvent.FAILURE_DHCP, sBSSID, sSSID);
3299         verify(mWifiNetworkFactory, atLeastOnce()).handleConnectionAttemptEnded(
3300                 eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class));
3301         verify(mWifiNetworkSuggestionsManager, atLeastOnce()).handleConnectionAttemptEnded(
3302                 eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class),
3303                 any(String.class));
3304         verify(mWifiMetrics, never())
3305                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
3306         verifyConnectionEventTimeoutDoesNotOccur();
3307     }
3308 
3309     /**
3310      * Verifies that a successful validation make WifiDiagnostics report CONNECTION_EVENT_SUCCEEDED
3311      * and then cancel any pending timeouts.
3312      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
3313      * @throws Exception
3314      */
3315     @Test
testReportConnectionEventIsCalledAfterSuccessfulConnection()3316     public void testReportConnectionEventIsCalledAfterSuccessfulConnection() throws Exception {
3317         mConnectedNetwork.getNetworkSelectionStatus()
3318                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, sBSSID1, sFreq).getScanResult());
3319         connect();
3320         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
3321         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
3322                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
3323                 anyInt(), any(NetworkAgentConfig.class), anyInt());
3324 
3325         Message message = new Message();
3326         message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS;
3327         message.arg1 = NetworkAgent.VALID_NETWORK;
3328         message.obj = new Bundle();
3329         messengerCaptor.getValue().send(message);
3330         mLooper.dispatchAll();
3331 
3332         verify(mWifiDiagnostics).reportConnectionEvent(
3333                 eq(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED));
3334         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
3335                 WifiMetrics.ConnectionEvent.FAILURE_NONE, sBSSID, sSSID);
3336         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
3337                 eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), any(WifiConfiguration.class));
3338         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
3339                 eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), any(WifiConfiguration.class),
3340                 any(String.class));
3341         // BSSID different, record this connection.
3342         verify(mWifiMetrics).incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
3343         verifyConnectionEventTimeoutDoesNotOccur();
3344     }
3345 
3346     /**
3347      * Verify that score card is notified of a connection attempt
3348      */
3349     @Test
testScoreCardNoteConnectionAttemptAfterCmdStartConnect()3350     public void testScoreCardNoteConnectionAttemptAfterCmdStartConnect() throws Exception {
3351         initializeAndAddNetworkAndVerifySuccess();
3352         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
3353         verify(mWifiScoreCard, never()).noteConnectionAttempt(any(), anyInt(), anyString());
3354         mLooper.dispatchAll();
3355         verify(mWifiScoreCard).noteConnectionAttempt(any(), anyInt(), anyString());
3356         verify(mWifiConfigManager).findScanRssi(anyInt(), anyInt());
3357         // But don't expect to see connection success yet
3358         verify(mWifiScoreCard, never()).noteIpConfiguration(any());
3359         // And certainly not validation success
3360         verify(mWifiScoreCard, never()).noteValidationSuccess(any());
3361 
3362     }
3363 
3364     /**
3365      * Verify that score card is notified of a successful connection
3366      */
3367     @Test
testScoreCardNoteConnectionComplete()3368     public void testScoreCardNoteConnectionComplete() throws Exception {
3369         Pair<String, String> l2KeyAndCluster = Pair.create("Wad", "Gab");
3370         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(l2KeyAndCluster);
3371         connect();
3372         mLooper.dispatchAll();
3373         verify(mWifiScoreCard).noteIpConfiguration(any());
3374         ArgumentCaptor<Layer2InformationParcelable> captor =
3375                 ArgumentCaptor.forClass(Layer2InformationParcelable.class);
3376         verify(mIpClient, atLeastOnce()).updateLayer2Information(captor.capture());
3377         final Layer2InformationParcelable info = captor.getValue();
3378         assertEquals(info.l2Key, "Wad");
3379         assertEquals(info.cluster, "Gab");
3380     }
3381 
3382     /**
3383      * Verify that score card/health monitor are notified when wifi is disabled while disconnected
3384      */
3385     @Test
testScoreCardNoteWifiDisabledWhileDisconnected()3386     public void testScoreCardNoteWifiDisabledWhileDisconnected() throws Exception {
3387         // connecting and disconnecting shouldn't note wifi disabled
3388         disconnect();
3389         mLooper.dispatchAll();
3390 
3391         verify(mWifiScoreCard, times(1)).resetConnectionState();
3392         verify(mWifiScoreCard, never()).noteWifiDisabled(any());
3393         verify(mWifiHealthMonitor, never()).setWifiEnabled(false);
3394 
3395         // disabling while disconnected should note wifi disabled
3396         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED);
3397         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3398         mLooper.dispatchAll();
3399         verify(mWifiScoreCard, times(2)).resetConnectionState();
3400         verify(mWifiHealthMonitor).setWifiEnabled(false);
3401     }
3402 
3403     /**
3404      * Verify that score card/health monitor are notified when wifi is disabled while connected
3405      */
3406     @Test
testScoreCardNoteWifiDisabledWhileConnected()3407     public void testScoreCardNoteWifiDisabledWhileConnected() throws Exception {
3408         // Get into connected state
3409         connect();
3410         mLooper.dispatchAll();
3411         verify(mWifiScoreCard, never()).noteWifiDisabled(any());
3412         verify(mWifiHealthMonitor, never()).setWifiEnabled(false);
3413 
3414         // disabling while connected should note wifi disabled
3415         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_DISABLED);
3416         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3417         mLooper.dispatchAll();
3418 
3419         verify(mWifiScoreCard).noteWifiDisabled(any());
3420         verify(mWifiScoreCard).resetConnectionState();
3421         verify(mWifiHealthMonitor).setWifiEnabled(false);
3422     }
3423 
3424     /**
3425      * Verify that we do not crash on quick toggling wifi on/off
3426      */
3427     @Test
quickTogglesDoNotCrash()3428     public void quickTogglesDoNotCrash() throws Exception {
3429         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3430         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3431         mLooper.dispatchAll();
3432 
3433         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3434         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3435         mLooper.dispatchAll();
3436 
3437         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3438         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3439         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3440         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3441         mLooper.dispatchAll();
3442 
3443         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3444         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3445         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3446         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3447         mLooper.dispatchAll();
3448     }
3449 
3450     /**
3451      * Verify that valid calls to set the current wifi state are returned when requested.
3452      */
3453     @Test
verifySetAndGetWifiStateCallsWorking()3454     public void verifySetAndGetWifiStateCallsWorking() throws Exception {
3455         // we start off disabled
3456         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
3457 
3458         // now check after updating
3459         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_UNKNOWN);
3460         assertEquals(WifiManager.WIFI_STATE_UNKNOWN, mCmi.syncGetWifiState());
3461 
3462         // check after two updates
3463         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLING);
3464         mCmi.setWifiStateForApiCalls(WifiManager.WIFI_STATE_ENABLED);
3465         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
3466     }
3467 
3468     /**
3469      * Verify that invalid states do not change the saved wifi state.
3470      */
3471     @Test
verifyInvalidStatesDoNotChangeSavedWifiState()3472     public void verifyInvalidStatesDoNotChangeSavedWifiState() throws Exception {
3473         int invalidStateNegative = -1;
3474         int invalidStatePositive = 5;
3475 
3476         // we start off disabled
3477         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
3478 
3479         mCmi.setWifiStateForApiCalls(invalidStateNegative);
3480         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
3481 
3482         mCmi.setWifiStateForApiCalls(invalidStatePositive);
3483         assertEquals(WifiManager.WIFI_STATE_DISABLED, mCmi.syncGetWifiState());
3484     }
3485 
3486     /**
3487      * Verify that IPClient instance is shutdown when wifi is disabled.
3488      */
3489     @Test
verifyIpClientShutdownWhenDisabled()3490     public void verifyIpClientShutdownWhenDisabled() throws Exception {
3491         loadComponentsInStaMode();
3492 
3493         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3494         mLooper.dispatchAll();
3495         verify(mIpClient).shutdown();
3496         verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks();
3497         verify(mWifiConfigManager).clearUserTemporarilyDisabledList();
3498     }
3499 
3500     /**
3501      * Verify that WifiInfo's MAC address is updated when the state machine receives
3502      * NETWORK_CONNECTION_EVENT while in ConnectedState.
3503      */
3504     @Test
verifyWifiInfoMacUpdatedWithNetworkConnectionWhileConnected()3505     public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileConnected() throws Exception {
3506         connect();
3507         assertEquals("ConnectedState", getCurrentState().getName());
3508         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
3509 
3510         // Verify receiving a NETWORK_CONNECTION_EVENT changes the MAC in WifiInfo
3511         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
3512                 .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString());
3513         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
3514         mLooper.dispatchAll();
3515         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
3516     }
3517 
3518     /**
3519      * Verify that WifiInfo's MAC address is updated when the state machine receives
3520      * NETWORK_CONNECTION_EVENT while in DisconnectedState.
3521      */
3522     @Test
verifyWifiInfoMacUpdatedWithNetworkConnectionWhileDisconnected()3523     public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileDisconnected() throws Exception {
3524         disconnect();
3525         assertEquals("DisconnectedState", getCurrentState().getName());
3526         // Since MAC randomization is enabled, wifiInfo's MAC should be set to default MAC
3527         // when disconnect happens.
3528         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mCmi.getWifiInfo().getMacAddress());
3529 
3530         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
3531                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
3532         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
3533         mLooper.dispatchAll();
3534         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mCmi.getWifiInfo().getMacAddress());
3535     }
3536 
3537     /**
3538      * Verify that we temporarily disable the network when auto-connected to a network
3539      * with no internet access.
3540      */
3541     @Test
verifyAutoConnectedNetworkWithInternetValidationFailure()3542     public void verifyAutoConnectedNetworkWithInternetValidationFailure() throws Exception {
3543         // Setup RSSI poll to update WifiInfo with low RSSI
3544         mCmi.enableRssiPolling(true);
3545         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
3546         llStats.txmpdu_be = 1000;
3547         llStats.rxmpdu_bk = 2000;
3548         WifiNl80211Manager.SignalPollResult signalPollResult =
3549                 new WifiNl80211Manager.SignalPollResult(RSSI_THRESHOLD_BREACH_MIN, 65, 54, sFreq);
3550         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
3551         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResult);
3552 
3553         // Simulate the first connection.
3554         connect();
3555         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
3556         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
3557                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
3558                 anyInt(), any(NetworkAgentConfig.class), anyInt());
3559 
3560         WifiConfiguration currentNetwork = new WifiConfiguration();
3561         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
3562         currentNetwork.SSID = DEFAULT_TEST_SSID;
3563         currentNetwork.noInternetAccessExpected = false;
3564         currentNetwork.numNoInternetAccessReports = 1;
3565         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
3566                 .thenReturn(currentNetwork);
3567         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
3568 
3569         Message message = new Message();
3570         message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS;
3571         message.arg1 = NetworkAgent.INVALID_NETWORK;
3572         message.obj = new Bundle();
3573         messengerCaptor.getValue().send(message);
3574         mLooper.dispatchAll();
3575 
3576         verify(mWifiConfigManager)
3577                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
3578         verify(mWifiConfigManager).updateNetworkSelectionStatus(
3579                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
3580         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
3581                 BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, true);
3582         verify(mWifiScoreCard).noteValidationFailure(any());
3583     }
3584 
3585     /**
3586      * Verify that we don't temporarily disable the network when user selected to connect to a
3587      * network with no internet access.
3588      */
3589     @Test
verifyLastSelectedNetworkWithInternetValidationFailure()3590     public void verifyLastSelectedNetworkWithInternetValidationFailure() throws Exception {
3591         // Simulate the first connection.
3592         connect();
3593         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
3594         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
3595                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
3596                 anyInt(), any(NetworkAgentConfig.class), anyInt());
3597 
3598         WifiConfiguration currentNetwork = new WifiConfiguration();
3599         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
3600         currentNetwork.noInternetAccessExpected = false;
3601         currentNetwork.numNoInternetAccessReports = 1;
3602         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
3603                 .thenReturn(currentNetwork);
3604         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID);
3605 
3606         Message message = new Message();
3607         message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS;
3608         message.arg1 = NetworkAgent.INVALID_NETWORK;
3609         message.obj = new Bundle();
3610         messengerCaptor.getValue().send(message);
3611         mLooper.dispatchAll();
3612 
3613         verify(mWifiConfigManager)
3614                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
3615         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(
3616                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
3617     }
3618 
3619     /**
3620      * Verify that we temporarily disable the network when auto-connected to a network
3621      * with no internet access.
3622      */
3623     @Test
verifyAutoConnectedNoInternetExpectedNetworkWithInternetValidationFailure()3624     public void verifyAutoConnectedNoInternetExpectedNetworkWithInternetValidationFailure()
3625             throws Exception {
3626         // Simulate the first connection.
3627         connect();
3628         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
3629         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
3630                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
3631                 anyInt(), any(NetworkAgentConfig.class), anyInt());
3632 
3633         WifiConfiguration currentNetwork = new WifiConfiguration();
3634         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
3635         currentNetwork.noInternetAccessExpected = true;
3636         currentNetwork.numNoInternetAccessReports = 1;
3637         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
3638                 .thenReturn(currentNetwork);
3639         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
3640 
3641         Message message = new Message();
3642         message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS;
3643         message.arg1 = NetworkAgent.INVALID_NETWORK;
3644         message.obj = new Bundle();
3645         messengerCaptor.getValue().send(message);
3646         mLooper.dispatchAll();
3647 
3648         verify(mWifiConfigManager)
3649                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
3650         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(
3651                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
3652     }
3653 
3654     /**
3655      * Verify that we enable the network when we detect validated internet access.
3656      */
3657     @Test
verifyNetworkSelectionEnableOnInternetValidation()3658     public void verifyNetworkSelectionEnableOnInternetValidation() throws Exception {
3659         // Simulate the first connection.
3660         connect();
3661         verify(mBssidBlocklistMonitor).handleBssidConnectionSuccess(sBSSID, sSSID);
3662         verify(mBssidBlocklistMonitor).handleDhcpProvisioningSuccess(sBSSID, sSSID);
3663         verify(mBssidBlocklistMonitor, never()).handleNetworkValidationSuccess(sBSSID, sSSID);
3664 
3665         ArgumentCaptor<Messenger> messengerCaptor = ArgumentCaptor.forClass(Messenger.class);
3666         verify(mConnectivityManager).registerNetworkAgent(messengerCaptor.capture(),
3667                 any(NetworkInfo.class), any(LinkProperties.class), any(NetworkCapabilities.class),
3668                 anyInt(), any(NetworkAgentConfig.class), anyInt());
3669 
3670         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
3671 
3672         Message message = new Message();
3673         message.what = NetworkAgent.CMD_REPORT_NETWORK_STATUS;
3674         message.arg1 = NetworkAgent.VALID_NETWORK;
3675         message.obj = new Bundle();
3676         messengerCaptor.getValue().send(message);
3677         mLooper.dispatchAll();
3678 
3679         verify(mWifiConfigManager)
3680                 .setNetworkValidatedInternetAccess(FRAMEWORK_NETWORK_ID, true);
3681         verify(mWifiConfigManager).updateNetworkSelectionStatus(
3682                 FRAMEWORK_NETWORK_ID, DISABLED_NONE);
3683         verify(mWifiScoreCard).noteValidationSuccess(any());
3684         verify(mBssidBlocklistMonitor).handleNetworkValidationSuccess(sBSSID, sSSID);
3685     }
3686 
connectWithValidInitRssi(int initRssiDbm)3687     private void connectWithValidInitRssi(int initRssiDbm) throws Exception {
3688         triggerConnect();
3689         mCmi.getWifiInfo().setRssi(initRssiDbm);
3690         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3691                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED));
3692         mLooper.dispatchAll();
3693 
3694         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
3695         mLooper.dispatchAll();
3696 
3697         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3698                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
3699         mLooper.dispatchAll();
3700 
3701         assertEquals("ObtainingIpState", getCurrentState().getName());
3702     }
3703 
3704     /**
3705      * Verify that we set the INTERNET and bandwidth capability in the network agent when connected
3706      * as a result of auto-join/legacy API's. Also verify up/down stream bandwidth values when
3707      * Rx link speed is unavailable.
3708      */
3709     @Test
verifyNetworkCapabilities()3710     public void verifyNetworkCapabilities() throws Exception {
3711         when(mWifiDataStall.getTxThroughputKbps()).thenReturn(70_000);
3712         when(mWifiDataStall.getRxThroughputKbps()).thenReturn(-1);
3713         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any()))
3714                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
3715         // Simulate the first connection.
3716         connectWithValidInitRssi(-42);
3717 
3718         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
3719                 ArgumentCaptor.forClass(NetworkCapabilities.class);
3720         verify(mConnectivityManager).registerNetworkAgent(any(Messenger.class),
3721                 any(NetworkInfo.class), any(LinkProperties.class),
3722                 networkCapabilitiesCaptor.capture(), anyInt(), any(NetworkAgentConfig.class),
3723                 anyInt());
3724 
3725         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
3726         assertNotNull(networkCapabilities);
3727 
3728         // Should have internet capability.
3729         assertTrue(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
3730         assertNull(networkCapabilities.getNetworkSpecifier());
3731 
3732         assertEquals(mConnectedNetwork.creatorUid, networkCapabilities.getOwnerUid());
3733         assertArrayEquals(
3734                 new int[] {mConnectedNetwork.creatorUid},
3735                 networkCapabilities.getAdministratorUids());
3736 
3737         // Should set bandwidth correctly
3738         assertEquals(-42, mCmi.getWifiInfo().getRssi());
3739         assertEquals(70_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
3740         assertEquals(70_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
3741     }
3742 
3743     /**
3744      * Verify that we don't set the INTERNET capability in the network agent when connected
3745      * as a result of the new network request API. Also verify up/down stream bandwidth values
3746      * when both Tx and Rx link speed are unavailable.
3747      */
3748     @Test
verifyNetworkCapabilitiesForSpecificRequest()3749     public void verifyNetworkCapabilitiesForSpecificRequest() throws Exception {
3750         when(mWifiDataStall.getTxThroughputKbps()).thenReturn(-1);
3751         when(mWifiDataStall.getRxThroughputKbps()).thenReturn(-1);
3752         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any()))
3753                 .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME));
3754         // Simulate the first connection.
3755         connectWithValidInitRssi(-42);
3756         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
3757                 ArgumentCaptor.forClass(NetworkCapabilities.class);
3758         verify(mConnectivityManager).registerNetworkAgent(any(Messenger.class),
3759                 any(NetworkInfo.class), any(LinkProperties.class),
3760                 networkCapabilitiesCaptor.capture(), anyInt(), any(NetworkAgentConfig.class),
3761                 anyInt());
3762 
3763         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
3764         assertNotNull(networkCapabilities);
3765 
3766         // should not have internet capability.
3767         assertFalse(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
3768 
3769         NetworkSpecifier networkSpecifier = networkCapabilities.getNetworkSpecifier();
3770         assertTrue(networkSpecifier instanceof WifiNetworkAgentSpecifier);
3771         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
3772                 (WifiNetworkAgentSpecifier) networkSpecifier;
3773         WifiNetworkAgentSpecifier expectedWifiNetworkAgentSpecifier =
3774                 new WifiNetworkAgentSpecifier(mCmi.getCurrentWifiConfiguration());
3775         assertEquals(expectedWifiNetworkAgentSpecifier, wifiNetworkAgentSpecifier);
3776         assertEquals(TEST_UID, networkCapabilities.getRequestorUid());
3777         assertEquals(OP_PACKAGE_NAME, networkCapabilities.getRequestorPackageName());
3778         assertEquals(90_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
3779         assertEquals(80_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
3780     }
3781 
3782     /**
3783      * Verify that we check for data stall during rssi poll
3784      * and then check that wifi link layer usage data are being updated.
3785      */
3786     @Test
verifyRssiPollChecksDataStall()3787     public void verifyRssiPollChecksDataStall() throws Exception {
3788         mCmi.enableRssiPolling(true);
3789         connect();
3790 
3791         WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
3792         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
3793         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
3794         mLooper.dispatchAll();
3795         WifiLinkLayerStats newLLStats = new WifiLinkLayerStats();
3796         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(newLLStats);
3797         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
3798         mLooper.dispatchAll();
3799         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(
3800                 oldLLStats, newLLStats, mCmi.getWifiInfo());
3801         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(newLLStats);
3802     }
3803 
3804     /**
3805      * Verify that we update wifi usability stats entries during rssi poll and that when we get
3806      * a data stall we label and save the current list of usability stats entries.
3807      * @throws Exception
3808      */
3809     @Test
verifyRssiPollUpdatesWifiUsabilityMetrics()3810     public void verifyRssiPollUpdatesWifiUsabilityMetrics() throws Exception {
3811         mCmi.enableRssiPolling(true);
3812         connect();
3813 
3814         WifiLinkLayerStats stats = new WifiLinkLayerStats();
3815         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats);
3816         when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any()))
3817                 .thenReturn(WifiIsUnusableEvent.TYPE_UNKNOWN);
3818         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
3819         mLooper.dispatchAll();
3820         verify(mWifiMetrics).updateWifiUsabilityStatsEntries(any(), eq(stats));
3821         verify(mWifiMetrics, never()).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3822                 eq(anyInt()), eq(-1));
3823 
3824         when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any()))
3825                 .thenReturn(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX);
3826         when(mClock.getElapsedSinceBootMillis()).thenReturn(10L);
3827         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
3828         mLooper.dispatchAll();
3829         verify(mWifiMetrics, times(2)).updateWifiUsabilityStatsEntries(any(), eq(stats));
3830         when(mClock.getElapsedSinceBootMillis())
3831                 .thenReturn(10L + ClientModeImpl.DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS);
3832         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
3833         mLooper.dispatchAll();
3834         verify(mWifiMetrics).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
3835                 WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, -1);
3836     }
3837 
3838     /**
3839      * Verify that when ordered to setPowerSave(true) while Interface is created,
3840      * WifiNative is called with the right powerSave mode.
3841      */
3842     @Test
verifySetPowerSaveTrueSuccess()3843     public void verifySetPowerSaveTrueSuccess() throws Exception {
3844         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3845         assertTrue(mCmi.setPowerSave(true));
3846         verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true);
3847     }
3848 
3849     /**
3850      * Verify that when ordered to setPowerSave(false) while Interface is created,
3851      * WifiNative is called with the right powerSave mode.
3852      */
3853     @Test
verifySetPowerSaveFalseSuccess()3854     public void verifySetPowerSaveFalseSuccess() throws Exception {
3855         mCmi.setOperationalMode(ClientModeImpl.CONNECT_MODE, WIFI_IFACE_NAME);
3856         assertTrue(mCmi.setPowerSave(false));
3857         verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
3858     }
3859 
3860     /**
3861      * Verify that when interface is not created yet (InterfaceName is null),
3862      * then setPowerSave() returns with error and no call in WifiNative happens.
3863      */
3864     @Test
verifySetPowerSaveFailure()3865     public void verifySetPowerSaveFailure() throws Exception {
3866         boolean powerSave = true;
3867         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
3868         assertFalse(mCmi.setPowerSave(powerSave));
3869         verify(mWifiNative, never()).setPowerSave(anyString(), anyBoolean());
3870     }
3871 
3872     /**
3873      * Verify that we call into WifiTrafficPoller during rssi poll
3874      */
3875     @Test
verifyRssiPollCallsWifiTrafficPoller()3876     public void verifyRssiPollCallsWifiTrafficPoller() throws Exception {
3877         mCmi.enableRssiPolling(true);
3878         connect();
3879 
3880         verify(mWifiTrafficPoller).notifyOnDataActivity(anyLong(), anyLong());
3881     }
3882 
3883     /**
3884      * Verify that LinkProbeManager is updated during RSSI poll
3885      */
3886     @Test
verifyRssiPollCallsLinkProbeManager()3887     public void verifyRssiPollCallsLinkProbeManager() throws Exception {
3888         mCmi.enableRssiPolling(true);
3889 
3890         connect();
3891         // reset() should be called when RSSI polling is enabled and entering L2ConnectedState
3892         verify(mLinkProbeManager).resetOnNewConnection(); // called first time here
3893         verify(mLinkProbeManager, never()).resetOnScreenTurnedOn(); // not called
3894         verify(mLinkProbeManager).updateConnectionStats(any(), any());
3895 
3896         mCmi.enableRssiPolling(false);
3897         mLooper.dispatchAll();
3898         // reset() should be called when in L2ConnectedState (or child states) and RSSI polling
3899         // becomes enabled
3900         mCmi.enableRssiPolling(true);
3901         mLooper.dispatchAll();
3902         verify(mLinkProbeManager, times(1)).resetOnNewConnection(); // verify not called again
3903         verify(mLinkProbeManager).resetOnScreenTurnedOn(); // verify called here
3904     }
3905 
3906     /**
3907      * Verify that when ordered to setLowLatencyMode(true),
3908      * WifiNative is called with the right lowLatency mode.
3909      */
3910     @Test
verifySetLowLatencyTrueSuccess()3911     public void verifySetLowLatencyTrueSuccess() throws Exception {
3912         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true);
3913         assertTrue(mCmi.setLowLatencyMode(true));
3914         verify(mWifiNative).setLowLatencyMode(true);
3915     }
3916 
3917     /**
3918      * Verify that when ordered to setLowLatencyMode(false),
3919      * WifiNative is called with the right lowLatency mode.
3920      */
3921     @Test
verifySetLowLatencyFalseSuccess()3922     public void verifySetLowLatencyFalseSuccess() throws Exception {
3923         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true);
3924         assertTrue(mCmi.setLowLatencyMode(false));
3925         verify(mWifiNative).setLowLatencyMode(false);
3926     }
3927 
3928     /**
3929      * Verify that when WifiNative fails to set low latency mode,
3930      * then the call setLowLatencyMode() returns with failure,
3931      */
3932     @Test
verifySetLowLatencyModeFailure()3933     public void verifySetLowLatencyModeFailure() throws Exception {
3934         final boolean lowLatencyMode = true;
3935         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(false);
3936         assertFalse(mCmi.setLowLatencyMode(lowLatencyMode));
3937         verify(mWifiNative).setLowLatencyMode(eq(lowLatencyMode));
3938     }
3939 
3940     /**
3941      * Verify getting the factory MAC address success case.
3942      */
3943     @Test
testGetFactoryMacAddressSuccess()3944     public void testGetFactoryMacAddressSuccess() throws Exception {
3945         initializeAndAddNetworkAndVerifySuccess();
3946         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
3947         verify(mWifiNative).getFactoryMacAddress(WIFI_IFACE_NAME);
3948         verify(mWifiNative).getMacAddress(anyString()); // called once when setting up client mode
3949     }
3950 
3951     /**
3952      * Verify getting the factory MAC address failure case.
3953      */
3954     @Test
testGetFactoryMacAddressFail()3955     public void testGetFactoryMacAddressFail() throws Exception {
3956         initializeAndAddNetworkAndVerifySuccess();
3957         when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
3958         assertNull(mCmi.getFactoryMacAddress());
3959         verify(mWifiNative).getFactoryMacAddress(WIFI_IFACE_NAME);
3960         verify(mWifiNative).getMacAddress(anyString()); // called once when setting up client mode
3961     }
3962 
3963     /**
3964      * Verify that when WifiNative#getFactoryMacAddress fails, if the device does not support
3965      * MAC randomization then the currently programmed MAC address gets returned.
3966      */
3967     @Test
testGetFactoryMacAddressFailWithNoMacRandomizationSupport()3968     public void testGetFactoryMacAddressFailWithNoMacRandomizationSupport() throws Exception {
3969         mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false);
3970         initializeCmi();
3971         initializeAndAddNetworkAndVerifySuccess();
3972         when(mWifiNative.getFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
3973         mCmi.getFactoryMacAddress();
3974         verify(mWifiNative).getFactoryMacAddress(anyString());
3975         verify(mWifiNative, times(2)).getMacAddress(WIFI_IFACE_NAME);
3976     }
3977 
3978     @Test
testSetDeviceMobilityState()3979     public void testSetDeviceMobilityState() {
3980         mCmi.setDeviceMobilityState(WifiManager.DEVICE_MOBILITY_STATE_STATIONARY);
3981         verify(mWifiConnectivityManager).setDeviceMobilityState(
3982                 WifiManager.DEVICE_MOBILITY_STATE_STATIONARY);
3983         verify(mWifiHealthMonitor).setDeviceMobilityState(
3984                 WifiManager.DEVICE_MOBILITY_STATE_STATIONARY);
3985         verify(mWifiDataStall).setDeviceMobilityState(
3986                 WifiManager.DEVICE_MOBILITY_STATE_STATIONARY);
3987     }
3988 
3989     /**
3990      * Verify the MAC address is being randomized at start to prevent leaking the factory MAC.
3991      */
3992     @Test
testRandomizeMacAddressOnStart()3993     public void testRandomizeMacAddressOnStart() throws Exception {
3994         ArgumentCaptor<MacAddress> macAddressCaptor = ArgumentCaptor.forClass(MacAddress.class);
3995         loadComponentsInStaMode();
3996         verify(mWifiNative).setMacAddress(anyString(), macAddressCaptor.capture());
3997         MacAddress currentMac = macAddressCaptor.getValue();
3998 
3999         assertNotEquals("The currently programmed MAC address should be different from the factory "
4000                 + "MAC address after ClientModeImpl starts",
4001                 mCmi.getFactoryMacAddress(), currentMac.toString());
4002     }
4003 
4004     /**
4005      * Verify the MAC address is being randomized at start to prevent leaking the factory MAC.
4006      */
4007     @Test
testNoRandomizeMacAddressOnStartIfMacRandomizationNotEnabled()4008     public void testNoRandomizeMacAddressOnStartIfMacRandomizationNotEnabled() throws Exception {
4009         mResources.setBoolean(R.bool.config_wifi_connected_mac_randomization_supported, false);
4010         loadComponentsInStaMode();
4011         verify(mWifiNative, never()).setMacAddress(anyString(), any());
4012     }
4013 
4014     /**
4015      * Verify bugreport will be taken when get IP_REACHABILITY_LOST
4016      */
4017     @Test
testTakebugreportbyIpReachabilityLost()4018     public void testTakebugreportbyIpReachabilityLost() throws Exception {
4019         connect();
4020 
4021         mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST);
4022         mLooper.dispatchAll();
4023         verify(mWifiDiagnostics).captureBugReportData(
4024                 eq(WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST));
4025     }
4026 
4027     /**
4028      * Verify removing sim will also remove an ephemeral Passpoint Provider. And reset carrier
4029      * privileged suggestor apps.
4030      */
4031     @Test
testResetSimNetworkWhenRemovingSim()4032     public void testResetSimNetworkWhenRemovingSim() throws Exception {
4033         // Switch to connect mode and verify wifi is reported as enabled
4034         startSupplicantAndDispatchMessages();
4035 
4036         // Indicate that sim is removed.
4037         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
4038                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
4039         mLooper.dispatchAll();
4040 
4041         verify(mWifiConfigManager).resetSimNetworks();
4042         verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps();
4043     }
4044 
4045     /**
4046      * Verify inserting sim will reset carrier privileged suggestor apps.
4047      * and remove any previous notifications due to sim removal
4048      */
4049     @Test
testResetCarrierPrivilegedAppsWhenInsertingSim()4050     public void testResetCarrierPrivilegedAppsWhenInsertingSim() throws Exception {
4051         // Switch to connect mode and verify wifi is reported as enabled
4052         startSupplicantAndDispatchMessages();
4053 
4054         // Indicate that sim is inserted.
4055         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
4056                 ClientModeImpl.RESET_SIM_REASON_SIM_INSERTED);
4057         mLooper.dispatchAll();
4058 
4059         verify(mWifiConfigManager, never()).resetSimNetworks();
4060         verify(mWifiNetworkSuggestionsManager).resetCarrierPrivilegedApps();
4061         verify(mSimRequiredNotifier).dismissSimRequiredNotification();
4062     }
4063 
4064     /**
4065      * Verifies that WifiLastResortWatchdog is notified of FOURWAY_HANDSHAKE_TIMEOUT.
4066      */
4067     @Test
testHandshakeTimeoutUpdatesWatchdog()4068     public void testHandshakeTimeoutUpdatesWatchdog() throws Exception {
4069         // Setup CONNECT_MODE & a WifiConfiguration
4070         initializeAndAddNetworkAndVerifySuccess();
4071         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4072         mLooper.dispatchAll();
4073         // Verifies that WifiLastResortWatchdog won't be notified
4074         // by other reason code
4075         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 2, sBSSID);
4076         mLooper.dispatchAll();
4077 
4078         assertEquals("DisconnectedState", getCurrentState().getName());
4079         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
4080                 sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION);
4081 
4082         // Verifies that WifiLastResortWatchdog be notified
4083         // for FOURWAY_HANDSHAKE_TIMEOUT.
4084         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4085         mLooper.dispatchAll();
4086         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID);
4087         mLooper.dispatchAll();
4088 
4089         assertEquals("DisconnectedState", getCurrentState().getName());
4090         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
4091                 sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION);
4092 
4093     }
4094 
4095     /**
4096      * Verify that WifiInfo is correctly populated after connection.
4097      */
4098     @Test
verifyWifiInfoGetNetworkSpecifierPackageName()4099     public void verifyWifiInfoGetNetworkSpecifierPackageName() throws Exception {
4100         mConnectedNetwork.fromWifiNetworkSpecifier = true;
4101         mConnectedNetwork.ephemeral = true;
4102         mConnectedNetwork.trusted = true;
4103         mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
4104         connect();
4105 
4106         assertTrue(mCmi.getWifiInfo().isEphemeral());
4107         assertTrue(mCmi.getWifiInfo().isTrusted());
4108         assertEquals(OP_PACKAGE_NAME,
4109                 mCmi.getWifiInfo().getRequestingPackageName());
4110     }
4111 
4112     /**
4113      * Verify that WifiInfo is correctly populated after connection.
4114      */
4115     @Test
verifyWifiInfoGetNetworkSuggestionPackageName()4116     public void verifyWifiInfoGetNetworkSuggestionPackageName() throws Exception {
4117         mConnectedNetwork.fromWifiNetworkSuggestion = true;
4118         mConnectedNetwork.ephemeral = true;
4119         mConnectedNetwork.trusted = true;
4120         mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
4121         connect();
4122 
4123         assertTrue(mCmi.getWifiInfo().isEphemeral());
4124         assertTrue(mCmi.getWifiInfo().isTrusted());
4125         assertEquals(OP_PACKAGE_NAME,
4126                 mCmi.getWifiInfo().getRequestingPackageName());
4127     }
4128 
4129     /**
4130      * Verify that a WifiIsUnusableEvent is logged and the current list of usability stats entries
4131      * are labeled and saved when receiving an IP reachability lost message.
4132      * @throws Exception
4133      */
4134     @Test
verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics()4135     public void verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics() throws Exception {
4136         connect();
4137 
4138         mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST);
4139         mLooper.dispatchAll();
4140         verify(mWifiMetrics).logWifiIsUnusableEvent(
4141                 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
4142         verify(mWifiMetrics).addToWifiUsabilityStatsList(WifiUsabilityStats.LABEL_BAD,
4143                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
4144     }
4145 
4146     /**
4147      * Tests that when {@link ClientModeImpl} receives a SUP_REQUEST_IDENTITY message, it responds
4148      * to the supplicant with the SIM identity.
4149      */
4150     @Test
testSupRequestIdentity_setsIdentityResponse()4151     public void testSupRequestIdentity_setsIdentityResponse() throws Exception {
4152         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
4153                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
4154         mConnectedNetwork.SSID = DEFAULT_TEST_SSID;
4155 
4156         when(mDataTelephonyManager.getSubscriberId()).thenReturn("3214561234567890");
4157         when(mDataTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY);
4158         when(mDataTelephonyManager.getSimOperator()).thenReturn("321456");
4159         when(mDataTelephonyManager.getCarrierInfoForImsiEncryption(anyInt())).thenReturn(null);
4160         MockitoSession mockSession = ExtendedMockito.mockitoSession()
4161                 .mockStatic(SubscriptionManager.class)
4162                 .startMocking();
4163         when(SubscriptionManager.getDefaultDataSubscriptionId()).thenReturn(DATA_SUBID);
4164         when(SubscriptionManager.isValidSubscriptionId(anyInt())).thenReturn(true);
4165 
4166         triggerConnect();
4167 
4168         mCmi.sendMessage(WifiMonitor.SUP_REQUEST_IDENTITY,
4169                 0, FRAMEWORK_NETWORK_ID, DEFAULT_TEST_SSID);
4170         mLooper.dispatchAll();
4171 
4172         verify(mWifiNative).simIdentityResponse(WIFI_IFACE_NAME,
4173                 "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", "");
4174         mockSession.finishMocking();
4175     }
4176 
4177     /**
4178      * Verifies that WifiLastResortWatchdog is notified of DHCP failures when recevied
4179      * NETWORK_DISCONNECTION_EVENT while in ObtainingIpState.
4180      */
4181     @Test
testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr()4182     public void testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr()
4183             throws Exception {
4184         initializeAndAddNetworkAndVerifySuccess();
4185 
4186         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
4187 
4188         IActionListener connectActionListener = mock(IActionListener.class);
4189         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
4190         mLooper.dispatchAll();
4191         verify(connectActionListener).onSuccess();
4192 
4193         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
4194 
4195         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
4196         mLooper.dispatchAll();
4197 
4198         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
4199                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
4200         mLooper.dispatchAll();
4201 
4202         assertEquals("ObtainingIpState", getCurrentState().getName());
4203 
4204         // Verifies that WifiLastResortWatchdog be notified.
4205         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
4206         mLooper.dispatchAll();
4207 
4208         assertEquals("DisconnectedState", getCurrentState().getName());
4209         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
4210                 sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP);
4211     }
4212 
4213     /**
4214      * Verifies that we trigger a disconnect when the {@link WifiConfigManager}.
4215      * OnNetworkUpdateListener#onNetworkRemoved(WifiConfiguration)} is invoked.
4216      */
4217     @Test
testOnNetworkRemoved()4218     public void testOnNetworkRemoved() throws Exception {
4219         connect();
4220 
4221         WifiConfiguration removedNetwork = new WifiConfiguration();
4222         removedNetwork.networkId = FRAMEWORK_NETWORK_ID;
4223         mConfigUpdateListenerCaptor.getValue().onNetworkRemoved(removedNetwork);
4224         mLooper.dispatchAll();
4225 
4226         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
4227         assertEquals("DisconnectingState", getCurrentState().getName());
4228     }
4229 
4230     /**
4231      * Verifies that we trigger a disconnect when the {@link WifiConfigManager
4232      * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked.
4233      */
4234     @Test
testOnNetworkPermanentlyDisabled()4235     public void testOnNetworkPermanentlyDisabled() throws Exception {
4236         connect();
4237 
4238         WifiConfiguration disabledNetwork = new WifiConfiguration();
4239         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
4240         mConfigUpdateListenerCaptor.getValue().onNetworkPermanentlyDisabled(disabledNetwork,
4241                 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
4242         mLooper.dispatchAll();
4243 
4244         assertEquals("DisconnectingState", getCurrentState().getName());
4245     }
4246 
4247     /**
4248      * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager
4249      * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked.
4250      */
4251     @Test
testOnNetworkPermanentlyDisabledWithNoInternet()4252     public void testOnNetworkPermanentlyDisabledWithNoInternet() throws Exception {
4253         connect();
4254 
4255         WifiConfiguration disabledNetwork = new WifiConfiguration();
4256         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
4257         mConfigUpdateListenerCaptor.getValue().onNetworkPermanentlyDisabled(disabledNetwork,
4258                 WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT);
4259         mLooper.dispatchAll();
4260 
4261         assertEquals("ConnectedState", getCurrentState().getName());
4262     }
4263 
4264     /**
4265      * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager
4266      * .OnNetworkUpdateListener#onNetworkTemporarilyDisabled(WifiConfiguration, int)} is invoked.
4267      */
4268     @Test
testOnNetworkTemporarilyDisabledWithNoInternet()4269     public void testOnNetworkTemporarilyDisabledWithNoInternet() throws Exception {
4270         connect();
4271 
4272         WifiConfiguration disabledNetwork = new WifiConfiguration();
4273         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
4274         mConfigUpdateListenerCaptor.getValue().onNetworkTemporarilyDisabled(disabledNetwork,
4275                 WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY);
4276         mLooper.dispatchAll();
4277 
4278         assertEquals("ConnectedState", getCurrentState().getName());
4279     }
4280 
4281     /**
4282      * Verify that MboOce/WifiDataStall enable/disable methods are called in ClientMode.
4283      */
4284     @Test
verifyMboOceWifiDataStallSetupInClientMode()4285     public void verifyMboOceWifiDataStallSetupInClientMode() throws Exception {
4286         startSupplicantAndDispatchMessages();
4287         verify(mMboOceController).enable();
4288         verify(mWifiDataStall).enablePhoneStateListener();
4289         mCmi.setOperationalMode(ClientModeImpl.DISABLED_MODE, null);
4290         mLooper.dispatchAll();
4291         verify(mMboOceController).disable();
4292         verify(mWifiDataStall).disablePhoneStateListener();
4293     }
4294 
4295     /**
4296      * Verify that Bluetooth active is set correctly with BT state/connection state changes
4297      */
4298     @Test
verifyBluetoothStateAndConnectionStateChanges()4299     public void verifyBluetoothStateAndConnectionStateChanges() throws Exception {
4300         startSupplicantAndDispatchMessages();
4301         mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_ON);
4302         mLooper.dispatchAll();
4303         verify(mWifiConnectivityManager, times(1)).setBluetoothConnected(false);
4304 
4305         mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTED);
4306         mLooper.dispatchAll();
4307         verify(mWifiConnectivityManager, times(1)).setBluetoothConnected(true);
4308 
4309         mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_OFF);
4310         mLooper.dispatchAll();
4311         verify(mWifiConnectivityManager, times(2)).setBluetoothConnected(false);
4312 
4313         mCmi.sendBluetoothAdapterStateChange(BluetoothAdapter.STATE_ON);
4314         mLooper.dispatchAll();
4315         verify(mWifiConnectivityManager, times(3)).setBluetoothConnected(false);
4316 
4317         mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTING);
4318         mLooper.dispatchAll();
4319         verify(mWifiConnectivityManager, times(2)).setBluetoothConnected(true);
4320 
4321         mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_DISCONNECTED);
4322         mLooper.dispatchAll();
4323         verify(mWifiConnectivityManager, times(4)).setBluetoothConnected(false);
4324 
4325         mCmi.sendBluetoothAdapterConnectionStateChange(BluetoothAdapter.STATE_CONNECTED);
4326         mLooper.dispatchAll();
4327         verify(mWifiConnectivityManager, times(3)).setBluetoothConnected(true);
4328     }
4329 
4330     /**
4331      * Test that handleBssTransitionRequest() blacklist the BSS upon
4332      * receiving BTM request frame that contains MBO-OCE IE with an
4333      * association retry delay attribute.
4334      */
4335     @Test
testBtmFrameWithMboAssocretryDelayBlackListTheBssid()4336     public void testBtmFrameWithMboAssocretryDelayBlackListTheBssid() throws Exception {
4337         // Connect to network with |sBSSID|, |sFreq|.
4338         connect();
4339 
4340         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
4341 
4342         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED;
4343         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
4344                 | MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED;
4345         btmFrmData.mBlackListDurationMs = 60000;
4346 
4347         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
4348         mLooper.dispatchAll();
4349 
4350         verify(mWifiMetrics, times(1)).incrementSteeringRequestCountIncludingMboAssocRetryDelay();
4351         verify(mBssidBlocklistMonitor).blockBssidForDurationMs(sBSSID, sSSID,
4352                 btmFrmData.mBlackListDurationMs);
4353     }
4354 
4355     /**
4356      * Test that handleBssTransitionRequest() trigger force scan for
4357      * network selection when status code is REJECT.
4358      */
4359     @Test
testBTMRequestRejectTriggerNetworkSelction()4360     public void testBTMRequestRejectTriggerNetworkSelction() throws Exception {
4361         // Connect to network with |sBSSID|, |sFreq|.
4362         connect();
4363 
4364         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
4365 
4366         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED;
4367         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
4368                 | MboOceConstants.BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED
4369                 | MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED;
4370         btmFrmData.mBlackListDurationMs = 60000;
4371 
4372         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
4373         mLooper.dispatchAll();
4374 
4375         verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(sBSSID, sSSID,
4376                 btmFrmData.mBlackListDurationMs);
4377         verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
4378         verify(mWifiMetrics, times(1)).incrementMboCellularSwitchRequestCount();
4379         verify(mWifiMetrics, times(1))
4380                 .incrementForceScanCountDueToSteeringRequest();
4381 
4382     }
4383 
4384     /**
4385      * Test that handleBssTransitionRequest() does not trigger force
4386      * scan when status code is accept.
4387      */
4388     @Test
testBTMRequestAcceptDoNotTriggerNetworkSelction()4389     public void testBTMRequestAcceptDoNotTriggerNetworkSelction() throws Exception {
4390         // Connect to network with |sBSSID|, |sFreq|.
4391         connect();
4392 
4393         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
4394 
4395         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT;
4396         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT;
4397 
4398         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
4399         mLooper.dispatchAll();
4400 
4401         verify(mWifiConnectivityManager, never())
4402                 .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
4403     }
4404 
4405     /**
4406      * Test that the interval for poll RSSI is read from config overlay correctly.
4407      */
4408     @Test
testPollRssiIntervalIsSetCorrectly()4409     public void testPollRssiIntervalIsSetCorrectly() throws Exception {
4410         assertEquals(3000, mCmi.getPollRssiIntervalMsecs());
4411         mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 6000);
4412         assertEquals(6000, mCmi.getPollRssiIntervalMsecs());
4413         mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 7000);
4414         assertEquals(6000, mCmi.getPollRssiIntervalMsecs());
4415     }
4416 
4417     /**
4418      * Verifies that the logic does not modify PSK key management when WPA3 auto upgrade feature is
4419      * disabled.
4420      *
4421      * @throws Exception
4422      */
4423     @Test
testNoWpa3UpgradeWhenOverlaysAreOff()4424     public void testNoWpa3UpgradeWhenOverlaysAreOff() throws Exception {
4425         initializeAndAddNetworkAndVerifySuccess();
4426         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4427         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4428 
4429         WifiConfiguration config = mock(WifiConfiguration.class);
4430         BitSet allowedKeyManagement = mock(BitSet.class);
4431         config.allowedKeyManagement = allowedKeyManagement;
4432         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn(
4433                 true);
4434         when(config.getNetworkSelectionStatus())
4435                 .thenReturn(new WifiConfiguration.NetworkSelectionStatus());
4436         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4437         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, false);
4438         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false);
4439 
4440         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4441         mLooper.dispatchAll();
4442 
4443         verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE));
4444     }
4445 
4446     /**
4447      * Verifies that the logic always enables SAE key management when WPA3 auto upgrade offload
4448      * feature is enabled.
4449      *
4450      * @throws Exception
4451      */
4452     @Test
testWpa3UpgradeOffload()4453     public void testWpa3UpgradeOffload() throws Exception {
4454         initializeAndAddNetworkAndVerifySuccess();
4455         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4456         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4457 
4458         WifiConfiguration config = mock(WifiConfiguration.class);
4459         BitSet allowedKeyManagement = mock(BitSet.class);
4460         BitSet allowedAuthAlgorithms = mock(BitSet.class);
4461         config.allowedKeyManagement = allowedKeyManagement;
4462         config.allowedAuthAlgorithms = allowedAuthAlgorithms;
4463         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK))).thenReturn(
4464                 true);
4465         when(config.getNetworkSelectionStatus())
4466                 .thenReturn(new WifiConfiguration.NetworkSelectionStatus());
4467         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4468         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true);
4469         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, true);
4470 
4471         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4472         mLooper.dispatchAll();
4473 
4474         verify(allowedKeyManagement).set(eq(WifiConfiguration.KeyMgmt.SAE));
4475         verify(allowedAuthAlgorithms).clear();
4476     }
4477 
4478     /**
4479      * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is
4480      * enabled but no SAE candidate is available.
4481      *
4482      * @throws Exception
4483      */
4484     @Test
testNoWpa3UpgradeWithPskCandidate()4485     public void testNoWpa3UpgradeWithPskCandidate() throws Exception {
4486         initializeAndAddNetworkAndVerifySuccess();
4487         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4488         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4489 
4490         WifiConfiguration config = mock(WifiConfiguration.class);
4491         BitSet allowedKeyManagement = mock(BitSet.class);
4492         config.allowedKeyManagement = allowedKeyManagement;
4493         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK)))
4494                 .thenReturn(true);
4495         WifiConfiguration.NetworkSelectionStatus networkSelectionStatus =
4496                 mock(WifiConfiguration.NetworkSelectionStatus.class);
4497         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus);
4498         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4499         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true);
4500         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false);
4501 
4502         String ssid = "WPA2-Network";
4503         String caps = "[WPA2-FT/PSK+PSK][ESS][WPS]";
4504         ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
4505                 "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,
4506                 0, true);
4507         scanResult.informationElements = new ScanResult.InformationElement[]{
4508                 createIE(ScanResult.InformationElement.EID_SSID,
4509                         ssid.getBytes(StandardCharsets.UTF_8))
4510         };
4511         when(networkSelectionStatus.getCandidate()).thenReturn(scanResult);
4512 
4513         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4514         mLooper.dispatchAll();
4515 
4516         verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE));
4517     }
4518 
4519     /**
4520      * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is
4521      * enabled and an SAE candidate is available.
4522      *
4523      * @throws Exception
4524      */
4525     @Test
testWpa3UpgradeWithSaeCandidate()4526     public void testWpa3UpgradeWithSaeCandidate() throws Exception {
4527         initializeAndAddNetworkAndVerifySuccess();
4528         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4529         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4530 
4531         WifiConfiguration config = mock(WifiConfiguration.class);
4532         BitSet allowedKeyManagement = mock(BitSet.class);
4533         BitSet allowedAuthAlgorithms = mock(BitSet.class);
4534         BitSet allowedProtocols = mock(BitSet.class);
4535         BitSet allowedPairwiseCiphers = mock(BitSet.class);
4536         BitSet allowedGroupCiphers = mock(BitSet.class);
4537         config.allowedKeyManagement = allowedKeyManagement;
4538         config.allowedAuthAlgorithms = allowedAuthAlgorithms;
4539         config.allowedProtocols = allowedProtocols;
4540         config.allowedPairwiseCiphers = allowedPairwiseCiphers;
4541         config.allowedGroupCiphers = allowedGroupCiphers;
4542         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK)))
4543                 .thenReturn(true);
4544         WifiConfiguration.NetworkSelectionStatus networkSelectionStatus =
4545                 mock(WifiConfiguration.NetworkSelectionStatus.class);
4546         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus);
4547         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
4548         when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null);
4549         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true);
4550         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false);
4551 
4552         final String ssid = "WPA3-Network";
4553         String caps = "[WPA2-FT/SAE+SAE][ESS][WPS]";
4554         ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
4555                 "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,
4556                 0, true);
4557         scanResult.informationElements = new ScanResult.InformationElement[]{
4558                 createIE(ScanResult.InformationElement.EID_SSID,
4559                         ssid.getBytes(StandardCharsets.UTF_8))
4560         };
4561         when(networkSelectionStatus.getCandidate()).thenReturn(scanResult);
4562 
4563         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4564         mLooper.dispatchAll();
4565 
4566         verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE));
4567     }
4568 
4569     /**
4570      * Verifies that the logic does not enable SAE key management when WPA3 auto upgrade feature is
4571      * enabled and an SAE candidate is available, while another WPA2 AP is in range.
4572      *
4573      * @throws Exception
4574      */
4575     @Test
testWpa3UpgradeWithSaeCandidateAndPskApInRange()4576     public void testWpa3UpgradeWithSaeCandidateAndPskApInRange() throws Exception {
4577         initializeAndAddNetworkAndVerifySuccess();
4578         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4579         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4580 
4581         WifiConfiguration config = mock(WifiConfiguration.class);
4582         BitSet allowedKeyManagement = mock(BitSet.class);
4583         BitSet allowedAuthAlgorithms = mock(BitSet.class);
4584         BitSet allowedProtocols = mock(BitSet.class);
4585         BitSet allowedPairwiseCiphers = mock(BitSet.class);
4586         BitSet allowedGroupCiphers = mock(BitSet.class);
4587         config.allowedKeyManagement = allowedKeyManagement;
4588         config.allowedAuthAlgorithms = allowedAuthAlgorithms;
4589         config.allowedProtocols = allowedProtocols;
4590         config.allowedPairwiseCiphers = allowedPairwiseCiphers;
4591         config.allowedGroupCiphers = allowedGroupCiphers;
4592         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK)))
4593                 .thenReturn(true);
4594         WifiConfiguration.NetworkSelectionStatus networkSelectionStatus =
4595                 mock(WifiConfiguration.NetworkSelectionStatus.class);
4596         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus);
4597         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
4598         when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt())).thenReturn(null);
4599         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true);
4600         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false);
4601 
4602         final String saeBssid = "ab:cd:01:ef:45:89";
4603         final String pskBssid = "ab:cd:01:ef:45:9a";
4604 
4605         final String ssidSae = "Mixed-Network";
4606         config.SSID = ScanResultUtil.createQuotedSSID(ssidSae);
4607         config.networkId = 1;
4608 
4609         String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]";
4610         ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae,
4611                 saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0,
4612                 0, true);
4613         ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID,
4614                 ssidSae.getBytes(StandardCharsets.UTF_8));
4615         scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae};
4616         when(networkSelectionStatus.getCandidate()).thenReturn(scanResultSae);
4617         ScanResult.InformationElement[] ieArr = new ScanResult.InformationElement[1];
4618         ieArr[0] = ieSae;
4619 
4620         final String ssidPsk = "Mixed-Network";
4621         String capsPsk = "[WPA2-FT/PSK+PSK][ESS][WPS]";
4622         ScanResult scanResultPsk = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidPsk), ssidPsk,
4623                 pskBssid, 1245, 0, capsPsk, -48, 2462, 1025, 22, 33, 20, 0,
4624                 0, true);
4625         ScanResult.InformationElement iePsk = createIE(ScanResult.InformationElement.EID_SSID,
4626                 ssidPsk.getBytes(StandardCharsets.UTF_8));
4627         scanResultPsk.informationElements = new ScanResult.InformationElement[]{iePsk};
4628         ScanResult.InformationElement[] ieArrPsk = new ScanResult.InformationElement[1];
4629         ieArrPsk[0] = iePsk;
4630         List<ScanResult> scanResults = new ArrayList<>();
4631         scanResults.add(scanResultPsk);
4632         scanResults.add(scanResultSae);
4633 
4634         when(mScanRequestProxy.getScanResults()).thenReturn(scanResults);
4635 
4636         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4637         mLooper.dispatchAll();
4638 
4639         verify(config, never()).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE));
4640     }
4641 
4642     /**
4643      * Verifies that the logic enables SAE key management when WPA3 auto upgrade feature is
4644      * enabled and no candidate is available (i.e. user selected a WPA2 saved network and the
4645      * network is actually WPA3.
4646      *
4647      * @throws Exception
4648      */
4649     @Test
testWpa3UpgradeWithNoCandidate()4650     public void testWpa3UpgradeWithNoCandidate() throws Exception {
4651         initializeAndAddNetworkAndVerifySuccess();
4652         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4653         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4654 
4655         WifiConfiguration config = mock(WifiConfiguration.class);
4656         BitSet allowedKeyManagement = mock(BitSet.class);
4657         BitSet allowedAuthAlgorithms = mock(BitSet.class);
4658         BitSet allowedProtocols = mock(BitSet.class);
4659         BitSet allowedPairwiseCiphers = mock(BitSet.class);
4660         BitSet allowedGroupCiphers = mock(BitSet.class);
4661         config.allowedKeyManagement = allowedKeyManagement;
4662         config.allowedAuthAlgorithms = allowedAuthAlgorithms;
4663         config.allowedProtocols = allowedProtocols;
4664         config.allowedPairwiseCiphers = allowedPairwiseCiphers;
4665         config.allowedGroupCiphers = allowedGroupCiphers;
4666         when(config.allowedKeyManagement.get(eq(WifiConfiguration.KeyMgmt.WPA_PSK)))
4667                 .thenReturn(true);
4668         WifiConfiguration.NetworkSelectionStatus networkSelectionStatus =
4669                 mock(WifiConfiguration.NetworkSelectionStatus.class);
4670         when(config.getNetworkSelectionStatus()).thenReturn(networkSelectionStatus);
4671         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
4672 
4673         mResources.setBoolean(R.bool.config_wifiSaeUpgradeEnabled, true);
4674         mResources.setBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled, false);
4675 
4676         final String saeBssid = "ab:cd:01:ef:45:89";
4677         final String ssidSae = "WPA3-Network";
4678         config.SSID = ScanResultUtil.createQuotedSSID(ssidSae);
4679         config.networkId = 1;
4680 
4681         String capsSae = "[WPA2-FT/SAE+SAE][ESS][WPS]";
4682         ScanResult scanResultSae = new ScanResult(WifiSsid.createFromAsciiEncoded(ssidSae), ssidSae,
4683                 saeBssid, 1245, 0, capsSae, -78, 2412, 1025, 22, 33, 20, 0,
4684                 0, true);
4685         ScanResult.InformationElement ieSae = createIE(ScanResult.InformationElement.EID_SSID,
4686                 ssidSae.getBytes(StandardCharsets.UTF_8));
4687         scanResultSae.informationElements = new ScanResult.InformationElement[]{ieSae};
4688         when(networkSelectionStatus.getCandidate()).thenReturn(null);
4689         List<ScanResult> scanResults = new ArrayList<>();
4690         scanResults.add(scanResultSae);
4691 
4692         when(mScanRequestProxy.getScanResults()).thenReturn(scanResults);
4693 
4694         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4695         mLooper.dispatchAll();
4696 
4697         verify(config).setSecurityParams(eq(WifiConfiguration.SECURITY_TYPE_SAE));
4698     }
4699 
createIE(int id, byte[] bytes)4700     private static ScanResult.InformationElement createIE(int id, byte[] bytes) {
4701         ScanResult.InformationElement ie = new ScanResult.InformationElement();
4702         ie.id = id;
4703         ie.bytes = bytes;
4704         return ie;
4705     }
4706 
4707     /*
4708      * Verify isWifiBandSupported for 5GHz with an overlay override config
4709      */
4710     @Test
testIsWifiBandSupported5gWithOverride()4711     public void testIsWifiBandSupported5gWithOverride() throws Exception {
4712         mResources.setBoolean(R.bool.config_wifi5ghzSupport, true);
4713         assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ));
4714         verify(mWifiNative, never()).getChannelsForBand(anyInt());
4715     }
4716 
4717     /**
4718      * Verify isWifiBandSupported for 6GHz with an overlay override config
4719      */
4720     @Test
testIsWifiBandSupported6gWithOverride()4721     public void testIsWifiBandSupported6gWithOverride() throws Exception {
4722         mResources.setBoolean(R.bool.config_wifi6ghzSupport, true);
4723         assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ));
4724         verify(mWifiNative, never()).getChannelsForBand(anyInt());
4725     }
4726 
4727     /**
4728      * Verify isWifiBandSupported for 5GHz with no overlay override config no channels
4729      */
4730     @Test
testIsWifiBandSupported5gNoOverrideNoChannels()4731     public void testIsWifiBandSupported5gNoOverrideNoChannels() throws Exception {
4732         final int[] emptyArray = {};
4733         mResources.setBoolean(R.bool.config_wifi5ghzSupport, false);
4734         when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray);
4735         assertFalse(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ));
4736         verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
4737     }
4738 
4739     /**
4740      * Verify isWifiBandSupported for 5GHz with no overlay override config with channels
4741      */
4742     @Test
testIsWifiBandSupported5gNoOverrideWithChannels()4743     public void testIsWifiBandSupported5gNoOverrideWithChannels() throws Exception {
4744         final int[] channelArray = {5170};
4745         mResources.setBoolean(R.bool.config_wifi5ghzSupport, false);
4746         when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray);
4747         assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_5_GHZ));
4748         verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
4749     }
4750 
4751     /**
4752      * Verify isWifiBandSupported for 6GHz with no overlay override config no channels
4753      */
4754     @Test
testIsWifiBandSupported6gNoOverrideNoChannels()4755     public void testIsWifiBandSupported6gNoOverrideNoChannels() throws Exception {
4756         final int[] emptyArray = {};
4757         mResources.setBoolean(R.bool.config_wifi6ghzSupport, false);
4758         when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(emptyArray);
4759         assertFalse(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ));
4760         verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ);
4761     }
4762 
4763     /**
4764      * Verify isWifiBandSupported for 6GHz with no overlay override config with channels
4765      */
4766     @Test
testIsWifiBandSupported6gNoOverrideWithChannels()4767     public void testIsWifiBandSupported6gNoOverrideWithChannels() throws Exception {
4768         final int[] channelArray = {6420};
4769         mResources.setBoolean(R.bool.config_wifi6ghzSupport, false);
4770         when(mWifiNative.getChannelsForBand(anyInt())).thenReturn(channelArray);
4771         assertTrue(mCmi.isWifiBandSupported(WifiScanner.WIFI_BAND_6_GHZ));
4772         verify(mWifiNative).getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ);
4773     }
4774 
4775     /**
4776      * Helper function for setting up fils test.
4777      *
4778      * @param isDriverSupportFils true if driver support fils.
4779      * @return wifi configuration.
4780      */
setupFilsTest(boolean isDriverSupportFils)4781     private WifiConfiguration setupFilsTest(boolean isDriverSupportFils) {
4782         assertEquals(ClientModeImpl.CONNECT_MODE, mCmi.getOperationalModeForTest());
4783         assertEquals(WifiManager.WIFI_STATE_ENABLED, mCmi.syncGetWifiState());
4784 
4785         WifiConfiguration config = new WifiConfiguration();
4786         config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
4787         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
4788         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
4789         config.SSID = ScanResultUtil.createQuotedSSID(sFilsSsid);
4790         config.networkId = 1;
4791         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
4792         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
4793 
4794         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
4795         if (isDriverSupportFils) {
4796             when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4797                     WifiManager.WIFI_FEATURE_FILS_SHA256 | WifiManager.WIFI_FEATURE_FILS_SHA384);
4798         } else {
4799             when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn((long) 0);
4800         }
4801 
4802         return config;
4803     }
4804 
4805     /**
4806      * Helper function for setting up a scan result with FILS supported AP.
4807      *
4808      */
setupFilsEnabledApInScanResult()4809     private void setupFilsEnabledApInScanResult() {
4810         String caps = "[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP]"
4811                 + "[RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP][ESS]";
4812         ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(sFilsSsid),
4813                 sFilsSsid, sBSSID, 1245, 0, caps, -78, 2412, 1025, 22, 33, 20, 0, 0, true);
4814         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
4815                 sFilsSsid.getBytes(StandardCharsets.UTF_8));
4816         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
4817         List<ScanResult> scanResults = new ArrayList<>();
4818         scanResults.add(scanResult);
4819 
4820         when(mScanRequestProxy.getScanResults()).thenReturn(scanResults);
4821     }
4822 
4823 
4824     /**
4825      * Helper function to send CMD_START_FILS_CONNECTION along with HLP IEs.
4826      *
4827      */
prepareFilsHlpPktAndSendStartConnect()4828     private void prepareFilsHlpPktAndSendStartConnect() {
4829         Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
4830         l2Packet.dstMacAddress = TEST_GLOBAL_MAC_ADDRESS;
4831         l2Packet.payload = new byte[] {0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13,
4832                 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x55, 0x66};
4833         mCmi.sendMessage(ClientModeImpl.CMD_START_FILS_CONNECTION, 0, 0,
4834                 Collections.singletonList(l2Packet));
4835         mLooper.dispatchAll();
4836     }
4837 
4838     /**
4839      * Verifies that while connecting to AP, the logic looks into the scan result and
4840      * looks for AP matching the network type and ssid and update the wificonfig with FILS
4841      * AKM if supported.
4842      *
4843      * @throws Exception
4844      */
4845     @Test
testFilsAKMUpdateBeforeConnect()4846     public void testFilsAKMUpdateBeforeConnect() throws Exception {
4847         initializeAndAddNetworkAndVerifySuccess();
4848         WifiConfiguration config = setupFilsTest(true);
4849         setupFilsEnabledApInScanResult();
4850 
4851         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4852         mLooper.dispatchAll();
4853 
4854         assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
4855         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
4856     }
4857 
4858     /**
4859      * Verifies that while connecting to AP, framework updates the wifi config with
4860      * FILS AKM only if underlying driver support FILS feature.
4861      *
4862      * @throws Exception
4863      */
4864     @Test
testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils()4865     public void testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils() throws Exception {
4866         initializeAndAddNetworkAndVerifySuccess();
4867         WifiConfiguration config = setupFilsTest(false);
4868         setupFilsEnabledApInScanResult();
4869 
4870         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4871         mLooper.dispatchAll();
4872 
4873         assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
4874         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
4875     }
4876 
4877 
4878     /**
4879      * Verifies that the HLP (DHCP) packets are send to wpa_supplicant
4880      * prior to Fils connection.
4881      *
4882      * @throws Exception
4883      */
4884     @Test
testFilsHlpUpdateBeforeFilsConnection()4885     public void testFilsHlpUpdateBeforeFilsConnection() throws Exception {
4886         initializeAndAddNetworkAndVerifySuccess();
4887         WifiConfiguration config = setupFilsTest(true);
4888         setupFilsEnabledApInScanResult();
4889 
4890         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4891         mLooper.dispatchAll();
4892 
4893         prepareFilsHlpPktAndSendStartConnect();
4894 
4895         verify(mWifiNative).flushAllHlp(eq(WIFI_IFACE_NAME));
4896         verify(mWifiNative).addHlpReq(eq(WIFI_IFACE_NAME), any(), any());
4897         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
4898     }
4899 
4900     /**
4901      * Verifies that an association rejection in first FILS connect attempt doesn't block
4902      * the second connection attempt.
4903      *
4904      * @throws Exception
4905      */
4906     @Test
testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject()4907     public void testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject() throws Exception {
4908         initializeAndAddNetworkAndVerifySuccess();
4909         WifiConfiguration config = setupFilsTest(true);
4910         setupFilsEnabledApInScanResult();
4911 
4912         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4913         mLooper.dispatchAll();
4914 
4915         prepareFilsHlpPktAndSendStartConnect();
4916 
4917         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
4918 
4919         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 2, sBSSID);
4920         mLooper.dispatchAll();
4921 
4922         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4923         mLooper.dispatchAll();
4924         prepareFilsHlpPktAndSendStartConnect();
4925 
4926         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
4927     }
4928 
4929     /**
4930      * Verifies Fils connection.
4931      *
4932      * @throws Exception
4933      */
4934     @Test
testFilsConnection()4935     public void testFilsConnection() throws Exception {
4936         initializeAndAddNetworkAndVerifySuccess();
4937         WifiConfiguration config = setupFilsTest(true);
4938         setupFilsEnabledApInScanResult();
4939 
4940         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
4941         mLooper.dispatchAll();
4942 
4943         prepareFilsHlpPktAndSendStartConnect();
4944 
4945         verify(mWifiMetrics, times(1)).incrementConnectRequestWithFilsAkmCount();
4946 
4947         mCmi.sendMessage(WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
4948         mLooper.dispatchAll();
4949 
4950         verify(mWifiMetrics, times(1)).incrementL2ConnectionThroughFilsAuthCount();
4951 
4952         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
4953                 new StateChangeResult(0, WifiSsid.createFromAsciiEncoded(sFilsSsid),
4954                 sBSSID, SupplicantState.COMPLETED));
4955         mLooper.dispatchAll();
4956 
4957         assertEquals("ObtainingIpState", getCurrentState().getName());
4958 
4959         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
4960         dhcpResults.baseConfiguration = new StaticIpConfiguration();
4961         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
4962         dhcpResults.baseConfiguration.ipAddress =
4963                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
4964         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
4965         dhcpResults.leaseDuration = 3600;
4966 
4967         injectDhcpSuccess(dhcpResults);
4968         mLooper.dispatchAll();
4969 
4970         WifiInfo wifiInfo = mCmi.getWifiInfo();
4971         assertNotNull(wifiInfo);
4972         assertEquals(sBSSID, wifiInfo.getBSSID());
4973         assertTrue(WifiSsid.createFromAsciiEncoded(sFilsSsid).equals(wifiInfo.getWifiSsid()));
4974         assertEquals("ConnectedState", getCurrentState().getName());
4975     }
4976 
4977     /**
4978      * Tests the wifi info is updated correctly for connecting network.
4979      */
4980     @Test
testWifiInfoOnConnectingNextNetwork()4981     public void testWifiInfoOnConnectingNextNetwork() throws Exception {
4982 
4983         mConnectedNetwork.ephemeral = true;
4984         mConnectedNetwork.trusted = true;
4985         mConnectedNetwork.osu = true;
4986 
4987         triggerConnect();
4988         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
4989                 .thenReturn(mScanDetailCache);
4990 
4991         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
4992                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq));
4993         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
4994                 getGoogleGuestScanDetail(TEST_RSSI, sBSSID, sFreq).getScanResult());
4995 
4996         // before the fist success connection, there is no valid wifi info.
4997         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, mCmi.getWifiInfo().getNetworkId());
4998 
4999         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5000                 new StateChangeResult(FRAMEWORK_NETWORK_ID,
5001                     sWifiSsid, sBSSID, SupplicantState.ASSOCIATED));
5002         mLooper.dispatchAll();
5003 
5004         // retrieve correct wifi info on receiving the supplicant state change event.
5005         assertEquals(FRAMEWORK_NETWORK_ID, mCmi.getWifiInfo().getNetworkId());
5006         assertEquals(mConnectedNetwork.ephemeral, mCmi.getWifiInfo().isEphemeral());
5007         assertEquals(mConnectedNetwork.trusted, mCmi.getWifiInfo().isTrusted());
5008         assertEquals(mConnectedNetwork.osu, mCmi.getWifiInfo().isOsuAp());
5009     }
5010 
5011     /**
5012      * Verify that we disconnect when we mark a previous unmetered network metered.
5013      */
5014     @Test
verifyDisconnectOnMarkingNetworkMetered()5015     public void verifyDisconnectOnMarkingNetworkMetered() throws Exception {
5016         connect();
5017         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5018             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5019         });
5020 
5021         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5022         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
5023 
5024         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5025         mLooper.dispatchAll();
5026         assertEquals("DisconnectingState", getCurrentState().getName());
5027     }
5028 
5029     /**
5030      * Verify that we only update capabilites when we mark a previous unmetered network metered.
5031      */
5032     @Test
verifyUpdateCapabilitiesOnMarkingNetworkUnmetered()5033     public void verifyUpdateCapabilitiesOnMarkingNetworkUnmetered() throws Exception {
5034         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
5035         connect();
5036         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5037             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5038         });
5039         reset(mNetworkAgentHandler);
5040 
5041         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5042         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
5043 
5044         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5045         mLooper.dispatchAll();
5046         assertEquals("ConnectedState", getCurrentState().getName());
5047 
5048         expectNetworkAgentUpdateCapabilities((cap) -> {
5049             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5050         });
5051     }
5052 
5053 
5054     /**
5055      * Verify that we disconnect when we mark a previous unmetered network metered.
5056      */
5057     @Test
verifyDisconnectOnMarkingNetworkAutoMeteredWithMeteredHint()5058     public void verifyDisconnectOnMarkingNetworkAutoMeteredWithMeteredHint() throws Exception {
5059         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
5060         connect();
5061         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5062             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5063         });
5064         reset(mNetworkAgentHandler);
5065 
5066         // Mark network metered none.
5067         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5068         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
5069 
5070         // Set metered hint in WifiInfo (either via DHCP or ScanResult IE).
5071         WifiInfo wifiInfo = mCmi.getWifiInfo();
5072         wifiInfo.setMeteredHint(true);
5073 
5074         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5075         mLooper.dispatchAll();
5076         assertEquals("DisconnectingState", getCurrentState().getName());
5077     }
5078 
5079     /**
5080      * Verify that we only update capabilites when we mark a previous unmetered network metered.
5081      */
5082     @Test
verifyUpdateCapabilitiesOnMarkingNetworkAutoMeteredWithoutMeteredHint()5083     public void verifyUpdateCapabilitiesOnMarkingNetworkAutoMeteredWithoutMeteredHint()
5084             throws Exception {
5085         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
5086         connect();
5087         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5088             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5089         });
5090         reset(mNetworkAgentHandler);
5091 
5092         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5093         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
5094 
5095         // Reset metered hint in WifiInfo.
5096         WifiInfo wifiInfo = mCmi.getWifiInfo();
5097         wifiInfo.setMeteredHint(false);
5098 
5099         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5100         mLooper.dispatchAll();
5101         assertEquals("ConnectedState", getCurrentState().getName());
5102 
5103         expectNetworkAgentUpdateCapabilities((cap) -> {
5104             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5105         });
5106     }
5107 
5108     /**
5109      * Verify that we do nothing on no metered change.
5110      */
5111     @Test
verifyDoNothingMarkingNetworkAutoMeteredWithMeteredHint()5112     public void verifyDoNothingMarkingNetworkAutoMeteredWithMeteredHint() throws Exception {
5113         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
5114         connect();
5115         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5116             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5117         });
5118         reset(mNetworkAgentHandler);
5119 
5120         // Mark network metered none.
5121         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5122         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
5123 
5124         // Set metered hint in WifiInfo (either via DHCP or ScanResult IE).
5125         WifiInfo wifiInfo = mCmi.getWifiInfo();
5126         wifiInfo.setMeteredHint(true);
5127 
5128         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5129         mLooper.dispatchAll();
5130         assertEquals("ConnectedState", getCurrentState().getName());
5131 
5132         verifyNoMoreInteractions(mNetworkAgentHandler);
5133     }
5134 
5135     /**
5136      * Verify that we do nothing on no metered change.
5137      */
5138     @Test
verifyDoNothingMarkingNetworkAutoMeteredWithoutMeteredHint()5139     public void verifyDoNothingMarkingNetworkAutoMeteredWithoutMeteredHint() throws Exception {
5140         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
5141         connect();
5142         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
5143             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
5144         });
5145         reset(mNetworkAgentHandler);
5146 
5147         // Mark network metered none.
5148         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5149         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
5150 
5151         // Reset metered hint in WifiInfo.
5152         WifiInfo wifiInfo = mCmi.getWifiInfo();
5153         wifiInfo.setMeteredHint(false);
5154 
5155         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5156         mLooper.dispatchAll();
5157         assertEquals("ConnectedState", getCurrentState().getName());
5158 
5159         verifyNoMoreInteractions(mNetworkAgentHandler);
5160     }
5161 
5162     /*
5163      * Verify that network cached data is cleared correctly in
5164      * disconnected state.
5165      */
5166     @Test
testNetworkCachedDataIsClearedCorrectlyInDisconnectedState()5167     public void testNetworkCachedDataIsClearedCorrectlyInDisconnectedState() throws Exception {
5168         // Setup CONNECT_MODE & a WifiConfiguration
5169         initializeAndAddNetworkAndVerifySuccess();
5170         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
5171         mLooper.dispatchAll();
5172 
5173         // got UNSPECIFIED during this connection attempt
5174         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 1, sBSSID);
5175         mLooper.dispatchAll();
5176 
5177         assertEquals("DisconnectedState", getCurrentState().getName());
5178         verify(mWifiNative, never()).removeNetworkCachedData(anyInt());
5179 
5180         // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt
5181         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, sBSSID);
5182         mLooper.dispatchAll();
5183         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID);
5184         mLooper.dispatchAll();
5185 
5186         assertEquals("DisconnectedState", getCurrentState().getName());
5187         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
5188     }
5189 
5190     /*
5191      * Verify that network cached data is cleared correctly in
5192      * disconnected state.
5193      */
5194     @Test
testNetworkCachedDataIsClearedCorrectlyInObtainingIpState()5195     public void testNetworkCachedDataIsClearedCorrectlyInObtainingIpState() throws Exception {
5196         initializeAndAddNetworkAndVerifySuccess();
5197 
5198         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
5199 
5200         IActionListener connectActionListener = mock(IActionListener.class);
5201         mCmi.connect(null, 0, mock(Binder.class), connectActionListener, 0, Binder.getCallingUid());
5202         mLooper.dispatchAll();
5203         verify(connectActionListener).onSuccess();
5204 
5205         verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt(), any());
5206 
5207         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
5208         mLooper.dispatchAll();
5209 
5210         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5211                 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
5212         mLooper.dispatchAll();
5213 
5214         assertEquals("ObtainingIpState", getCurrentState().getName());
5215 
5216         // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt
5217         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID);
5218         mLooper.dispatchAll();
5219 
5220         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
5221     }
5222 
5223     /*
5224      * Verify that network cached data is NOT cleared in ConnectedState.
5225      */
5226     @Test
testNetworkCachedDataIsClearedIf4WayHandshakeFailure()5227     public void testNetworkCachedDataIsClearedIf4WayHandshakeFailure() throws Exception {
5228         when(mWifiScoreCard.detectAbnormalDisconnection())
5229                 .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL);
5230         InOrder inOrderWifiLockManager = inOrder(mWifiLockManager);
5231         connect();
5232         inOrderWifiLockManager.verify(mWifiLockManager).updateWifiClientConnected(true);
5233 
5234         // got 4WAY_HANDSHAKE_TIMEOUT
5235         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 15, sBSSID);
5236         mLooper.dispatchAll();
5237         verify(mWifiNative, never()).removeNetworkCachedData(anyInt());
5238     }
5239 
5240     /**
5241      * Verify that network cached data is cleared on updating a network.
5242      */
5243     @Test
testNetworkCachedDataIsClearedOnUpdatingNetwork()5244     public void testNetworkCachedDataIsClearedOnUpdatingNetwork() throws Exception {
5245         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
5246         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
5247 
5248         mConfigUpdateListenerCaptor.getValue().onNetworkUpdated(mConnectedNetwork, oldConfig);
5249         mLooper.dispatchAll();
5250         verify(mWifiNative).removeNetworkCachedData(eq(oldConfig.networkId));
5251     }
5252 
5253 
5254     @Test
testIpReachabilityLostAndRoamEventsRace()5255     public void testIpReachabilityLostAndRoamEventsRace() throws Exception {
5256         connect();
5257         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
5258         reset(mNetworkAgentHandler);
5259 
5260         // Trigger ip reachibility loss and ensure we trigger a disconnect & we're in
5261         // "DisconnectingState"
5262         mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_LOST);
5263         mLooper.dispatchAll();
5264         verify(mWifiNative).disconnect(any());
5265         assertEquals("DisconnectingState", getCurrentState().getName());
5266 
5267         // Now send a network connection (indicating a roam) event before we get the disconnect
5268         // event.
5269         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
5270         mLooper.dispatchAll();
5271         // ensure that we ignored the transient roam while we're disconnecting.
5272         assertEquals("DisconnectingState", getCurrentState().getName());
5273         verifyNoMoreInteractions(mNetworkAgentHandler);
5274 
5275         // Now send the disconnect event and ensure that we transition to "DisconnectedState".
5276         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
5277         mLooper.dispatchAll();
5278         assertEquals("DisconnectedState", getCurrentState().getName());
5279         expectUnregisterNetworkAgent();
5280 
5281         verifyNoMoreInteractions(mNetworkAgentHandler);
5282     }
5283 
5284     @Test
testSyncGetCurrentNetwork()5285     public void testSyncGetCurrentNetwork() throws Exception {
5286         // syncGetCurrentNetwork() returns null when disconnected
5287         mLooper.startAutoDispatch();
5288         assertNull(mCmi.syncGetCurrentNetwork(mCmiAsyncChannel));
5289         mLooper.stopAutoDispatch();
5290 
5291         connect();
5292 
5293         // syncGetCurrentNetwork() returns non-null Network when connected
5294         mLooper.startAutoDispatch();
5295         assertEquals(mNetwork, mCmi.syncGetCurrentNetwork(mCmiAsyncChannel));
5296         mLooper.stopAutoDispatch();
5297     }
5298 }
5299