• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.NetworkInfo.DetailedState.AUTHENTICATING;
20 import static android.net.NetworkInfo.DetailedState.CONNECTED;
21 import static android.net.NetworkInfo.DetailedState.CONNECTING;
22 import static android.net.NetworkInfo.DetailedState.DISCONNECTED;
23 import static android.net.NetworkInfo.DetailedState.OBTAINING_IPADDR;
24 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
25 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
26 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
27 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE;
28 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT;
29 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
30 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_UNWANTED_LOW_RSSI;
31 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED;
32 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE;
33 import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN;
34 import static android.net.wifi.WifiInfo.SECURITY_TYPE_OWE;
35 import static android.net.wifi.WifiInfo.SECURITY_TYPE_PSK;
36 import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_SUCCESS;
37 
38 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
39 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
40 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED;
41 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
42 import static com.android.server.wifi.ClientModeImpl.ARP_TABLE_PATH;
43 import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION;
44 import static com.android.server.wifi.ClientModeImpl.CMD_PRE_DHCP_ACTION_COMPLETE;
45 import static com.android.server.wifi.ClientModeImpl.CMD_UNWANTED_NETWORK;
46 import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE;
47 import static com.android.server.wifi.WifiBlocklistMonitor.REASON_APP_DISALLOW;
48 import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS;
49 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS;
50 import static com.android.server.wifi.TestUtil.createCapabilityBitset;
51 
52 import static org.junit.Assert.assertArrayEquals;
53 import static org.junit.Assert.assertEquals;
54 import static org.junit.Assert.assertFalse;
55 import static org.junit.Assert.assertNotEquals;
56 import static org.junit.Assert.assertNotNull;
57 import static org.junit.Assert.assertNull;
58 import static org.junit.Assert.assertTrue;
59 import static org.junit.Assert.fail;
60 import static org.junit.Assume.assumeFalse;
61 import static org.junit.Assume.assumeTrue;
62 import static org.mockito.Mockito.any;
63 import static org.mockito.Mockito.anyBoolean;
64 import static org.mockito.Mockito.anyByte;
65 import static org.mockito.Mockito.anyInt;
66 import static org.mockito.Mockito.anyLong;
67 import static org.mockito.Mockito.anyString;
68 import static org.mockito.Mockito.argThat;
69 import static org.mockito.Mockito.atLeast;
70 import static org.mockito.Mockito.atLeastOnce;
71 import static org.mockito.Mockito.clearInvocations;
72 import static org.mockito.Mockito.doAnswer;
73 import static org.mockito.Mockito.doReturn;
74 import static org.mockito.Mockito.eq;
75 import static org.mockito.Mockito.inOrder;
76 import static org.mockito.Mockito.mock;
77 import static org.mockito.Mockito.never;
78 import static org.mockito.Mockito.reset;
79 import static org.mockito.Mockito.spy;
80 import static org.mockito.Mockito.times;
81 import static org.mockito.Mockito.verify;
82 import static org.mockito.Mockito.verifyNoMoreInteractions;
83 import static org.mockito.Mockito.when;
84 import static org.mockito.Mockito.withSettings;
85 
86 import android.Manifest;
87 import android.annotation.NonNull;
88 import android.annotation.Nullable;
89 import android.app.ActivityManager;
90 import android.app.test.MockAnswerUtil.AnswerWithArguments;
91 import android.app.test.TestAlarmManager;
92 import android.content.BroadcastReceiver;
93 import android.content.Context;
94 import android.content.Intent;
95 import android.content.pm.PackageManager;
96 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
97 import android.hardware.wifi.supplicant.V1_4.ISupplicantStaIfaceCallback.AssociationRejectionData;
98 import android.hardware.wifi.supplicant.V1_4.ISupplicantStaIfaceCallback.MboAssocDisallowedReasonCode;
99 import android.net.CaptivePortalData;
100 import android.net.DhcpResultsParcelable;
101 import android.net.InetAddresses;
102 import android.net.IpConfiguration;
103 import android.net.IpPrefix;
104 import android.net.Layer2InformationParcelable;
105 import android.net.Layer2PacketParcelable;
106 import android.net.LinkAddress;
107 import android.net.LinkProperties;
108 import android.net.MacAddress;
109 import android.net.Network;
110 import android.net.NetworkAgent;
111 import android.net.NetworkAgentConfig;
112 import android.net.NetworkCapabilities;
113 import android.net.NetworkInfo;
114 import android.net.NetworkProvider;
115 import android.net.NetworkSpecifier;
116 import android.net.ProvisioningConfigurationParcelable;
117 import android.net.RouteInfo;
118 import android.net.StaticIpConfiguration;
119 import android.net.Uri;
120 import android.net.apf.ApfCapabilities;
121 import android.net.ip.IIpClient;
122 import android.net.ip.IpClientCallbacks;
123 import android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable;
124 import android.net.networkstack.aidl.ip.ReachabilityLossReason;
125 import android.net.vcn.VcnManager;
126 import android.net.vcn.VcnNetworkPolicyResult;
127 import android.net.wifi.BlockingOption;
128 import android.net.wifi.IActionListener;
129 import android.net.wifi.MloLink;
130 import android.net.wifi.ScanResult;
131 import android.net.wifi.SecurityParams;
132 import android.net.wifi.SupplicantState;
133 import android.net.wifi.WifiConfiguration;
134 import android.net.wifi.WifiConfiguration.KeyMgmt;
135 import android.net.wifi.WifiContext;
136 import android.net.wifi.WifiEnterpriseConfig;
137 import android.net.wifi.WifiInfo;
138 import android.net.wifi.WifiManager;
139 import android.net.wifi.WifiNetworkAgentSpecifier;
140 import android.net.wifi.WifiNetworkSpecifier;
141 import android.net.wifi.WifiScanner;
142 import android.net.wifi.WifiSsid;
143 import android.net.wifi.flags.Flags;
144 import android.net.wifi.hotspot2.IProvisioningCallback;
145 import android.net.wifi.hotspot2.OsuProvider;
146 import android.net.wifi.nl80211.DeviceWiphyCapabilities;
147 import android.net.wifi.p2p.WifiP2pManager;
148 import android.net.wifi.util.ScanResultUtil;
149 import android.os.BatteryStatsManager;
150 import android.os.Binder;
151 import android.os.Bundle;
152 import android.os.Handler;
153 import android.os.HandlerThread;
154 import android.os.Looper;
155 import android.os.Messenger;
156 import android.os.PowerManager;
157 import android.os.Process;
158 import android.os.UserHandle;
159 import android.os.test.TestLooper;
160 import android.provider.Settings;
161 import android.telephony.TelephonyManager;
162 import android.test.mock.MockContentProvider;
163 import android.test.mock.MockContentResolver;
164 import android.util.ArraySet;
165 import android.util.LocalLog;
166 import android.util.Log;
167 import android.util.Pair;
168 import android.util.Range;
169 
170 import androidx.test.filters.SmallTest;
171 
172 import com.android.dx.mockito.inline.extended.ExtendedMockito;
173 import com.android.internal.util.AsyncChannel;
174 import com.android.internal.util.IState;
175 import com.android.internal.util.StateMachine;
176 import com.android.modules.utils.build.SdkLevel;
177 import com.android.server.wifi.ClientMode.LinkProbeCallback;
178 import com.android.server.wifi.ClientModeManagerBroadcastQueue.QueuedBroadcast;
179 import com.android.server.wifi.WifiNative.ConnectionCapabilities;
180 import com.android.server.wifi.WifiScoreCard.PerBssid;
181 import com.android.server.wifi.WifiScoreCard.PerNetwork;
182 import com.android.server.wifi.b2b.WifiRoamingModeManager;
183 import com.android.server.wifi.hotspot2.NetworkDetail;
184 import com.android.server.wifi.hotspot2.PasspointManager;
185 import com.android.server.wifi.hotspot2.PasspointProvisioningTestUtil;
186 import com.android.server.wifi.hotspot2.WnmData;
187 import com.android.server.wifi.p2p.WifiP2pServiceImpl;
188 import com.android.server.wifi.proto.nano.WifiMetricsProto;
189 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
190 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
191 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
192 import com.android.server.wifi.util.ActionListenerWrapper;
193 import com.android.server.wifi.util.NativeUtil;
194 import com.android.server.wifi.util.RssiUtilTest;
195 import com.android.server.wifi.util.WifiPermissionsUtil;
196 import com.android.wifi.resources.R;
197 
198 import org.junit.After;
199 import org.junit.Before;
200 import org.junit.Test;
201 import org.mockito.ArgumentCaptor;
202 import org.mockito.ArgumentMatcher;
203 import org.mockito.Captor;
204 import org.mockito.InOrder;
205 import org.mockito.Mock;
206 import org.mockito.MockitoAnnotations;
207 import org.mockito.MockitoSession;
208 import org.mockito.quality.Strictness;
209 import org.mockito.verification.VerificationMode;
210 
211 import java.io.BufferedReader;
212 import java.io.ByteArrayOutputStream;
213 import java.io.FileDescriptor;
214 import java.io.PrintWriter;
215 import java.io.StringWriter;
216 import java.lang.reflect.Field;
217 import java.lang.reflect.InvocationTargetException;
218 import java.lang.reflect.Method;
219 import java.net.Inet4Address;
220 import java.net.InetAddress;
221 import java.net.URL;
222 import java.nio.charset.StandardCharsets;
223 import java.util.ArrayList;
224 import java.util.Arrays;
225 import java.util.BitSet;
226 import java.util.Collections;
227 import java.util.HashMap;
228 import java.util.List;
229 import java.util.Map;
230 import java.util.Random;
231 import java.util.Set;
232 import java.util.StringJoiner;
233 import java.util.concurrent.CountDownLatch;
234 import java.util.function.Consumer;
235 
236 /**
237  * Unit tests for {@link com.android.server.wifi.ClientModeImpl}.
238  */
239 @SmallTest
240 public class ClientModeImplTest extends WifiBaseTest {
241     public static final String TAG = "ClientModeImplTest";
242 
243     private static final int MANAGED_PROFILE_UID = 1100000;
244     private static final int OTHER_USER_UID = 1200000;
245     private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE = ClientModeImpl.NUM_LOG_RECS_VERBOSE;
246     private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE_LOW_RAM =
247             ClientModeImpl.NUM_LOG_RECS_VERBOSE_LOW_MEMORY;
248     private static final int FRAMEWORK_NETWORK_ID = 0;
249     private static final int PASSPOINT_NETWORK_ID = 1;
250     private static final int OTHER_NETWORK_ID = 47;
251     private static final int TEST_RSSI = -54;
252     private static final int TEST_NETWORK_ID = 54;
253     private static final int WPS_SUPPLICANT_NETWORK_ID = 5;
254     private static final int WPS_FRAMEWORK_NETWORK_ID = 10;
255     private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
256     private static final String OP_PACKAGE_NAME = "com.xxx";
257     private static final int TEST_UID = Process.SYSTEM_UID + 1000;
258     private static final MacAddress TEST_GLOBAL_MAC_ADDRESS =
259             MacAddress.fromString("10:22:34:56:78:92");
260     private static final MacAddress TEST_LOCAL_MAC_ADDRESS =
261             MacAddress.fromString("2a:53:43:c3:56:21");
262     private static final MacAddress TEST_LOCAL_MAC_ADDRESS_SECONDARY_DBS =
263             MacAddress.fromString("2a:53:43:c3:56:22");
264     private static final MacAddress TEST_DEFAULT_MAC_ADDRESS =
265             MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
266    // NetworkAgent creates threshold ranges with Integers
267     private static final int RSSI_THRESHOLD_MAX = -30;
268     private static final int RSSI_THRESHOLD_MIN = -76;
269     // Threshold breach callbacks are called with bytes
270     private static final byte RSSI_THRESHOLD_BREACH_MIN = -80;
271     private static final byte RSSI_THRESHOLD_BREACH_MAX = -20;
272 
273     private static final int DATA_SUBID = 1;
274     private static final int CARRIER_ID_1 = 100;
275 
276     private static final long TEST_BSSID = 0x112233445566L;
277     private static final int TEST_DELAY_IN_SECONDS = 300;
278     private static final String TEST_ATTRIBUTION_TAG = "TEST_ATTRIBUTION_TAG";
279 
280     private static final int DEFINED_ERROR_CODE = 32764;
281     private static final String TEST_TERMS_AND_CONDITIONS_URL =
282             "https://policies.google.com/terms?hl=en-US";
283     private static final String VENUE_URL =
284             "https://www.android.com/android-11/";
285     private static final long[] TEST_RCOI_ARRAY = {0xcafeL, 0xbabaL};
286     private static final long TEST_MATCHED_RCOI = TEST_RCOI_ARRAY[0];
287 
288     private static final String TEST_AP_MLD_MAC_ADDRESS_STR = "02:03:04:05:06:07";
289     private static final MacAddress TEST_AP_MLD_MAC_ADDRESS =
290             MacAddress.fromString(TEST_AP_MLD_MAC_ADDRESS_STR);
291 
292     private static final String TEST_MLO_LINK_ADDR_STR = "02:03:04:05:06:0A";
293     private static final MacAddress TEST_MLO_LINK_ADDR =
294             MacAddress.fromString(TEST_MLO_LINK_ADDR_STR);
295 
296     private static final String TEST_MLO_LINK_ADDR_1_STR = "02:03:04:05:06:0B";
297     private static final MacAddress TEST_MLO_LINK_ADDR_1 =
298             MacAddress.fromString(TEST_MLO_LINK_ADDR_1_STR);
299 
300     private static final int TEST_MLO_LINK_ID = 1;
301     private static final int TEST_MLO_LINK_ID_1 = 2;
302 
303     private static final int TEST_MLO_LINK_FREQ = 5160;
304     private static final int TEST_MLO_LINK_FREQ_1 = 2437;
305 
306     private static final String TEST_TDLS_PEER_ADDR_STR = "02:55:11:02:36:4C";
307 
308     private long mBinderToken;
309     private MockitoSession mSession;
310     private TestNetworkParams mTestNetworkParams = new TestNetworkParams();
311 
312     // Attribution tag to be used in the mocked connect sequence
313     private String mAttributionTagForConnect = TEST_ATTRIBUTION_TAG;
314 
315     /**
316      * Helper class for setting the default parameters of the WifiConfiguration that gets used
317      * in connect().
318      */
319     class TestNetworkParams {
320         public boolean hasEverConnected = false;
321     }
322 
mockWithInterfaces(Class<T> class1, Class<?>... interfaces)323     private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
324         return mock(class1, withSettings().extraInterfaces(interfaces));
325     }
326 
enableDebugLogs()327     private void enableDebugLogs() {
328         mCmi.enableVerboseLogging(true);
329     }
330 
getFrameworkFacade()331     private FrameworkFacade getFrameworkFacade() throws Exception {
332         FrameworkFacade facade = mock(FrameworkFacade.class);
333 
334         doAnswer(new AnswerWithArguments() {
335             public void answer(
336                     Context context, String ifname, IpClientCallbacks callback) {
337                 mIpClientCallback = callback;
338                 callback.onIpClientCreated(mIpClient);
339             }
340         }).when(facade).makeIpClient(any(), anyString(), any());
341 
342         return facade;
343     }
344 
getContext()345     private WifiContext getContext() throws Exception {
346         when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
347 
348         WifiContext context = mock(WifiContext.class);
349         when(context.getPackageManager()).thenReturn(mPackageManager);
350 
351         MockContentResolver mockContentResolver = new MockContentResolver();
352         mockContentResolver.addProvider(Settings.AUTHORITY,
353                 new MockContentProvider(context) {
354                     @Override
355                     public Bundle call(String method, String arg, Bundle extras) {
356                         return new Bundle();
357                     }
358                 });
359         when(context.getContentResolver()).thenReturn(mockContentResolver);
360 
361         when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
362         when(context.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
363         when(mPowerManager.isInteractive()).thenReturn(true);
364         when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(
365                 mock(PowerManager.WakeLock.class));
366 
367         mAlarmManager = new TestAlarmManager();
368         when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
369                 mAlarmManager.getAlarmManager());
370 
371         when(context.getOpPackageName()).thenReturn(OP_PACKAGE_NAME);
372 
373         when(context.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
374 
375         WifiP2pManager p2pm = mock(WifiP2pManager.class);
376         when(context.getSystemService(WifiP2pManager.class)).thenReturn(p2pm);
377         final CountDownLatch untilDone = new CountDownLatch(1);
378         mP2pThread = new HandlerThread("WifiP2pMockThread") {
379             @Override
380             protected void onLooperPrepared() {
381                 untilDone.countDown();
382             }
383         };
384         mP2pThread.start();
385         untilDone.await();
386         Handler handler = new Handler(mP2pThread.getLooper());
387         when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
388 
389         mUserAllContext = mock(Context.class);
390         when(context.createContextAsUser(UserHandle.ALL, 0)).thenReturn(mUserAllContext);
391 
392         return context;
393     }
394 
getMockResources()395     private MockResources getMockResources() {
396         MockResources resources = new MockResources();
397         return resources;
398     }
399 
getCurrentState()400     private IState getCurrentState() throws
401             NoSuchMethodException, InvocationTargetException, IllegalAccessException {
402         Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
403         method.setAccessible(true);
404         return (IState) method.invoke(mCmi);
405     }
406 
getCmiHandlerThread(ClientModeImpl cmi)407     private static HandlerThread getCmiHandlerThread(ClientModeImpl cmi) throws
408             NoSuchFieldException, InvocationTargetException, IllegalAccessException {
409         Field field = StateMachine.class.getDeclaredField("mSmThread");
410         field.setAccessible(true);
411         return (HandlerThread) field.get(cmi);
412     }
413 
stopLooper(final Looper looper)414     private static void stopLooper(final Looper looper) throws Exception {
415         new Handler(looper).post(new Runnable() {
416             @Override
417             public void run() {
418                 looper.quitSafely();
419             }
420         });
421     }
422 
dumpState()423     private void dumpState() {
424         ByteArrayOutputStream stream = new ByteArrayOutputStream();
425         PrintWriter writer = new PrintWriter(stream);
426         mCmi.dump(null, writer, null);
427         writer.flush();
428         Log.d(TAG, "ClientModeImpl state -" + stream.toString());
429     }
430 
getGoogleGuestScanDetail(int rssi, String bssid, int freq)431     private static ScanDetail getGoogleGuestScanDetail(int rssi, String bssid, int freq) {
432         ScanResult.InformationElement[] ie = new ScanResult.InformationElement[1];
433         ie[0] = ScanResults.generateSsidIe(TEST_SSID);
434         NetworkDetail nd = new NetworkDetail(TEST_BSSID_STR, ie, new ArrayList<String>(), sFreq);
435         ScanDetail detail = new ScanDetail(nd, TEST_WIFI_SSID, bssid, "", rssi, freq,
436                 Long.MAX_VALUE, /* needed so that scan results aren't rejected because
437                                    there older than scan start */
438                 ie, new ArrayList<String>(), ScanResults.generateIERawDatafromScanResultIE(ie));
439 
440         return detail;
441     }
442 
getHiddenScanDetail(int rssi, String bssid, int freq)443     private static ScanDetail getHiddenScanDetail(int rssi, String bssid, int freq) {
444         ScanResult.InformationElement ie = new ScanResult.InformationElement();
445         WifiSsid ssid = WifiSsid.fromBytes(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
446         ie.id = ScanResult.InformationElement.EID_SSID;
447         ie.bytes = ssid.getBytes();
448         ScanResult.InformationElement[] ies = new ScanResult.InformationElement[1];
449         ies[0] = ie;
450         NetworkDetail nd = new NetworkDetail(TEST_BSSID_STR, ies, new ArrayList<String>(), sFreq);
451         ScanDetail detail = new ScanDetail(nd, ssid, bssid, "", rssi, freq,
452                 Long.MAX_VALUE, /* needed so that scan results aren't rejected because
453                                    there older than scan start */
454                 ies, new ArrayList<String>(), ScanResults.generateIERawDatafromScanResultIE(ies));
455 
456         return detail;
457     }
458 
getMockScanResults()459     private ArrayList<ScanDetail> getMockScanResults() {
460         ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
461         ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
462 
463         list.add(getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
464         return list;
465     }
466 
injectDhcpSuccess(DhcpResultsParcelable dhcpResults)467     private void injectDhcpSuccess(DhcpResultsParcelable dhcpResults) {
468         mIpClientCallback.onNewDhcpResults(dhcpResults);
469         mIpClientCallback.onProvisioningSuccess(new LinkProperties());
470     }
471 
injectDhcpSuccess()472     private void injectDhcpSuccess() {
473         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
474         dhcpResults.baseConfiguration = new StaticIpConfiguration();
475         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
476         dhcpResults.baseConfiguration.ipAddress =
477                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
478         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
479         dhcpResults.leaseDuration = 3600;
480         injectDhcpSuccess(dhcpResults);
481     }
482 
injectDhcpFailure()483     private void injectDhcpFailure() {
484         mIpClientCallback.onNewDhcpResults((DhcpResultsParcelable) null);
485         mIpClientCallback.onProvisioningFailure(new LinkProperties());
486     }
487 
488     static final String   TEST_SSID = "\"GoogleGuest\"";
489     static final String   SSID_NO_QUOTE = TEST_SSID.replace("\"", "");
490     static final WifiSsid TEST_WIFI_SSID = WifiSsid.fromUtf8Text(SSID_NO_QUOTE);
491     static final String   TEST_SSID1 = "\"RandomSsid1\"";
492     static final String   SSID_NO_QUOTE1 = TEST_SSID1.replace("\"", "");
493     static final WifiSsid TEST_WIFI_SSID1 = WifiSsid.fromUtf8Text(SSID_NO_QUOTE1);
494     static final String   TEST_BSSID_STR = "01:02:03:04:05:06";
495     static final String   TEST_BSSID_STR1 = "02:01:04:03:06:05";
496     static final String   TEST_BSSID_STR2 = "02:01:04:03:06:04";
497     static final int      sFreq = 2437;
498     static final int      sFreq1 = 5240;
499     static final String   WIFI_IFACE_NAME = "mockWlan";
500     static final String sFilsSsid = "FILS-AP";
501     static final ApfCapabilities APF_CAP = new ApfCapabilities(1, 2, 3);
502     static final long TEST_TX_BYTES = 6666;
503     static final long TEST_RX_BYTES = 8888;
504     static final int TEST_MULTICAST_LOCK_MAX_DTIM_MULTIPLIER = 1;
505     static final int TEST_IPV6_ONLY_NETWORK_MAX_DTIM_MULTIPLIER = 2;
506     static final int TEST_IPV4_ONLY_NETWORK_MAX_DTIM_MULTIPLIER = 9;
507     static final int TEST_DUAL_STACK_NETWORK_MAX_DTIM_MULTIPLIER = 2;
508     static final int TEST_CHANNEL = 6;
509     static final int TEST_CHANNEL_1 = 44;
510 
511     ClientModeImpl mCmi;
512     HandlerThread mWifiCoreThread;
513     HandlerThread mP2pThread;
514     HandlerThread mSyncThread;
515     TestAlarmManager mAlarmManager;
516     MockWifiMonitor mWifiMonitor;
517     TestLooper mLooper;
518     WifiContext mContext;
519     Context mUserAllContext;
520     MockResources mResources;
521     FrameworkFacade mFrameworkFacade;
522     IpClientCallbacks mIpClientCallback;
523     OsuProvider mOsuProvider;
524     WifiConfiguration mConnectedNetwork;
525     WifiConfiguration mTestConfig;
526     ExtendedWifiInfo mWifiInfo;
527     WifiRoamingModeManager mWifiRoamingModeManager;
528     ConnectionCapabilities mConnectionCapabilities = new ConnectionCapabilities();
529 
530     @Mock ActivityManager mActivityManager;
531     @Mock WifiNetworkAgent mWifiNetworkAgent;
532     @Mock SupplicantStateTracker mSupplicantStateTracker;
533     @Mock WifiMetrics mWifiMetrics;
534     @Mock WifiInjector mWifiInjector;
535     @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
536     @Mock WifiBlocklistMonitor mWifiBlocklistMonitor;
537     @Mock WifiConfigManager mWifiConfigManager;
538     @Mock WifiNative mWifiNative;
539     @Mock WifiScoreCard mWifiScoreCard;
540     @Mock PerNetwork mPerNetwork;
541     @Mock PerBssid mPerBssid;
542     @Mock WifiScoreCard.NetworkConnectionStats mPerNetworkRecentStats;
543     @Mock WifiHealthMonitor mWifiHealthMonitor;
544     @Mock WifiTrafficPoller mWifiTrafficPoller;
545     @Mock WifiConnectivityManager mWifiConnectivityManager;
546     @Mock WifiStateTracker mWifiStateTracker;
547     @Mock PasspointManager mPasspointManager;
548     @Mock WifiPermissionsUtil mWifiPermissionsUtil;
549     @Mock IIpClient mIpClient;
550     @Mock TelephonyManager mTelephonyManager;
551     @Mock TelephonyManager mDataTelephonyManager;
552     @Mock WrongPasswordNotifier mWrongPasswordNotifier;
553     @Mock Clock mClock;
554     @Mock ScanDetailCache mScanDetailCache;
555     @Mock WifiDiagnostics mWifiDiagnostics;
556     @Mock IProvisioningCallback mProvisioningCallback;
557     @Mock WakeupController mWakeupController;
558     @Mock WifiDataStall mWifiDataStall;
559     @Mock WifiNetworkFactory mWifiNetworkFactory;
560     @Mock UntrustedWifiNetworkFactory mUntrustedWifiNetworkFactory;
561     @Mock OemWifiNetworkFactory mOemWifiNetworkFactory;
562     @Mock RestrictedWifiNetworkFactory mRestrictedWifiNetworkFactory;
563     @Mock MultiInternetManager mMultiInternetManager;
564     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
565     @Mock PackageManager mPackageManager;
566     @Mock WifiLockManager mWifiLockManager;
567     @Mock AsyncChannel mNullAsyncChannel;
568     @Mock BatteryStatsManager mBatteryStatsManager;
569     @Mock MboOceController mMboOceController;
570     @Mock ConnectionFailureNotifier mConnectionFailureNotifier;
571     @Mock EapFailureNotifier mEapFailureNotifier;
572     @Mock SimRequiredNotifier mSimRequiredNotifier;
573     @Mock ThroughputPredictor mThroughputPredictor;
574     @Mock ScanRequestProxy mScanRequestProxy;
575     @Mock DeviceConfigFacade mDeviceConfigFacade;
576     @Mock Network mNetwork;
577     @Mock ConcreteClientModeManager mClientModeManager;
578     @Mock WifiScoreReport mWifiScoreReport;
579     @Mock PowerManager mPowerManager;
580     @Mock WifiP2pConnection mWifiP2pConnection;
581     @Mock WifiGlobals mWifiGlobals;
582     @Mock LinkProbeCallback mLinkProbeCallback;
583     @Mock ClientModeImplMonitor mCmiMonitor;
584     @Mock ClientModeManagerBroadcastQueue mBroadcastQueue;
585     @Mock WifiNetworkSelector mWifiNetworkSelector;
586     @Mock ActiveModeWarden mActiveModeWarden;
587     @Mock ClientModeManager mPrimaryClientModeManager;
588     @Mock WifiSettingsConfigStore mSettingsConfigStore;
589     @Mock Uri mMockUri;
590     @Mock WifiCarrierInfoManager mWifiCarrierInfoManager;
591     @Mock WifiPseudonymManager mWifiPseudonymManager;
592     @Mock WifiNotificationManager mWifiNotificationManager;
593 
594     @Mock WifiConnectivityHelper mWifiConnectivityHelper;
595     @Mock InsecureEapNetworkHandler mInsecureEapNetworkHandler;
596     @Mock ScanResult mScanResult;
597     @Mock HandlerThread mWifiHandlerThread;
598     @Mock SsidTranslator mSsidTranslator;
599     @Mock ApplicationQosPolicyRequestHandler mApplicationQosPolicyRequestHandler;
600     @Mock LocalLog mLocalLog;
601     @Mock WifiDeviceStateChangeManager mWifiDeviceStateChangeManager;
602     @Mock WifiCountryCode mWifiCountryCode;
603     @Mock WifiRoamingConfigStore mWifiRoamingConfigStore;
604 
605     @Mock DeviceWiphyCapabilities mDeviceWiphyCapabilities;
606 
607     @Captor ArgumentCaptor<WifiConfigManager.OnNetworkUpdateListener> mConfigUpdateListenerCaptor;
608     @Captor ArgumentCaptor<WifiNetworkAgent.Callback> mWifiNetworkAgentCallbackCaptor;
609     @Captor ArgumentCaptor<WifiCarrierInfoManager.OnCarrierOffloadDisabledListener>
610             mOffloadDisabledListenerArgumentCaptor = ArgumentCaptor.forClass(
611                     WifiCarrierInfoManager.OnCarrierOffloadDisabledListener.class);
612     @Captor ArgumentCaptor<BroadcastReceiver> mScreenStateBroadcastReceiverCaptor;
613 
614     @Captor
615     ArgumentCaptor<WifiDeviceStateChangeManager.StateChangeCallback>
616             mStateChangeCallbackArgumentCaptor;
617 
618     @Captor ArgumentCaptor<ProvisioningConfigurationParcelable> mProvisioningConfigurationCaptor;
619     WifiInfo mPrimaryWifiInfo;
620 
setUpWifiNative()621     private void setUpWifiNative() throws Exception {
622         when(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(
623                 TEST_GLOBAL_MAC_ADDRESS);
624         doAnswer(new AnswerWithArguments() {
625             public void answer(WifiSettingsConfigStore.Key<String> key, Object macAddress) {
626                 when(mSettingsConfigStore.get(WIFI_STA_FACTORY_MAC_ADDRESS))
627                         .thenReturn((String) macAddress);
628             }
629         }).when(mSettingsConfigStore).put(eq(WIFI_STA_FACTORY_MAC_ADDRESS), any(String.class));
630         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
631                 .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString());
632         ConnectionCapabilities cap = new ConnectionCapabilities();
633         cap.wifiStandard = ScanResult.WIFI_STANDARD_11AC;
634         when(mWifiNative.getConnectionCapabilities(WIFI_IFACE_NAME))
635                 .thenReturn(mConnectionCapabilities);
636         when(mWifiNative.setStaMacAddress(eq(WIFI_IFACE_NAME), any()))
637                 .then(new AnswerWithArguments() {
638                     public boolean answer(String iface, MacAddress mac) {
639                         when(mWifiNative.getMacAddress(iface)).thenReturn(mac.toString());
640                         return true;
641                     }
642                 });
643         when(mWifiNative.connectToNetwork(any(), any())).thenReturn(true);
644         when(mWifiNative.getApfCapabilities(anyString())).thenReturn(APF_CAP);
645         when(mWifiNative.isQosPolicyFeatureEnabled()).thenReturn(true);
646         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
647     }
648 
649     /** Reset verify() counters on WifiNative, and restore when() mocks on mWifiNative */
resetWifiNative()650     private void resetWifiNative() throws Exception {
651         reset(mWifiNative);
652         setUpWifiNative();
653     }
654 
655     @Before
setUp()656     public void setUp() throws Exception {
657         Log.d(TAG, "Setting up ...");
658 
659         // Ensure looper exists
660         mLooper = new TestLooper();
661 
662         MockitoAnnotations.initMocks(this);
663 
664         /** uncomment this to enable logs from ClientModeImpls */
665         // enableDebugLogs();
666         mWifiMonitor = spy(new MockWifiMonitor());
667         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
668         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
669                 .thenReturn(Collections.emptySet());
670         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
671                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
672         setUpWifiNative();
673         doAnswer(new AnswerWithArguments() {
674             public MacAddress answer(
675                     WifiConfiguration config, boolean isForSecondaryDbs) {
676                 MacAddress mac = config.getRandomizedMacAddress();
677                 if (isForSecondaryDbs) {
678                     mac = MacAddressUtil.nextMacAddress(mac);
679                 }
680                 return mac;
681             }
682         }).when(mWifiConfigManager).getRandomizedMacAndUpdateIfNeeded(any(), anyBoolean());
683 
684         mTestNetworkParams = new TestNetworkParams();
685         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(true);
686         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(true);
687         when(mOemWifiNetworkFactory.hasConnectionRequests()).thenReturn(true);
688         when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(true);
689         when(mApplicationQosPolicyRequestHandler.isFeatureEnabled()).thenReturn(true);
690         when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog);
691         when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode);
692         when(mWifiInjector.getApplicationQosPolicyRequestHandler())
693                 .thenReturn(mApplicationQosPolicyRequestHandler);
694 
695         mFrameworkFacade = getFrameworkFacade();
696         mContext = getContext();
697         mWifiInfo = new ExtendedWifiInfo(mWifiGlobals, WIFI_IFACE_NAME);
698         mWifiRoamingModeManager = new WifiRoamingModeManager(mWifiNative,
699                 mActiveModeWarden, mWifiRoamingConfigStore);
700 
701         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(true);
702         mResources = getMockResources();
703         mResources.setIntArray(R.array.config_wifiRssiLevelThresholds,
704                 RssiUtilTest.RSSI_THRESHOLDS);
705         mResources.setInteger(R.integer.config_wifiLinkBandwidthUpdateThresholdPercent, 25);
706         mResources.setInteger(R.integer.config_wifiClientModeImplNumLogRecs, 100);
707         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
708         when(mContext.getResources()).thenReturn(mResources);
709 
710         when(mWifiGlobals.getPollRssiIntervalMillis()).thenReturn(3000);
711         when(mWifiGlobals.getIpReachabilityDisconnectEnabled()).thenReturn(true);
712         when(mWifiGlobals.getRepeatedNudFailuresThreshold()).thenReturn(Integer.MAX_VALUE);
713 
714         when(mFrameworkFacade.getIntegerSetting(mContext,
715                 Settings.Global.WIFI_FREQUENCY_BAND,
716                 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
717                 WifiManager.WIFI_FREQUENCY_BAND_AUTO);
718         when(mFrameworkFacade.getTxBytes(eq(WIFI_IFACE_NAME))).thenReturn(TEST_TX_BYTES);
719         when(mFrameworkFacade.getRxBytes(eq(WIFI_IFACE_NAME))).thenReturn(TEST_RX_BYTES);
720         when(mFrameworkFacade.getTotalTxBytes()).thenReturn(TEST_TX_BYTES);
721         when(mFrameworkFacade.getTotalRxBytes()).thenReturn(TEST_RX_BYTES);
722         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
723         doAnswer(inv -> {
724             mIpClientCallback.onQuit();
725             return null;
726         }).when(mIpClient).shutdown();
727         when(mWifiNetworkAgent.getNetwork()).thenReturn(mNetwork);
728 
729         // static mocking
730         mSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
731                 .mockStatic(WifiInjector.class, withSettings().lenient())
732                 .spyStatic(MacAddress.class)
733                 .startMocking();
734         when(WifiInjector.getInstance()).thenReturn(mWifiInjector);
735 
736         when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden);
737         when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager);
738         when(mPrimaryClientModeManager.getSupportedFeaturesBitSet()).thenReturn(
739                 createCapabilityBitset(
740                         WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE));
741         when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals);
742         when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread);
743         when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator);
744         when(mWifiInjector.getWifiDeviceStateChangeManager())
745                 .thenReturn(mWifiDeviceStateChangeManager);
746         when(mWifiHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
747         when(mWifiNative.getDeviceWiphyCapabilities(any())).thenReturn(mDeviceWiphyCapabilities);
748         if (Flags.getDeviceCrossAkmRoamingSupport() && SdkLevel.isAtLeastV()) {
749             when(mDeviceWiphyCapabilities.getMaxNumberAkms()).thenReturn(3);
750         }
751         when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true);
752         when(mWifiGlobals.getClientModeImplNumLogRecs()).thenReturn(100);
753         when(mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled()).thenReturn(true);
754         when(mWifiGlobals.getNetworkNotFoundEventThreshold()).thenReturn(3);
755         when(mWifiGlobals.getMacRandomizationUnsupportedSsidPrefixes()).thenReturn(
756                 Collections.EMPTY_SET);
757         when(mWifiInjector.makeWifiNetworkAgent(any(), any(), any(), any(), any()))
758                 .thenAnswer(new AnswerWithArguments() {
759                     public WifiNetworkAgent answer(
760                             @NonNull NetworkCapabilities nc,
761                             @NonNull LinkProperties linkProperties,
762                             @NonNull NetworkAgentConfig naConfig,
763                             @Nullable NetworkProvider provider,
764                             @NonNull WifiNetworkAgent.Callback callback) {
765                         when(mWifiNetworkAgent.getCallback()).thenReturn(callback);
766                         return mWifiNetworkAgent;
767                     }
768                 });
769         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
770         // Update the WifiInfo in WifiActiveModeWarden
771         doAnswer(inv -> {
772             if (mCmi != null) {
773                 mPrimaryWifiInfo = mCmi.getConnectionInfo();
774             }
775             return null;
776         }).when(mActiveModeWarden).updateCurrentConnectionInfo();
777         initializeCmi();
778         // Retrieve factory MAC address on first bootup.
779         verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME);
780         if (Flags.getDeviceCrossAkmRoamingSupport() && SdkLevel.isAtLeastV()) {
781             verify(mWifiGlobals).setWpa3SaeUpgradeOffloadEnabled();
782         }
783 
784         mOsuProvider = PasspointProvisioningTestUtil.generateOsuProvider(true);
785         mConnectedNetwork = spy(WifiConfigurationTestUtil.createOpenNetwork());
786         when(mNullAsyncChannel.sendMessageSynchronously(any())).thenReturn(null);
787         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(new Pair<>(null, null));
788         when(mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()).thenReturn(true);
789         when(mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()).thenReturn(true);
790         when(mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()).thenReturn(true);
791         when(mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()).thenReturn(
792                 DeviceConfigFacade.DEFAULT_OVERLAPPING_CONNECTION_DURATION_THRESHOLD_MS);
793         when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
794                 .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
795         when(mWifiScoreCard.detectAbnormalDisconnection(any()))
796                 .thenReturn(WifiHealthMonitor.REASON_NO_FAILURE);
797         when(mPerNetwork.getRecentStats()).thenReturn(mPerNetworkRecentStats);
798         when(mWifiScoreCard.lookupNetwork(any())).thenReturn(mPerNetwork);
799         when(mWifiScoreCard.lookupBssid(any(), any())).thenReturn(mPerBssid);
800         when(mThroughputPredictor.predictMaxTxThroughput(any())).thenReturn(90);
801         when(mThroughputPredictor.predictMaxRxThroughput(any())).thenReturn(80);
802         when(mWifiInjector.getWifiRoamingModeManager()).thenReturn(mWifiRoamingModeManager);
803 
804         doAnswer(new AnswerWithArguments() {
805             public void answer(boolean shouldReduceNetworkScore) {
806                 mCmi.setShouldReduceNetworkScore(shouldReduceNetworkScore);
807             }
808         }).when(mClientModeManager).setShouldReduceNetworkScore(anyBoolean());
809         doAnswer(new AnswerWithArguments() {
810             public void answer(ClientModeManager manager, QueuedBroadcast broadcast) {
811                 broadcast.send();
812             }
813         }).when(mBroadcastQueue).queueOrSendBroadcast(any(), any());
814     }
815 
validateConnectionInfo()816     private void validateConnectionInfo() {
817         // The WifiInfo#equals returns false for pre-S, don't enforce the check.
818         if (!SdkLevel.isAtLeastS()) return;
819         if (mClientModeManager.getRole() == ROLE_CLIENT_PRIMARY) {
820             assertEquals(mCmi.getConnectionInfo(), mPrimaryWifiInfo);
821         }
822     }
823 
initializeCmi()824     private void initializeCmi() throws Exception {
825         mCmi = new ClientModeImpl(mContext, mWifiMetrics, mClock, mWifiScoreCard, mWifiStateTracker,
826                 mWifiPermissionsUtil, mWifiConfigManager, mPasspointManager,
827                 mWifiMonitor, mWifiDiagnostics, mWifiDataStall,
828                 new ScoringParams(), new WifiThreadRunner(new Handler(mLooper.getLooper())),
829                 mWifiNetworkSuggestionsManager, mWifiHealthMonitor, mThroughputPredictor,
830                 mDeviceConfigFacade, mScanRequestProxy, mWifiInfo, mWifiConnectivityManager,
831                 mWifiBlocklistMonitor, mConnectionFailureNotifier,
832                 WifiInjector.REGULAR_NETWORK_CAPABILITIES_FILTER, mWifiNetworkFactory,
833                 mUntrustedWifiNetworkFactory, mOemWifiNetworkFactory, mRestrictedWifiNetworkFactory,
834                 mMultiInternetManager, mWifiLastResortWatchdog, mWakeupController,
835                 mWifiLockManager, mFrameworkFacade, mLooper.getLooper(),
836                 mWifiNative, mWrongPasswordNotifier, mWifiTrafficPoller,
837                 1, mBatteryStatsManager, mSupplicantStateTracker, mMboOceController,
838                 mWifiCarrierInfoManager, mWifiPseudonymManager, mEapFailureNotifier,
839                 mSimRequiredNotifier, mWifiScoreReport, mWifiP2pConnection, mWifiGlobals,
840                 WIFI_IFACE_NAME, mClientModeManager, mCmiMonitor,
841                 mBroadcastQueue, mWifiNetworkSelector, mTelephonyManager, mWifiInjector,
842                 mSettingsConfigStore, false, mWifiNotificationManager,
843                 mWifiConnectivityHelper);
844         mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler;
845 
846         mWifiCoreThread = getCmiHandlerThread(mCmi);
847 
848         mBinderToken = Binder.clearCallingIdentity();
849 
850         verify(mWifiConfigManager, atLeastOnce()).addOnNetworkUpdateListener(
851                 mConfigUpdateListenerCaptor.capture());
852         assertNotNull(mConfigUpdateListenerCaptor.getValue());
853 
854         verify(mWifiCarrierInfoManager, atLeastOnce()).addOnCarrierOffloadDisabledListener(
855                 mOffloadDisabledListenerArgumentCaptor.capture());
856         assertNotNull(mOffloadDisabledListenerArgumentCaptor.getValue());
857 
858         mCmi.enableVerboseLogging(true);
859         mCmi.disconnect();
860         mLooper.dispatchAll();
861 
862         verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts();
863         assertEquals("DisconnectedState", getCurrentState().getName());
864         validateConnectionInfo();
865 
866         verify(mWifiDeviceStateChangeManager, atLeastOnce())
867                 .registerStateChangeCallback(mStateChangeCallbackArgumentCaptor.capture());
868     }
869 
870     @After
cleanUp()871     public void cleanUp() throws Exception {
872         Binder.restoreCallingIdentity(mBinderToken);
873 
874         if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
875         if (mWifiCoreThread != null) stopLooper(mWifiCoreThread.getLooper());
876         if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
877 
878         mWifiCoreThread = null;
879         mP2pThread = null;
880         mSyncThread = null;
881         mCmi = null;
882         if (mSession != null) {
883             mSession.finishMocking();
884         }
885     }
886 
887     /**
888      *  Test that mode changes accurately reflect the value for isWifiEnabled.
889      */
890     @Test
checkIsWifiEnabledForModeChanges()891     public void checkIsWifiEnabledForModeChanges() throws Exception {
892         // now disable client mode and verify the reported wifi state
893         mCmi.stop();
894         mLooper.dispatchAll();
895         verify(mContext, never())
896                 .sendStickyBroadcastAsUser(argThat(new WifiEnablingStateIntentMatcher()), any());
897     }
898 
899     private static class WifiEnablingStateIntentMatcher implements ArgumentMatcher<Intent> {
900         @Override
matches(Intent intent)901         public boolean matches(Intent intent) {
902             return WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())
903                     && WifiManager.WIFI_STATE_ENABLING
904                             == intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
905                                     WifiManager.WIFI_STATE_DISABLED);
906         }
907     }
908 
909     private class NetworkStateChangedIntentMatcher implements ArgumentMatcher<Intent> {
910         private final NetworkInfo.DetailedState mState;
NetworkStateChangedIntentMatcher(NetworkInfo.DetailedState state)911         NetworkStateChangedIntentMatcher(NetworkInfo.DetailedState state) {
912             mState = state;
913         }
914         @Override
matches(Intent intent)915         public boolean matches(Intent intent) {
916             if (WifiManager.NETWORK_STATE_CHANGED_ACTION != intent.getAction()) {
917                 // not the correct type
918                 return false;
919             }
920             NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
921             return networkInfo.getDetailedState() == mState;
922         }
923     }
924 
canSaveNetworkConfig()925     private void canSaveNetworkConfig() throws Exception {
926         IActionListener connectActionListener = mock(IActionListener.class);
927         mCmi.saveNetwork(
928                 new NetworkUpdateResult(TEST_NETWORK_ID),
929                 new ActionListenerWrapper(connectActionListener),
930                 Binder.getCallingUid(), OP_PACKAGE_NAME);
931         mLooper.dispatchAll();
932         verify(connectActionListener).onSuccess();
933     }
934 
935     /**
936      * Verifies that configs can be saved when in client mode.
937      */
938     @Test
canSaveNetworkConfigInClientMode()939     public void canSaveNetworkConfigInClientMode() throws Exception {
940         canSaveNetworkConfig();
941     }
942 
943     /**
944      * Verifies that admin restricted configs can be saved without triggering a connection.
945      */
946     @Test
canSaveAdminRestrictedNetworkWithoutConnecting()947     public void canSaveAdminRestrictedNetworkWithoutConnecting() throws Exception {
948         assumeTrue(SdkLevel.isAtLeastT());
949 
950         mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
951         IActionListener connectActionListener = mock(IActionListener.class);
952         when(mWifiPermissionsUtil.isAdminRestrictedNetwork(any())).thenReturn(true);
953         mCmi.saveNetwork(
954                 new NetworkUpdateResult(TEST_NETWORK_ID, STATUS_SUCCESS, false, false, true, false),
955                 new ActionListenerWrapper(connectActionListener),
956                 Binder.getCallingUid(), OP_PACKAGE_NAME);
957         mLooper.dispatchAll();
958 
959         verify(connectActionListener).onSuccess();
960         verify(mWifiPermissionsUtil).isAdminRestrictedNetwork(any());
961         verify(mClientModeManager, never())
962                 .setShouldReduceNetworkScore(false);
963     }
964 
965     /**
966      * Verifies that deprecated security type configs can be saved without triggering a connection.
967      */
968     @Test
canSaveDeprecatedSecurityTypeNetworkWithoutConnecting()969     public void canSaveDeprecatedSecurityTypeNetworkWithoutConnecting() throws Exception {
970         mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
971         IActionListener connectActionListener = mock(IActionListener.class);
972         when(mWifiGlobals.isDeprecatedSecurityTypeNetwork(any())).thenReturn(true);
973         mCmi.saveNetwork(
974                 new NetworkUpdateResult(TEST_NETWORK_ID, STATUS_SUCCESS, false, false, true, false),
975                 new ActionListenerWrapper(connectActionListener),
976                 Binder.getCallingUid(), OP_PACKAGE_NAME);
977         mLooper.dispatchAll();
978 
979         verify(connectActionListener).onSuccess();
980         verify(mClientModeManager, never())
981                 .setShouldReduceNetworkScore(false);
982     }
983 
createTestNetwork(boolean isHidden)984     private WifiConfiguration createTestNetwork(boolean isHidden) {
985         WifiConfiguration config = new WifiConfiguration();
986         config.networkId = FRAMEWORK_NETWORK_ID;
987         config.SSID = TEST_SSID;
988         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
989         config.hiddenSSID = isHidden;
990         return config;
991     }
992 
initializeMocksForAddedNetwork(WifiConfiguration config)993     private void initializeMocksForAddedNetwork(WifiConfiguration config) throws Exception {
994         when(mWifiConfigManager.getSavedNetworks(anyInt())).thenReturn(Arrays.asList(config));
995         when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
996         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
997     }
998 
initializeMocksForAddedNetwork(boolean isHidden)999     private void initializeMocksForAddedNetwork(boolean isHidden) throws Exception {
1000         mTestConfig = createTestNetwork(isHidden);
1001         initializeMocksForAddedNetwork(mTestConfig);
1002     }
1003 
initializeAndAddNetworkAndVerifySuccess(WifiConfiguration config)1004     private void initializeAndAddNetworkAndVerifySuccess(WifiConfiguration config)
1005             throws Exception {
1006         initializeMocksForAddedNetwork(config);
1007     }
1008 
initializeAndAddNetworkAndVerifySuccess()1009     private void initializeAndAddNetworkAndVerifySuccess() throws Exception {
1010         initializeAndAddNetworkAndVerifySuccess(false);
1011     }
1012 
initializeAndAddNetworkAndVerifySuccess(boolean isHidden)1013     private void initializeAndAddNetworkAndVerifySuccess(boolean isHidden) throws Exception {
1014         initializeMocksForAddedNetwork(isHidden);
1015     }
1016 
setupAndStartConnectSequence(WifiConfiguration config)1017     private void setupAndStartConnectSequence(WifiConfiguration config) throws Exception {
1018         when(mWifiConfigManager.getConfiguredNetwork(eq(config.networkId)))
1019                 .thenReturn(config);
1020         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(
1021                 eq(config.networkId))).thenReturn(config);
1022 
1023         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
1024 
1025         IActionListener connectActionListener = mock(IActionListener.class);
1026         mCmi.connectNetwork(
1027                 new NetworkUpdateResult(config.networkId),
1028                 new ActionListenerWrapper(connectActionListener),
1029                 Binder.getCallingUid(), OP_PACKAGE_NAME, mAttributionTagForConnect);
1030         mLooper.dispatchAll();
1031         verify(connectActionListener).onSuccess();
1032     }
1033 
validateSuccessfulConnectSequence(WifiConfiguration config)1034     private void validateSuccessfulConnectSequence(WifiConfiguration config) {
1035         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
1036         verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId));
1037         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
1038         verify(mCmiMonitor).onConnectionStart(mClientModeManager);
1039         assertEquals("L2ConnectingState", mCmi.getCurrentState().getName());
1040     }
1041 
validateFailureConnectSequence(WifiConfiguration config)1042     private void validateFailureConnectSequence(WifiConfiguration config) {
1043         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
1044         verify(mWifiConfigManager, never())
1045                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
1046         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
1047     }
1048 
1049     /**
1050      * Tests the network connection initiation sequence with the default network request pending
1051      * from WifiNetworkFactory.
1052      * This simulates the connect sequence using the public
1053      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
1054      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
1055      */
1056     @Test
triggerConnect()1057     public void triggerConnect() throws Exception {
1058         WifiConfiguration config = mConnectedNetwork;
1059         config.networkId = FRAMEWORK_NETWORK_ID;
1060         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
1061         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
1062         config.getNetworkSelectionStatus().setHasEverConnected(mTestNetworkParams.hasEverConnected);
1063         assertEquals(null, config.getNetworkSelectionStatus().getCandidateSecurityParams());
1064         setupAndStartConnectSequence(config);
1065         validateSuccessfulConnectSequence(config);
1066         assertEquals(config.getSecurityParamsList().stream()
1067                         .filter(WifiConfigurationUtil::isSecurityParamsValid)
1068                         .findFirst().orElse(null),
1069                 config.getNetworkSelectionStatus().getCandidateSecurityParams());
1070         mConnectedNetwork.getNetworkSelectionStatus().setLastUsedSecurityParams(
1071                 config.getNetworkSelectionStatus().getCandidateSecurityParams());
1072     }
1073 
1074     /**
1075      * Tests the manual connection request will run network selection to find
1076      * a proper security params, but not use the default one.
1077      */
1078     @Test
triggerConnectWithUpgradeType()1079     public void triggerConnectWithUpgradeType() throws Exception {
1080         String ssid = "TestOpenOweSsid";
1081         WifiConfiguration config = spy(WifiConfigurationTestUtil.createOpenOweNetwork(
1082                 ScanResultUtil.createQuotedSsid(ssid)));
1083         doAnswer(new AnswerWithArguments() {
1084             public WifiConfiguration answer(List<WifiCandidates.Candidate> candidates) {
1085                 config.getNetworkSelectionStatus().setCandidateSecurityParams(
1086                         SecurityParams.createSecurityParamsBySecurityType(
1087                                 WifiConfiguration.SECURITY_TYPE_OWE));
1088                 return config;
1089             }
1090         }).when(mWifiNetworkSelector).selectNetwork(any());
1091         String caps = "[RSN-OWE_TRANSITION]";
1092         ScanResult scanResult = new ScanResult.Builder(WifiSsid.fromUtf8Text(ssid),
1093                 TEST_BSSID_STR)
1094                 .setHessid(1245)
1095                 .setCaps(caps)
1096                 .setRssi(-78)
1097                 .setFrequency(2450)
1098                 .setTsf(1025)
1099                 .setDistanceCm(22)
1100                 .setDistanceSdCm(33)
1101                 .setIs80211McRTTResponder(true)
1102                 .build();
1103         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
1104                 ssid.getBytes(StandardCharsets.UTF_8));
1105         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
1106         when(mScanRequestProxy.getScanResults()).thenReturn(Arrays.asList(scanResult));
1107 
1108         config.networkId = FRAMEWORK_NETWORK_ID;
1109         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
1110         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
1111         config.getNetworkSelectionStatus().setHasEverConnected(mTestNetworkParams.hasEverConnected);
1112         assertEquals(null, config.getNetworkSelectionStatus().getCandidateSecurityParams());
1113 
1114         setupAndStartConnectSequence(config);
1115         validateSuccessfulConnectSequence(config);
1116         assertEquals(WifiConfiguration.SECURITY_TYPE_OWE,
1117                 config.getNetworkSelectionStatus().getCandidateSecurityParams().getSecurityType());
1118     }
1119 
1120     /**
1121      * Tests the manual connection request will use the last used security params when there
1122      * is no scan result.
1123      */
1124     @Test
triggerConnectWithLastUsedSecurityParams()1125     public void triggerConnectWithLastUsedSecurityParams() throws Exception {
1126         String ssid = "TestOpenOweSsid";
1127         WifiConfiguration config = spy(WifiConfigurationTestUtil.createOpenOweNetwork(
1128                 ScanResultUtil.createQuotedSsid(ssid)));
1129         when(mScanRequestProxy.getScanResults()).thenReturn(new ArrayList<>());
1130 
1131         config.networkId = FRAMEWORK_NETWORK_ID;
1132         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
1133         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
1134         config.getNetworkSelectionStatus().setHasEverConnected(mTestNetworkParams.hasEverConnected);
1135         config.getNetworkSelectionStatus().setLastUsedSecurityParams(
1136                 SecurityParams.createSecurityParamsBySecurityType(
1137                         WifiConfiguration.SECURITY_TYPE_OWE));
1138         assertEquals(null, config.getNetworkSelectionStatus().getCandidateSecurityParams());
1139 
1140         setupAndStartConnectSequence(config);
1141         validateSuccessfulConnectSequence(config);
1142         assertEquals(WifiConfiguration.SECURITY_TYPE_OWE,
1143                 config.getNetworkSelectionStatus().getCandidateSecurityParams().getSecurityType());
1144     }
1145 
1146     /**
1147      * Tests the network connection initiation sequence with the default network request pending
1148      * from WifiNetworkFactory.
1149      * This simulates the connect sequence using the public
1150      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
1151      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
1152      */
1153     @Test
triggerConnectFromNonSettingsApp()1154     public void triggerConnectFromNonSettingsApp() throws Exception {
1155         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
1156         config.networkId = FRAMEWORK_NETWORK_ID;
1157         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(Process.myUid()))
1158                 .thenReturn(false);
1159         setupAndStartConnectSequence(config);
1160         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
1161         verify(mWifiConfigManager).getConfiguredNetworkWithoutMasking(eq(config.networkId));
1162         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
1163     }
1164 
1165     /**
1166      * Tests the network connection initiation sequence with no network request pending from
1167      * from WifiNetworkFactory.
1168      * This simulates the connect sequence using the public
1169      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke
1170      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
1171      */
1172     @Test
triggerConnectWithNoNetworkRequest()1173     public void triggerConnectWithNoNetworkRequest() throws Exception {
1174         // Remove the network requests.
1175         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1176         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1177         when(mOemWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
1178         when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(false);
1179 
1180         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
1181         config.networkId = FRAMEWORK_NETWORK_ID;
1182         setupAndStartConnectSequence(config);
1183         validateFailureConnectSequence(config);
1184     }
1185 
1186     /**
1187      * Tests the entire successful network connection flow.
1188      */
1189     @Test
testConnect()1190     public void testConnect() throws Exception {
1191         connect(null);
1192     }
1193 
connect()1194     private void connect() throws Exception {
1195         connect(null);
1196     }
1197 
1198     /**
1199      * Simulate a connect
1200      *
1201      * @param wnmDataForTermsAndConditions Use null unless it is required to simulate a terms and
1202      *                                     conditions acceptance notification from Passpoint
1203      * @throws Exception
1204      */
connect(WnmData wnmDataForTermsAndConditions)1205     private void connect(WnmData wnmDataForTermsAndConditions) throws Exception {
1206         assertNull(mCmi.getConnectingWifiConfiguration());
1207         assertNull(mCmi.getConnectedWifiConfiguration());
1208 
1209         triggerConnect();
1210         validateConnectionInfo();
1211 
1212         assertNotNull(mCmi.getConnectingWifiConfiguration());
1213         assertNull(mCmi.getConnectedWifiConfiguration());
1214 
1215         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID);
1216         config.carrierId = CARRIER_ID_1;
1217         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1218                 .thenReturn(mScanDetailCache);
1219 
1220         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1221                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1222         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1223                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1224         ScanResult scanResult = new ScanResult.Builder(WifiSsid.fromUtf8Text(sFilsSsid),
1225                 TEST_BSSID_STR)
1226                 .setHessid(1245)
1227                 .setRssi(-78)
1228                 .setFrequency(2450)
1229                 .setTsf(1025)
1230                 .setDistanceCm(22)
1231                 .setDistanceSdCm(33)
1232                 .setIs80211McRTTResponder(true)
1233                 .build();
1234         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
1235                 sFilsSsid.getBytes(StandardCharsets.UTF_8));
1236         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
1237         when(mScanRequestProxy.getScanResult(eq(TEST_BSSID_STR))).thenReturn(scanResult);
1238 
1239         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1240                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
1241                         SupplicantState.ASSOCIATED));
1242         mLooper.dispatchAll();
1243         validateConnectionInfo();
1244 
1245         WifiSsid wifiSsid = WifiSsid.fromBytes(
1246                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1247         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1248                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1249         mLooper.dispatchAll();
1250         // WifiInfo should be updated if it is primary
1251         validateConnectionInfo();
1252 
1253         verify(mWifiMetrics).noteFirstL2ConnectionAfterBoot(true);
1254 
1255         // L2 connected, but not L3 connected yet. So, still "Connecting"...
1256         assertNotNull(mCmi.getConnectingWifiConfiguration());
1257         assertNull(mCmi.getConnectedWifiConfiguration());
1258 
1259         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1260                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
1261                         SupplicantState.COMPLETED));
1262         mLooper.dispatchAll();
1263         validateConnectionInfo();
1264 
1265         assertEquals("L3ProvisioningState", getCurrentState().getName());
1266         verifyNetworkStateChangedBroadcast(times(1),
1267                 new NetworkStateChangedIntentMatcher(CONNECTING));
1268         verifyNetworkStateChangedBroadcast(times(1),
1269                 new NetworkStateChangedIntentMatcher(OBTAINING_IPADDR));
1270 
1271         if (wnmDataForTermsAndConditions != null) {
1272             mCmi.sendMessage(WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT,
1273                     0, 0, wnmDataForTermsAndConditions);
1274             mLooper.dispatchAll();
1275         }
1276 
1277         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
1278         dhcpResults.baseConfiguration = new StaticIpConfiguration();
1279         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
1280         dhcpResults.baseConfiguration.ipAddress =
1281                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
1282         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
1283         dhcpResults.leaseDuration = 3600;
1284 
1285         injectDhcpSuccess(dhcpResults);
1286         mLooper.dispatchAll();
1287 
1288         assertNull(mCmi.getConnectingWifiConfiguration());
1289         assertNotNull(mCmi.getConnectedWifiConfiguration());
1290 
1291         // Verify WifiMetrics logging for metered metrics based on DHCP results
1292         verify(mWifiMetrics).addMeteredStat(any(), anyBoolean());
1293         WifiInfo wifiInfo = mWifiInfo;
1294         assertNotNull(wifiInfo);
1295         assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID());
1296         assertEquals(sFreq, wifiInfo.getFrequency());
1297         assertEquals(TEST_WIFI_SSID, wifiInfo.getWifiSsid());
1298         assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, wifiInfo.getMacAddress());
1299         assertEquals(mConnectedNetwork.getDefaultSecurityParams().getSecurityType(),
1300                 mWifiInfo.getCurrentSecurityType());
1301         if (wifiInfo.isPasspointAp()) {
1302             assertEquals(wifiInfo.getPasspointProviderFriendlyName(),
1303                     WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME);
1304         } else {
1305             assertNull(wifiInfo.getPasspointProviderFriendlyName());
1306         }
1307         assertEquals(Arrays.asList(scanResult.informationElements),
1308                     wifiInfo.getInformationElements());
1309         assertNotNull(wifiInfo.getNetworkKey());
1310         expectRegisterNetworkAgent((na) -> {
1311             if (!mConnectedNetwork.carrierMerged) {
1312                 assertNull(na.subscriberId);
1313             }
1314         }, (nc) -> {
1315                 if (SdkLevel.isAtLeastS()) {
1316                     WifiInfo wifiInfoFromTi = (WifiInfo) nc.getTransportInfo();
1317                     assertEquals(TEST_BSSID_STR, wifiInfoFromTi.getBSSID());
1318                     assertEquals(sFreq, wifiInfoFromTi.getFrequency());
1319                     assertEquals(TEST_WIFI_SSID, wifiInfoFromTi.getWifiSsid());
1320                     if (wifiInfo.isPasspointAp()) {
1321                         assertEquals(wifiInfoFromTi.getPasspointProviderFriendlyName(),
1322                                 WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME);
1323                     } else {
1324                         assertNull(wifiInfoFromTi.getPasspointProviderFriendlyName());
1325                     }
1326                 }
1327             });
1328 
1329         assertFalse(mCmi.isIpProvisioningTimedOut());
1330         // Ensure the connection stats for the network is updated.
1331         verify(mWifiConfigManager).updateNetworkAfterConnect(eq(FRAMEWORK_NETWORK_ID),
1332                 anyBoolean(), anyBoolean(), anyInt());
1333         verify(mWifiConfigManager).updateRandomizedMacExpireTime(any(), anyLong());
1334         verifyNetworkStateChangedBroadcast(times(1),
1335                 new NetworkStateChangedIntentMatcher(CONNECTED));
1336 
1337         // Anonymous Identity is not set.
1338         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1339         verify(mWifiStateTracker).updateState(WIFI_IFACE_NAME, WifiStateTracker.CONNECTED);
1340         assertEquals("L3ConnectedState", getCurrentState().getName());
1341         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionSuccess();
1342         verify(mWifiLockManager).updateWifiClientConnected(mClientModeManager, true);
1343         verify(mWifiNative).getConnectionCapabilities(any());
1344         verify(mThroughputPredictor).predictMaxTxThroughput(any());
1345         verify(mWifiMetrics).setConnectionMaxSupportedLinkSpeedMbps(WIFI_IFACE_NAME, 90, 80);
1346         assertEquals(90, wifiInfo.getMaxSupportedTxLinkSpeedMbps());
1347         verify(mWifiMetrics).noteFirstL3ConnectionAfterBoot(true);
1348         validateConnectionInfo();
1349     }
1350 
connectWithIpProvisionTimeout(boolean lateDhcpResponse)1351     private void connectWithIpProvisionTimeout(boolean lateDhcpResponse) throws Exception {
1352         mResources.setBoolean(R.bool.config_wifiRemainConnectedAfterIpProvisionTimeout, true);
1353         assertNull(mCmi.getConnectingWifiConfiguration());
1354         assertNull(mCmi.getConnectedWifiConfiguration());
1355 
1356         triggerConnect();
1357         validateConnectionInfo();
1358 
1359         assertNotNull(mCmi.getConnectingWifiConfiguration());
1360         assertNull(mCmi.getConnectedWifiConfiguration());
1361 
1362         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID);
1363         config.carrierId = CARRIER_ID_1;
1364         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1365                 .thenReturn(mScanDetailCache);
1366 
1367         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1368                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1369         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1370                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1371         ScanResult scanResult = new ScanResult.Builder(WifiSsid.fromUtf8Text(sFilsSsid),
1372                 TEST_BSSID_STR)
1373                 .setHessid(1245)
1374                 .setRssi(-78)
1375                 .setFrequency(2450)
1376                 .setTsf(1025)
1377                 .setDistanceCm(22)
1378                 .setDistanceSdCm(33)
1379                 .setIs80211McRTTResponder(true)
1380                 .build();
1381         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
1382                 sFilsSsid.getBytes(StandardCharsets.UTF_8));
1383         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
1384         when(mScanRequestProxy.getScanResult(eq(TEST_BSSID_STR))).thenReturn(scanResult);
1385 
1386         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1387                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
1388                         SupplicantState.ASSOCIATED));
1389         mLooper.dispatchAll();
1390         validateConnectionInfo();
1391 
1392         WifiSsid wifiSsid = WifiSsid.fromBytes(
1393                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1394         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1395                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1396         mLooper.dispatchAll();
1397         // WifiInfo should be updated if it is primary
1398         validateConnectionInfo();
1399 
1400         verify(mWifiMetrics).noteFirstL2ConnectionAfterBoot(true);
1401 
1402         // L2 connected, but not L3 connected yet. So, still "Connecting"...
1403         assertNotNull(mCmi.getConnectingWifiConfiguration());
1404         assertNull(mCmi.getConnectedWifiConfiguration());
1405 
1406         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1407                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
1408                         SupplicantState.COMPLETED));
1409         mLooper.dispatchAll();
1410         validateConnectionInfo();
1411 
1412         assertEquals("L3ProvisioningState", getCurrentState().getName());
1413         verifyNetworkStateChangedBroadcast(times(1),
1414                 new NetworkStateChangedIntentMatcher(CONNECTING));
1415         verifyNetworkStateChangedBroadcast(times(1),
1416                 new NetworkStateChangedIntentMatcher(OBTAINING_IPADDR));
1417         mLooper.dispatchAll();
1418 
1419         mLooper.moveTimeForward(mCmi.WAIT_FOR_L3_PROVISIONING_TIMEOUT_MS);
1420         mLooper.dispatchAll();
1421         verify(mWifiConnectivityManager).handleConnectionStateChanged(mClientModeManager,
1422                 WifiConnectivityManager.WIFI_STATE_CONNECTED);
1423         assertTrue(mCmi.isIpProvisioningTimedOut());
1424         verify(mWifiConfigManager).setIpProvisioningTimedOut(eq(FRAMEWORK_NETWORK_ID), eq(true));
1425 
1426         if (!lateDhcpResponse) {
1427             return;
1428         }
1429 
1430         // Simulate the scenario of a late response of the dhcp after the network is labeled a local
1431         // only due to ip provisioning timeout.
1432 
1433         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
1434         dhcpResults.baseConfiguration = new StaticIpConfiguration();
1435         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
1436         dhcpResults.baseConfiguration.ipAddress =
1437                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
1438         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
1439         dhcpResults.leaseDuration = 3600;
1440 
1441         injectDhcpSuccess(dhcpResults);
1442         mLooper.dispatchAll();
1443         assertNull(mCmi.getConnectingWifiConfiguration());
1444         assertNotNull(mCmi.getConnectedWifiConfiguration());
1445 
1446         // Verify WifiMetrics logging for metered metrics based on DHCP results
1447         verify(mWifiMetrics).addMeteredStat(any(), anyBoolean());
1448         WifiInfo wifiInfo = mWifiInfo;
1449         assertNotNull(wifiInfo);
1450         assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID());
1451         assertEquals(sFreq, wifiInfo.getFrequency());
1452         assertEquals(TEST_WIFI_SSID, wifiInfo.getWifiSsid());
1453         assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, wifiInfo.getMacAddress());
1454         assertEquals(mConnectedNetwork.getDefaultSecurityParams().getSecurityType(),
1455                 mWifiInfo.getCurrentSecurityType());
1456 
1457         if (wifiInfo.isPasspointAp()) {
1458             assertEquals(wifiInfo.getPasspointProviderFriendlyName(),
1459                     WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME);
1460         } else {
1461             assertNull(wifiInfo.getPasspointProviderFriendlyName());
1462         }
1463         assertEquals(Arrays.asList(scanResult.informationElements),
1464                 wifiInfo.getInformationElements());
1465         assertNotNull(wifiInfo.getNetworkKey());
1466         expectRegisterNetworkAgent((na) -> {
1467             if (!mConnectedNetwork.carrierMerged) {
1468                 assertNull(na.subscriberId);
1469             }
1470         }, (nc) -> {
1471                 if (SdkLevel.isAtLeastS()) {
1472                     WifiInfo wifiInfoFromTi = (WifiInfo) nc.getTransportInfo();
1473                     assertEquals(TEST_BSSID_STR, wifiInfoFromTi.getBSSID());
1474                     assertEquals(sFreq, wifiInfoFromTi.getFrequency());
1475                     assertEquals(TEST_WIFI_SSID, wifiInfoFromTi.getWifiSsid());
1476                     if (wifiInfo.isPasspointAp()) {
1477                         assertEquals(wifiInfoFromTi.getPasspointProviderFriendlyName(),
1478                                 WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME);
1479                     } else {
1480                         assertNull(wifiInfoFromTi.getPasspointProviderFriendlyName());
1481                     }
1482                 }
1483             });
1484 
1485         assertFalse(mCmi.isIpProvisioningTimedOut());
1486         verify(mWifiConfigManager).setIpProvisioningTimedOut(eq(FRAMEWORK_NETWORK_ID), eq(false));
1487 
1488         // Ensure the connection stats for the network is updated.
1489         verify(mWifiConfigManager).updateRandomizedMacExpireTime(any(), anyLong());
1490         verifyNetworkStateChangedBroadcast(atLeast(1),
1491                 new NetworkStateChangedIntentMatcher(CONNECTED));
1492 
1493         //Ensure that the network is registered
1494         verify(mWifiConfigManager).updateNetworkAfterConnect(
1495                 eq(FRAMEWORK_NETWORK_ID), anyBoolean(), anyBoolean(), anyInt());
1496         verify(mWifiConnectivityManager, times(2)).handleConnectionStateChanged(mClientModeManager,
1497                 WifiConnectivityManager.WIFI_STATE_CONNECTED);
1498 
1499 
1500         // Anonymous Identity is not set.
1501         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1502         verify(mWifiStateTracker).updateState(WIFI_IFACE_NAME, WifiStateTracker.CONNECTED);
1503         assertEquals("L3ConnectedState", getCurrentState().getName());
1504         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionSuccess();
1505         verify(mWifiLockManager).updateWifiClientConnected(mClientModeManager, true);
1506         verify(mWifiNative).getConnectionCapabilities(any());
1507         verify(mThroughputPredictor).predictMaxTxThroughput(any());
1508         verify(mWifiMetrics).setConnectionMaxSupportedLinkSpeedMbps(WIFI_IFACE_NAME, 90, 80);
1509         assertEquals(90, wifiInfo.getMaxSupportedTxLinkSpeedMbps());
1510         verify(mWifiMetrics).noteFirstL3ConnectionAfterBoot(true);
1511         validateConnectionInfo();
1512 
1513     }
1514 
1515     @Test
testConnectWithIpProvisioningTimeout()1516     public void testConnectWithIpProvisioningTimeout() throws Exception {
1517         connectWithIpProvisionTimeout(false);
1518     }
1519 
1520     @Test
testConnectWithIpProvisioningTimeoutLateDhcpResponse()1521     public void testConnectWithIpProvisioningTimeoutLateDhcpResponse() throws Exception {
1522         connectWithIpProvisionTimeout(true);
1523     }
1524 
verifyNetworkStateChangedBroadcast(VerificationMode mode, ArgumentCaptor<Intent> intentCaptor)1525     private void verifyNetworkStateChangedBroadcast(VerificationMode mode,
1526             ArgumentCaptor<Intent> intentCaptor) {
1527         if (SdkLevel.isAtLeastU()) {
1528             verify(mUserAllContext, mode).sendStickyBroadcast(intentCaptor.capture(), any());
1529         } else {
1530             verify(mContext, mode).sendStickyBroadcastAsUser(intentCaptor.capture(), any());
1531         }
1532     }
1533 
verifyNetworkStateChangedBroadcast(VerificationMode mode, ArgumentMatcher<Intent> intentMatcher)1534     private void verifyNetworkStateChangedBroadcast(VerificationMode mode,
1535             ArgumentMatcher<Intent> intentMatcher) {
1536         if (SdkLevel.isAtLeastU()) {
1537             verify(mUserAllContext, mode).sendStickyBroadcast(argThat(intentMatcher), any());
1538         } else {
1539             verify(mContext, mode).sendStickyBroadcastAsUser(argThat(intentMatcher), any());
1540         }
1541     }
1542 
inOrderVerifyNetworkStateChangedBroadcasts( ArgumentMatcher<Intent>.... intentMatchers)1543     private void inOrderVerifyNetworkStateChangedBroadcasts(
1544             ArgumentMatcher<Intent>... intentMatchers) {
1545         final InOrder inOrder = SdkLevel.isAtLeastU()
1546                 ? inOrder(mUserAllContext) : inOrder(mContext);
1547         for (ArgumentMatcher<Intent> intentMatcher : intentMatchers) {
1548             if (SdkLevel.isAtLeastU()) {
1549                 inOrder.verify(mUserAllContext).sendStickyBroadcast(argThat(intentMatcher), any());
1550             } else {
1551                 inOrder.verify(mContext).sendStickyBroadcastAsUser(argThat(intentMatcher), any());
1552             }
1553         }
1554     }
1555 
setupEapSimConnection()1556     private void setupEapSimConnection() throws Exception {
1557         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1558                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1559         mConnectedNetwork.carrierId = CARRIER_ID_1;
1560         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
1561                 .thenReturn(DATA_SUBID);
1562         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
1563         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1564 
1565         triggerConnect();
1566 
1567         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1568                 .thenReturn(mScanDetailCache);
1569         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1570                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1571         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1572                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1573 
1574         WifiSsid wifiSsid = WifiSsid.fromBytes(
1575                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1576         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1577                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1578         mLooper.dispatchAll();
1579         verify(mEapFailureNotifier).dismissEapFailureNotification(mConnectedNetwork.SSID);
1580         assertEquals("L3ProvisioningState", getCurrentState().getName());
1581     }
1582 
setupCarrierConnectionNotSimBased()1583     private void setupCarrierConnectionNotSimBased() throws Exception {
1584         mConnectedNetwork.carrierId = CARRIER_ID_1;
1585         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
1586                 .thenReturn(DATA_SUBID);
1587         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
1588 
1589         triggerConnect();
1590 
1591         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1592                 .thenReturn(mScanDetailCache);
1593         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1594                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1595         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1596                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1597 
1598         WifiSsid wifiSsid = WifiSsid.fromBytes(
1599                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1600         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1601                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1602         mLooper.dispatchAll();
1603         assertEquals("L3ProvisioningState", getCurrentState().getName());
1604     }
1605 
1606     @Test
testUpdatingOobPseudonymToSupplicant()1607     public void testUpdatingOobPseudonymToSupplicant() throws Exception {
1608         when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true);
1609         when(mDeviceConfigFacade.isOobPseudonymEnabled()).thenReturn(true);
1610 
1611         ArgumentCaptor<WifiPseudonymManager.PseudonymUpdatingListener> listenerCaptor =
1612                 ArgumentCaptor.forClass(WifiPseudonymManager.PseudonymUpdatingListener.class);
1613         setupEapSimConnection();
1614         verify(mWifiPseudonymManager).registerPseudonymUpdatingListener(listenerCaptor.capture());
1615         String expectedPseudonym = "abc-123";
1616         String expectedDecoratedPseudonym = "abc-123@wlan.mnc456.mcc123.3gppnetwork.org";
1617         when(mWifiCarrierInfoManager.decoratePseudonymWith3GppRealm(any(), eq(expectedPseudonym)))
1618                 .thenReturn(expectedDecoratedPseudonym);
1619         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
1620         listenerCaptor.getValue().onUpdated(CARRIER_ID_1, expectedPseudonym);
1621         mLooper.dispatchAll();
1622 
1623         verify(mWifiNative).setEapAnonymousIdentity(
1624                 anyString(), eq(expectedDecoratedPseudonym), eq(true));
1625 
1626         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
1627                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false));
1628         mLooper.dispatchAll();
1629 
1630         assertEquals("DisconnectedState", getCurrentState().getName());
1631         verify(mWifiPseudonymManager)
1632                 .unregisterPseudonymUpdatingListener(eq(listenerCaptor.getValue()));
1633     }
1634 
1635     @Test
testNotUpdatingOobPseudonymToSupplicant()1636     public void testNotUpdatingOobPseudonymToSupplicant() throws Exception {
1637         when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true);
1638         when(mDeviceConfigFacade.isOobPseudonymEnabled()).thenReturn(true);
1639 
1640         ArgumentCaptor<WifiPseudonymManager.PseudonymUpdatingListener> listenerCaptor =
1641                 ArgumentCaptor.forClass(WifiPseudonymManager.PseudonymUpdatingListener.class);
1642         setupEapSimConnection();
1643         verify(mWifiPseudonymManager).registerPseudonymUpdatingListener(listenerCaptor.capture());
1644         String expectedPseudonym = "abc-123";
1645         String expectedDecoratedPseudonym = "abc-123@wlan.mnc456.mcc123.3gppnetwork.org";
1646         when(mWifiCarrierInfoManager.decoratePseudonymWith3GppRealm(any(), eq(expectedPseudonym)))
1647                 .thenReturn(expectedDecoratedPseudonym);
1648         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(false);
1649         listenerCaptor.getValue().onUpdated(CARRIER_ID_1, expectedPseudonym);
1650         mLooper.dispatchAll();
1651 
1652         verify(mWifiNative, never()).setEapAnonymousIdentity(
1653                 anyString(), anyString(), anyBoolean());
1654 
1655         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
1656                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false));
1657         mLooper.dispatchAll();
1658 
1659         assertEquals("DisconnectedState", getCurrentState().getName());
1660         verify(mWifiPseudonymManager)
1661                 .unregisterPseudonymUpdatingListener(eq(listenerCaptor.getValue()));
1662     }
1663 
1664     /**
1665      * Test when a roam occurs simultaneously with another connection attempt.
1666      * The roam's NETWORK_CONNECTION_EVENT should be ignored, only the new network's
1667      * NETWORK_CONNECTION_EVENT should be acted upon.
1668      */
1669     @Test
roamRaceWithConnect()1670     public void roamRaceWithConnect() throws Exception {
1671         connect();
1672 
1673         initializeAndAddNetworkAndVerifySuccess();
1674 
1675         // connect to new network
1676         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
1677         config.networkId = OTHER_NETWORK_ID;
1678         setupAndStartConnectSequence(config);
1679 
1680         // in L2ConnectingState
1681         assertEquals("L2ConnectingState", getCurrentState().getName());
1682 
1683         // send NETWORK_CONNECTION_EVENT for previous network ID
1684         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1685                 new NetworkConnectionEventInfo(
1686                         FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
1687         mLooper.dispatchAll();
1688 
1689         // should ignore it, stay in L2ConnectingState
1690         assertEquals("L2ConnectingState", getCurrentState().getName());
1691 
1692         // send expected new network SSID
1693         WifiSsid wifiSsid = WifiSsid.fromBytes(
1694                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(config.SSID)));
1695         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1696                 new NetworkConnectionEventInfo(
1697                         OTHER_NETWORK_ID, wifiSsid, TEST_BSSID_STR1, false, null));
1698         mLooper.dispatchAll();
1699 
1700         // then move to next state
1701         assertEquals("L3ProvisioningState", getCurrentState().getName());
1702     }
1703 
1704     @Test
testSimAuthRequestIsHandledWhileAlreadyConnectedSuccess()1705     public void testSimAuthRequestIsHandledWhileAlreadyConnectedSuccess() throws Exception {
1706         connect();
1707 
1708         WifiCarrierInfoManager.SimAuthRequestData requestData =
1709                 new WifiCarrierInfoManager.SimAuthRequestData();
1710         requestData.protocol = WifiEnterpriseConfig.Eap.SIM;
1711         requestData.networkId = FRAMEWORK_NETWORK_ID;
1712         String testSimAuthResponse = "TEST_SIM_AUTH_RESPONSE";
1713         when(mWifiCarrierInfoManager.getGsmSimAuthResponse(any(), any()))
1714                 .thenReturn(testSimAuthResponse);
1715         mCmi.sendMessage(WifiMonitor.SUP_REQUEST_SIM_AUTH, requestData);
1716         mLooper.dispatchAll();
1717 
1718         // Expect success
1719         verify(mWifiNative).simAuthResponse(WIFI_IFACE_NAME, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH,
1720                 testSimAuthResponse);
1721     }
1722 
1723     @Test
testSimAuthRequestIsHandledWhileAlreadyConnectedFail()1724     public void testSimAuthRequestIsHandledWhileAlreadyConnectedFail() throws Exception {
1725         connect();
1726 
1727         WifiCarrierInfoManager.SimAuthRequestData requestData =
1728                 new WifiCarrierInfoManager.SimAuthRequestData();
1729         requestData.protocol = WifiEnterpriseConfig.Eap.SIM;
1730         requestData.networkId = FRAMEWORK_NETWORK_ID;
1731         // Mock WifiCarrierInfoManager to return null so that sim auth fails.
1732         when(mWifiCarrierInfoManager.getGsmSimAuthResponse(any(), any())).thenReturn(null);
1733         mCmi.sendMessage(WifiMonitor.SUP_REQUEST_SIM_AUTH, requestData);
1734         mLooper.dispatchAll();
1735 
1736         // Expect failure
1737         verify(mWifiNative).simAuthFailedResponse(WIFI_IFACE_NAME);
1738     }
1739 
1740     /**
1741      * When the SIM card was removed, if the current wifi connection is not using it, the connection
1742      * should be kept.
1743      */
1744     @Test
testResetSimWhenNonConnectedSimRemoved()1745     public void testResetSimWhenNonConnectedSimRemoved() throws Exception {
1746         setupEapSimConnection();
1747         doReturn(true).when(mWifiCarrierInfoManager).isSimReady(eq(DATA_SUBID));
1748         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1749                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
1750         mLooper.dispatchAll();
1751 
1752         verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any());
1753         assertEquals("L3ProvisioningState", getCurrentState().getName());
1754     }
1755 
1756     /**
1757      * When the SIM card was removed, if the current wifi connection is using it, the connection
1758      * should be disconnected, otherwise, the connection shouldn't be impacted.
1759      */
1760     @Test
testResetSimWhenConnectedSimRemoved()1761     public void testResetSimWhenConnectedSimRemoved() throws Exception {
1762         when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true);
1763         setupEapSimConnection();
1764         doReturn(false).when(mWifiCarrierInfoManager).isSimReady(eq(DATA_SUBID));
1765         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1766                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
1767         mLooper.dispatchAll();
1768 
1769         verify(mSimRequiredNotifier).showSimRequiredNotification(any(), any());
1770         verify(mWifiNative, times(2)).removeAllNetworks(WIFI_IFACE_NAME);
1771         verify(mWifiMetrics).startConnectionEvent(
1772                 anyString(), any(), anyString(), anyInt(), eq(true), anyInt(), anyInt());
1773     }
1774 
1775     /**
1776      * When the SIM card was removed, if the current wifi connection is using it, the connection
1777      * should be disconnected, otherwise, the connection shouldn't be impacted.
1778      */
1779     @Test
testResetSimWhenConnectedSimRemovedAfterNetworkRemoval()1780     public void testResetSimWhenConnectedSimRemovedAfterNetworkRemoval() throws Exception {
1781         setupEapSimConnection();
1782         doReturn(false).when(mWifiCarrierInfoManager).isSimReady(eq(DATA_SUBID));
1783         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
1784         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1785                 ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
1786         mLooper.dispatchAll();
1787 
1788         verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any());
1789         assertEquals("L3ProvisioningState", getCurrentState().getName());
1790     }
1791 
1792     /**
1793      * When the default data SIM is changed, if the current wifi connection is carrier wifi,
1794      * the connection should be disconnected.
1795      */
1796     @Test
testResetSimWhenDefaultDataSimChanged()1797     public void testResetSimWhenDefaultDataSimChanged() throws Exception {
1798         setupEapSimConnection();
1799         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1800                 ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED);
1801         mLooper.dispatchAll();
1802 
1803         verify(mWifiNative, times(2)).removeAllNetworks(WIFI_IFACE_NAME);
1804         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
1805                 eq(StaEvent.DISCONNECT_RESET_SIM_NETWORKS));
1806         verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), anyString());
1807     }
1808 
1809     /**
1810      * When the default data SIM is changed, if the current wifi connection is carrier wifi,
1811      * the connection should be disconnected, and if the network is not SIM-based, no notification
1812      * should be send
1813      */
1814     @Test
testDefaultDataSimChangedNotSimBased()1815     public void testDefaultDataSimChangedNotSimBased() throws Exception {
1816         setupCarrierConnectionNotSimBased();
1817         doReturn(false).when(mWifiCarrierInfoManager).isSimReady(eq(DATA_SUBID));
1818         mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
1819                 ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED);
1820         mLooper.dispatchAll();
1821 
1822         verify(mWifiNative, times(2)).removeAllNetworks(WIFI_IFACE_NAME);
1823         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
1824                 eq(StaEvent.DISCONNECT_RESET_SIM_NETWORKS));
1825         verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), anyString());
1826     }
1827 
1828     /**
1829      * Tests anonymous identity is set again whenever a connection is established for the carrier
1830      * that supports encrypted IMSI and anonymous identity and no real pseudonym was provided.
1831      */
1832     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedNoPseudonym()1833     public void testSetAnonymousIdentityWhenConnectionIsEstablishedNoPseudonym() throws Exception {
1834         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1835                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1836         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1837         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
1838 
1839         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
1840                 .thenReturn(DATA_SUBID);
1841         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
1842         when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
1843         when(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(any()))
1844                 .thenReturn(expectedAnonymousIdentity);
1845 
1846         // Initial value should be "not set"
1847         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1848 
1849         triggerConnect();
1850 
1851         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1852         assertEquals(expectedAnonymousIdentity,
1853                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1854 
1855         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1856                 .thenReturn(mScanDetailCache);
1857         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1858                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1859         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1860                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1861         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1862                 .thenReturn(expectedAnonymousIdentity);
1863 
1864         WifiSsid wifiSsid = WifiSsid.fromBytes(
1865                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1866         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1867                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1868         mLooper.dispatchAll();
1869 
1870         verify(mWifiNative).getEapAnonymousIdentity(any());
1871 
1872         // Post connection value should remain "not set"
1873         assertEquals("", mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1874         // verify that WifiConfigManager#addOrUpdateNetwork() was called to clear any previously
1875         // stored pseudonym. i.e. to enable Encrypted IMSI for subsequent connections.
1876         // Note: This test will fail if future logic will have additional conditions that would
1877         // trigger "add or update network" operation. The test needs to be updated to account for
1878         // this change.
1879         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1880     }
1881 
1882     /**
1883      * Tests anonymous identity is set again whenever a connection is established for the carrier
1884      * that supports encrypted IMSI and anonymous identity but real pseudonym was provided for
1885      * subsequent connections.
1886      */
1887     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonym()1888     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonym()
1889             throws Exception {
1890         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1891                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1892         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1893         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
1894         String pseudonym = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org";
1895 
1896         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
1897                 .thenReturn(DATA_SUBID);
1898         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
1899         when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
1900         when(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(any()))
1901                 .thenReturn(expectedAnonymousIdentity);
1902 
1903         triggerConnect();
1904 
1905         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1906         assertEquals(expectedAnonymousIdentity,
1907                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1908 
1909         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1910                 .thenReturn(mScanDetailCache);
1911         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1912                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1913         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1914                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1915         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1916                 .thenReturn(pseudonym);
1917         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
1918 
1919         WifiSsid wifiSsid = WifiSsid.fromBytes(
1920                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1921         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1922                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1923         mLooper.dispatchAll();
1924 
1925         verify(mWifiNative).getEapAnonymousIdentity(any());
1926         // No decorated pseudonum, only update the cached data.
1927         verify(mWifiNative).setEapAnonymousIdentity(any(), eq(pseudonym), eq(false));
1928         assertEquals(pseudonym,
1929                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1930         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
1931         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
1932         // pseudonym usage in all subsequent connections.
1933         // Note: This test will fail if future logic will have additional conditions that would
1934         // trigger "add or update network" operation. The test needs to be updated to account for
1935         // this change.
1936         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1937     }
1938 
1939     /**
1940      * Tests anonymous identity is set again whenever a connection is established for the carrier
1941      * that supports encrypted IMSI and anonymous identity but real but not decorated pseudonym was
1942      * provided for subsequent connections.
1943      */
1944     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym()1945     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithNonDecoratedPseudonym()
1946             throws Exception {
1947         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
1948                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
1949         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
1950         String pseudonym = "83bcca9384fca";
1951         String realm = "wlan.mnc456.mcc123.3gppnetwork.org";
1952         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
1953 
1954         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
1955                 .thenReturn(DATA_SUBID);
1956         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
1957         when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
1958         when(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(any()))
1959                 .thenReturn(expectedAnonymousIdentity);
1960         doAnswer(invocation -> { return invocation.getArgument(1) + "@" + realm; })
1961                 .when(mWifiCarrierInfoManager).decoratePseudonymWith3GppRealm(any(), anyString());
1962         triggerConnect();
1963 
1964         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
1965         assertEquals(expectedAnonymousIdentity,
1966                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1967 
1968         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
1969                 .thenReturn(mScanDetailCache);
1970         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
1971                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
1972         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
1973                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
1974         when(mWifiNative.getEapAnonymousIdentity(anyString()))
1975                 .thenReturn(pseudonym);
1976         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
1977 
1978         WifiSsid wifiSsid = WifiSsid.fromBytes(
1979                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
1980         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
1981                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
1982         mLooper.dispatchAll();
1983 
1984         verify(mWifiNative).getEapAnonymousIdentity(any());
1985         verify(mWifiNative).setEapAnonymousIdentity(any(), eq(pseudonym + "@" + realm),
1986                 eq(true));
1987         assertEquals(pseudonym + "@" + realm,
1988                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
1989         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
1990         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
1991         // pseudonym usage in all subsequent connections.
1992         // Note: This test will fail if future logic will have additional conditions that would
1993         // trigger "add or update network" operation. The test needs to be updated to account for
1994         // this change.
1995         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
1996     }
1997 
1998     /**
1999      * Tests anonymous identity will be set to suggestion network.
2000      */
2001     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonymForSuggestion()2002     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonymForSuggestion()
2003             throws Exception {
2004         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
2005                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
2006         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
2007         mConnectedNetwork.fromWifiNetworkSuggestion = true;
2008         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
2009         String pseudonym = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org";
2010 
2011         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
2012                 .thenReturn(DATA_SUBID);
2013         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
2014         when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
2015         when(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(any()))
2016                 .thenReturn(expectedAnonymousIdentity);
2017 
2018         triggerConnect();
2019 
2020         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
2021         assertEquals(expectedAnonymousIdentity,
2022                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2023 
2024         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2025                 .thenReturn(mScanDetailCache);
2026         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
2027                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
2028         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
2029                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
2030         when(mWifiNative.getEapAnonymousIdentity(anyString()))
2031                 .thenReturn(pseudonym);
2032         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
2033 
2034         WifiSsid wifiSsid = WifiSsid.fromBytes(
2035                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
2036         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2037                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
2038         mLooper.dispatchAll();
2039 
2040         verify(mWifiNative).getEapAnonymousIdentity(any());
2041         // No decorated pseudonum, only update the cached data.
2042         verify(mWifiNative).setEapAnonymousIdentity(any(), eq(pseudonym), eq(false));
2043         assertEquals(pseudonym,
2044                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2045         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
2046         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
2047         // pseudonym usage in all subsequent connections.
2048         // Note: This test will fail if future logic will have additional conditions that would
2049         // trigger "add or update network" operation. The test needs to be updated to account for
2050         // this change.
2051         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
2052         verify(mWifiNetworkSuggestionsManager).setAnonymousIdentity(any());
2053     }
2054 
2055     /**
2056      * For EAP SIM network, the In-band pseudonym from supplicant should override the OOB
2057      * pseudonym if the OOB Pseudonym feature is enabled.
2058      */
2059     @Test
testUpdatePseudonymAsInBandPseudonymWhenConnectionIsEstablished()2060     public void testUpdatePseudonymAsInBandPseudonymWhenConnectionIsEstablished()
2061             throws Exception {
2062         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
2063                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
2064         String initialOobPseudonym = "1234abcg@wlan.mnc456.mcc123.3gppnetwork.org";
2065         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity(initialOobPseudonym);
2066         mConnectedNetwork.fromWifiNetworkSuggestion = true;
2067         String pseudonymFromSupplicant = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org";
2068 
2069         when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true);
2070         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
2071                 .thenReturn(DATA_SUBID);
2072         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
2073 
2074         triggerConnect();
2075 
2076         // CMD_START_CONNECT doesn't change the anonymous identity.
2077         assertEquals(initialOobPseudonym,
2078                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2079 
2080         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2081                 .thenReturn(mScanDetailCache);
2082         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
2083                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
2084         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
2085                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
2086         when(mWifiNative.getEapAnonymousIdentity(anyString()))
2087                 .thenReturn(pseudonymFromSupplicant);
2088         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
2089 
2090         WifiSsid wifiSsid = WifiSsid.fromBytes(
2091                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
2092         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2093                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
2094         mLooper.dispatchAll();
2095 
2096         verify(mWifiNative).getEapAnonymousIdentity(any());
2097         // No decorated pseudonum, only update the cached data.
2098         verify(mWifiNative).setEapAnonymousIdentity(any(), eq(pseudonymFromSupplicant),
2099                 eq(false));
2100         verify(mWifiPseudonymManager).setInBandPseudonym(anyInt(), eq(pseudonymFromSupplicant));
2101         assertEquals(pseudonymFromSupplicant,
2102                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2103     }
2104 
2105     /**
2106      * Tests anonymous identity will be set to passpoint network.
2107      */
2108     @Test
testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonymForPasspoint()2109     public void testSetAnonymousIdentityWhenConnectionIsEstablishedWithPseudonymForPasspoint()
2110             throws Exception {
2111         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
2112                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
2113         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
2114         mConnectedNetwork.FQDN = WifiConfigurationTestUtil.TEST_FQDN;
2115         mConnectedNetwork.providerFriendlyName =
2116                 WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
2117         mConnectedNetwork.setPasspointUniqueId(WifiConfigurationTestUtil.TEST_FQDN + "_"
2118                 + WifiConfigurationTestUtil.TEST_FQDN.hashCode());
2119         String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org";
2120         String pseudonym = "83bcca9384fca@wlan.mnc456.mcc123.3gppnetwork.org";
2121 
2122         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
2123                 .thenReturn(DATA_SUBID);
2124         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
2125         when(mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(anyInt())).thenReturn(true);
2126         when(mWifiCarrierInfoManager.getAnonymousIdentityWith3GppRealm(any()))
2127                 .thenReturn(expectedAnonymousIdentity);
2128 
2129         triggerConnect();
2130 
2131         // CMD_START_CONNECT should have set anonymousIdentity to anonymous@<realm>
2132         assertEquals(expectedAnonymousIdentity,
2133                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2134 
2135         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2136                 .thenReturn(mScanDetailCache);
2137         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
2138                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
2139         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
2140                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
2141         when(mWifiNative.getEapAnonymousIdentity(anyString()))
2142                 .thenReturn(pseudonym);
2143         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(1)).thenReturn(true);
2144 
2145         WifiSsid wifiSsid = WifiSsid.fromBytes(
2146                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
2147         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2148                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
2149         mLooper.dispatchAll();
2150 
2151         verify(mWifiNative).getEapAnonymousIdentity(any());
2152         // No decorated pseudonum, only update the cached data.
2153         verify(mWifiNative).setEapAnonymousIdentity(any(), eq(pseudonym), eq(false));
2154         assertEquals(pseudonym,
2155                 mConnectedNetwork.enterpriseConfig.getAnonymousIdentity());
2156         // Verify that WifiConfigManager#addOrUpdateNetwork() was called if there we received a
2157         // real pseudonym to be stored. i.e. Encrypted IMSI will be used once, followed by
2158         // pseudonym usage in all subsequent connections.
2159         // Note: This test will fail if future logic will have additional conditions that would
2160         // trigger "add or update network" operation. The test needs to be updated to account for
2161         // this change.
2162         verify(mWifiConfigManager).addOrUpdateNetwork(any(), anyInt());
2163         verify(mPasspointManager).setAnonymousIdentity(any());
2164     }
2165     /**
2166      * Tests the Passpoint information is set in WifiInfo for Passpoint AP connection.
2167      */
2168     @Test
connectPasspointAp()2169     public void connectPasspointAp() throws Exception {
2170         WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork());
2171         config.SSID = TEST_WIFI_SSID.toString();
2172         config.BSSID = TEST_BSSID_STR;
2173         config.networkId = FRAMEWORK_NETWORK_ID;
2174         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
2175         config.roamingConsortiumIds = TEST_RCOI_ARRAY;
2176         when(mPasspointManager.getSelectedRcoiForNetwork(eq(config.getPasspointUniqueId()),
2177                 eq(config.SSID))).thenReturn(TEST_MATCHED_RCOI);
2178         setupAndStartConnectSequence(config);
2179         validateSuccessfulConnectSequence(config);
2180         assertEquals(TEST_MATCHED_RCOI, config.enterpriseConfig.getSelectedRcoi());
2181 
2182         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2183                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2184                         SupplicantState.ASSOCIATING));
2185         mLooper.dispatchAll();
2186 
2187         WifiInfo wifiInfo = mWifiInfo;
2188         assertNotNull(wifiInfo);
2189         assertEquals(WifiConfigurationTestUtil.TEST_FQDN, wifiInfo.getPasspointFqdn());
2190         assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME,
2191                 wifiInfo.getPasspointProviderFriendlyName());
2192     }
2193 
2194     /**
2195      * Tests that Passpoint fields in WifiInfo are reset when connecting to a non-Passpoint network
2196      * during DisconnectedState.
2197      * @throws Exception
2198      */
2199     @Test
testResetWifiInfoPasspointFields()2200     public void testResetWifiInfoPasspointFields() throws Exception {
2201         WifiConfiguration config = spy(WifiConfigurationTestUtil.createPasspointNetwork());
2202         config.SSID = TEST_WIFI_SSID.toString();
2203         config.BSSID = TEST_BSSID_STR;
2204         config.networkId = PASSPOINT_NETWORK_ID;
2205         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
2206         setupAndStartConnectSequence(config);
2207         validateSuccessfulConnectSequence(config);
2208 
2209         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2210                 new StateChangeResult(PASSPOINT_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2211                         SupplicantState.ASSOCIATING));
2212         mLooper.dispatchAll();
2213 
2214         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2215                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2216                         SupplicantState.ASSOCIATING));
2217         mLooper.dispatchAll();
2218 
2219         WifiInfo wifiInfo = mWifiInfo;
2220         assertNotNull(wifiInfo);
2221         assertNull(wifiInfo.getPasspointFqdn());
2222         assertNull(wifiInfo.getPasspointProviderFriendlyName());
2223     }
2224 
2225     /**
2226      * Tests the OSU information is set in WifiInfo for OSU AP connection.
2227      */
2228     @Test
connectOsuAp()2229     public void connectOsuAp() throws Exception {
2230         WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork());
2231         osuConfig.SSID = TEST_WIFI_SSID.toString();
2232         osuConfig.BSSID = TEST_BSSID_STR;
2233         osuConfig.osu = true;
2234         osuConfig.networkId = FRAMEWORK_NETWORK_ID;
2235         osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
2236         osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
2237         setupAndStartConnectSequence(osuConfig);
2238         validateSuccessfulConnectSequence(osuConfig);
2239 
2240         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2241                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2242                         SupplicantState.ASSOCIATING));
2243         mLooper.dispatchAll();
2244 
2245         WifiInfo wifiInfo = mWifiInfo;
2246         assertNotNull(wifiInfo);
2247         assertTrue(wifiInfo.isOsuAp());
2248         assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME,
2249                 wifiInfo.getPasspointProviderFriendlyName());
2250     }
2251 
2252     /**
2253      * Tests that OSU fields in WifiInfo are reset when connecting to a non-OSU network during
2254      * DisconnectedState.
2255      * @throws Exception
2256      */
2257     @Test
testResetWifiInfoOsuFields()2258     public void testResetWifiInfoOsuFields() throws Exception {
2259         WifiConfiguration osuConfig = spy(WifiConfigurationTestUtil.createEphemeralNetwork());
2260         osuConfig.SSID = TEST_WIFI_SSID.toString();
2261         osuConfig.BSSID = TEST_BSSID_STR;
2262         osuConfig.osu = true;
2263         osuConfig.networkId = PASSPOINT_NETWORK_ID;
2264         osuConfig.providerFriendlyName = WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME;
2265         osuConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
2266         setupAndStartConnectSequence(osuConfig);
2267         validateSuccessfulConnectSequence(osuConfig);
2268 
2269         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2270                 new StateChangeResult(PASSPOINT_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2271                         SupplicantState.ASSOCIATING));
2272         mLooper.dispatchAll();
2273 
2274         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2275                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
2276                         SupplicantState.ASSOCIATING));
2277         mLooper.dispatchAll();
2278 
2279         WifiInfo wifiInfo = mWifiInfo;
2280         assertNotNull(wifiInfo);
2281         assertFalse(wifiInfo.isOsuAp());
2282     }
2283 
2284     /**
2285      * Tests that {@link WifiInfo#getHiddenSsid()} returns {@code true} if we've connected to a
2286      * hidden SSID network.
2287      * @throws Exception
2288      */
2289     @Test
testConnectHiddenSsid()2290     public void testConnectHiddenSsid() throws Exception {
2291         connect();
2292 
2293         // Set the scan detail cache for hidden SSID.
2294         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
2295                 .thenReturn(mScanDetailCache);
2296         ScanDetail hiddenScanDetail = getHiddenScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1);
2297         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR1)).thenReturn(hiddenScanDetail);
2298         when(mScanDetailCache.getScanResult(TEST_BSSID_STR1)).thenReturn(
2299                 hiddenScanDetail.getScanResult());
2300 
2301         mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, TEST_BSSID_STR1);
2302         mLooper.dispatchAll();
2303 
2304         // Hidden SSID scan result should set WifiInfo.getHiddenSsid() to true.
2305         assertTrue(mWifiInfo.getHiddenSSID());
2306 
2307         // Set the scan detail cache for non-hidden SSID.
2308         ScanDetail googleGuestScanDetail =
2309                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq1);
2310         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(googleGuestScanDetail);
2311         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
2312                 googleGuestScanDetail.getScanResult());
2313 
2314         mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, TEST_BSSID_STR);
2315         mLooper.dispatchAll();
2316 
2317         // Non-hidden SSID scan result should set WifiInfo.getHiddenSsid() to false.
2318         assertFalse(mWifiInfo.getHiddenSSID());
2319     }
2320 
2321     /**
2322      * Verify that WifiStateTracker is called if wifi is disabled while connected.
2323      */
2324     @Test
verifyWifiStateTrackerUpdatedWhenDisabled()2325     public void verifyWifiStateTrackerUpdatedWhenDisabled() throws Exception {
2326         connect();
2327 
2328         mCmi.stop();
2329         mLooper.dispatchAll();
2330         verify(mWifiStateTracker).updateState(WIFI_IFACE_NAME, WifiStateTracker.DISCONNECTED);
2331     }
2332 
2333     @Test
testIdleModeChanged_firmwareRoaming()2334     public void testIdleModeChanged_firmwareRoaming() throws Exception {
2335         // verify no-op when either the feature flag is disabled or firmware roaming is not
2336         // supported
2337         when(mWifiGlobals.isDisableFirmwareRoamingInIdleMode()).thenReturn(false);
2338         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
2339         mCmi.onIdleModeChanged(true);
2340         verify(mWifiNative, never()).enableFirmwareRoaming(anyString(), anyInt());
2341         when(mWifiGlobals.isDisableFirmwareRoamingInIdleMode()).thenReturn(true);
2342         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false);
2343         mCmi.onIdleModeChanged(true);
2344         verify(mWifiNative, never()).enableFirmwareRoaming(anyString(), anyInt());
2345 
2346         // Enable both, then verify firmware roaming is not yet disabled when idle mode is entered
2347         // because screen is still on
2348         when(mWifiGlobals.isDisableFirmwareRoamingInIdleMode()).thenReturn(true);
2349         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
2350         mCmi.onIdleModeChanged(true);
2351         verify(mWifiNative, never()).enableFirmwareRoaming(anyString(), anyInt());
2352 
2353         // Verify firmware roaming is now disabled after screen turns off
2354         setScreenState(false);
2355         mLooper.dispatchAll();
2356         verify(mWifiNative).enableFirmwareRoaming(anyString(),
2357                 eq(WifiNative.DISABLE_FIRMWARE_ROAMING));
2358 
2359         // Verify firmware roaming is enabled when idle mode exited
2360         when(mWifiRoamingConfigStore.getRoamingMode(anyString())).thenReturn(
2361                 WifiManager.ROAMING_MODE_NORMAL);
2362         mCmi.onIdleModeChanged(false);
2363         verify(mWifiNative).setRoamingMode(anyString(),
2364                 eq(WifiManager.ROAMING_MODE_NORMAL));
2365     }
2366 
2367     @Test
testIdleModeChanged_firmwareRoamingLocalOnlyCase()2368     public void testIdleModeChanged_firmwareRoamingLocalOnlyCase() throws Exception {
2369         // mock connected network to be local only
2370         connect();
2371         mConnectedNetwork.fromWifiNetworkSpecifier = true;
2372 
2373         // Enable feature, then verify firmware roaming is disabled when idle mode is entered
2374         when(mWifiGlobals.isDisableFirmwareRoamingInIdleMode()).thenReturn(true);
2375         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
2376         mCmi.onIdleModeChanged(true);
2377         setScreenState(false);
2378         mLooper.dispatchAll();
2379         verify(mWifiNative).enableFirmwareRoaming(anyString(),
2380                 eq(WifiNative.DISABLE_FIRMWARE_ROAMING));
2381 
2382         // Verify firmware roaming is not enabled when idle mode exited
2383         mCmi.onIdleModeChanged(false);
2384         verify(mWifiNative, never()).enableFirmwareRoaming(anyString(),
2385                 eq(WifiNative.ENABLE_FIRMWARE_ROAMING));
2386     }
2387 
2388     /**
2389      * Verify that when the primary connects, roaming mode is set
2390      * based on the connected network ssid.
2391      */
2392     @Test
testPerSsidRoamingModePrimary()2393     public void testPerSsidRoamingModePrimary() throws Exception {
2394         when(mWifiRoamingConfigStore.getRoamingMode(TEST_SSID)).thenReturn(
2395                 WifiManager.ROAMING_MODE_NORMAL);
2396         connect();
2397         verify(mWifiRoamingConfigStore).getRoamingMode(TEST_SSID);
2398         verify(mWifiNative).setRoamingMode(anyString(),
2399                 eq(WifiManager.ROAMING_MODE_NORMAL));
2400     }
2401 
2402     /**
2403      * Verify that when the secondary connects, roaming mode is not set.
2404      */
2405     @Test
testPerSsidRoamingModeSecondary()2406     public void testPerSsidRoamingModeSecondary() throws Exception {
2407         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
2408         connect();
2409         verify(mWifiRoamingConfigStore, never()).getRoamingMode(anyString());
2410         verify(mWifiNative, never()).setRoamingMode(anyString(), anyInt());
2411     }
2412 
2413     /**
2414      * Tests the network connection initiation sequence with no network request pending from
2415      * from WifiNetworkFactory when we're already connected to a different network.
2416      * This simulates the connect sequence using the public
2417      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we invoke
2418      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
2419      */
2420     @Test
triggerConnectWithNoNetworkRequestAndAlreadyConnected()2421     public void triggerConnectWithNoNetworkRequestAndAlreadyConnected() throws Exception {
2422         // Simulate the first connection.
2423         connect();
2424 
2425         // Remove the network requests.
2426         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2427         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2428         when(mOemWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2429         when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(false);
2430 
2431         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
2432         config.networkId = FRAMEWORK_NETWORK_ID + 1;
2433         setupAndStartConnectSequence(config);
2434         validateSuccessfulConnectSequence(config);
2435         verify(mWifiPermissionsUtil, atLeastOnce()).checkNetworkSettingsPermission(anyInt());
2436     }
2437 
2438     /**
2439      * Tests the network connection initiation sequence from a non-privileged app with no network
2440      * request pending from from WifiNetworkFactory when we're already connected to a different
2441      * network.
2442      * This simulates the connect sequence using the public
2443      * {@link WifiManager#enableNetwork(int, boolean)} and ensures that we don't invoke
2444      * {@link WifiNative#connectToNetwork(WifiConfiguration)}.
2445      */
2446     @Test
triggerConnectWithNoNetworkRequestAndAlreadyConnectedButNonPrivilegedApp()2447     public void triggerConnectWithNoNetworkRequestAndAlreadyConnectedButNonPrivilegedApp()
2448             throws Exception {
2449         // Simulate the first connection.
2450         connect();
2451 
2452         // Remove the network requests.
2453         when(mWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2454         when(mUntrustedWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2455         when(mOemWifiNetworkFactory.hasConnectionRequests()).thenReturn(false);
2456         when(mMultiInternetManager.hasPendingConnectionRequests()).thenReturn(false);
2457 
2458         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
2459 
2460         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
2461         config.networkId = FRAMEWORK_NETWORK_ID + 1;
2462         setupAndStartConnectSequence(config);
2463         verify(mWifiConnectivityManager).prepareForForcedConnection(eq(config.networkId));
2464         verify(mWifiConfigManager, never())
2465                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
2466         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
2467         // These are called from connectToUserSelectNetwork() and L2ConnectedState::enter()
2468         verify(mWifiPermissionsUtil, times(4)).checkNetworkSettingsPermission(anyInt());
2469     }
2470 
2471     /**
2472      * If caller tries to connect to a network that is already connected, the connection request
2473      * should succeed.
2474      *
2475      * Test: Create and connect to a network, then try to reconnect to the same network. Verify
2476      * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
2477      */
2478     @Test
reconnectToConnectedNetworkWithNetworkId()2479     public void reconnectToConnectedNetworkWithNetworkId() throws Exception {
2480         connect();
2481 
2482         // try to reconnect
2483         IActionListener connectActionListener = mock(IActionListener.class);
2484         mCmi.connectNetwork(
2485                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2486                 new ActionListenerWrapper(connectActionListener),
2487                 Binder.getCallingUid(), OP_PACKAGE_NAME, TEST_ATTRIBUTION_TAG);
2488         mLooper.dispatchAll();
2489         verify(connectActionListener).onSuccess();
2490 
2491         // Verify that we didn't trigger a second connection.
2492         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2493     }
2494 
2495     /**
2496      * If caller tries to connect to a network that is already connected, the connection request
2497      * should succeed.
2498      *
2499      * Test: Create and connect to a network, then try to reconnect to the same network. Verify
2500      * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
2501      */
2502     @Test
reconnectToConnectedNetworkWithConfig()2503     public void reconnectToConnectedNetworkWithConfig() throws Exception {
2504         connect();
2505 
2506         // try to reconnect
2507         IActionListener connectActionListener = mock(IActionListener.class);
2508         int callingUid = Binder.getCallingUid();
2509         mCmi.connectNetwork(
2510                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2511                 new ActionListenerWrapper(connectActionListener),
2512                 callingUid, OP_PACKAGE_NAME, TEST_ATTRIBUTION_TAG);
2513         mLooper.dispatchAll();
2514         verify(connectActionListener).onSuccess();
2515 
2516         // Verify that we didn't trigger a second connection.
2517         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2518     }
2519 
2520     /**
2521      * If caller tries to connect to a network that is already connecting, the connection request
2522      * should succeed.
2523      *
2524      * Test: Create and trigger connect to a network, then try to reconnect to the same network.
2525      * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did not trigger a
2526      * new connection.
2527      */
2528     @Test
reconnectToConnectingNetwork()2529     public void reconnectToConnectingNetwork() throws Exception {
2530         triggerConnect();
2531 
2532         // try to reconnect to the same network (before connection is established).
2533         IActionListener connectActionListener = mock(IActionListener.class);
2534         mCmi.connectNetwork(
2535                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2536                 new ActionListenerWrapper(connectActionListener),
2537                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2538         mLooper.dispatchAll();
2539         verify(connectActionListener).onSuccess();
2540 
2541         // Verify that we didn't trigger a second connection.
2542         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2543     }
2544 
2545     /**
2546      * If caller tries to connect to a network that is already connecting, the connection request
2547      * should succeed.
2548      *
2549      * Test: Create and trigger connect to a network, then try to reconnect to the same network.
2550      * Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED and did trigger a new
2551      * connection.
2552      */
2553     @Test
reconnectToConnectingNetworkWithCredentialChange()2554     public void reconnectToConnectingNetworkWithCredentialChange() throws Exception {
2555         triggerConnect();
2556 
2557         // try to reconnect to the same network with a credential changed (before connection is
2558         // established).
2559         NetworkUpdateResult networkUpdateResult = new NetworkUpdateResult(
2560                 FRAMEWORK_NETWORK_ID,
2561                 STATUS_SUCCESS,
2562                 false /* ip */,
2563                 false /* proxy */,
2564                 true /* credential */,
2565                 false /* isNewNetwork */);
2566         IActionListener connectActionListener = mock(IActionListener.class);
2567         mCmi.connectNetwork(
2568                 networkUpdateResult,
2569                 new ActionListenerWrapper(connectActionListener),
2570                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2571         mLooper.dispatchAll();
2572         verify(connectActionListener).onSuccess();
2573 
2574         // Verify that we triggered a second connection.
2575         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2576     }
2577 
2578     /**
2579      * If caller tries to connect to a network that previously failed connection, the connection
2580      * request should succeed.
2581      *
2582      * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect
2583      * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED
2584      * and did trigger a new * connection.
2585      */
2586     @Test
connectAfterAssociationRejection()2587     public void connectAfterAssociationRejection() throws Exception {
2588         triggerConnect();
2589 
2590         // fail the connection.
2591         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
2592                 new AssocRejectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR,
2593                         ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, false));
2594         mLooper.dispatchAll();
2595 
2596         IActionListener connectActionListener = mock(IActionListener.class);
2597         mCmi.connectNetwork(
2598                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2599                 new ActionListenerWrapper(connectActionListener),
2600                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2601         mLooper.dispatchAll();
2602         verify(connectActionListener).onSuccess();
2603 
2604         // Verify that we triggered a second connection.
2605         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2606     }
2607 
2608     /**
2609      * If caller tries to connect to a network that previously failed connection, the connection
2610      * request should succeed.
2611      *
2612      * Test: Create and trigger connect to a network, then fail the connection. Now try to reconnect
2613      * to the same network. Verify that connection request returns with CONNECT_NETWORK_SUCCEEDED
2614      * and did trigger a new * connection.
2615      */
2616     @Test
connectAfterConnectionFailure()2617     public void connectAfterConnectionFailure() throws Exception {
2618         triggerConnect();
2619 
2620         // fail the connection.
2621         DisconnectEventInfo disconnectEventInfo =
2622                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
2623         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2624         mLooper.dispatchAll();
2625 
2626         IActionListener connectActionListener = mock(IActionListener.class);
2627         mCmi.connectNetwork(
2628                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2629                 new ActionListenerWrapper(connectActionListener),
2630                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2631         mLooper.dispatchAll();
2632         verify(connectActionListener).onSuccess();
2633 
2634         // Verify that we triggered a second connection.
2635         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), any());
2636     }
2637 
2638     /**
2639      * If the interface has been switched to scan, the network disconnection event should clear the
2640      * current network.
2641      * @throws Exception
2642      */
2643     @Test
testNetworkDisconnectAfterInterfaceSwitchedToScan()2644     public void testNetworkDisconnectAfterInterfaceSwitchedToScan() throws Exception {
2645         triggerConnect();
2646         IActionListener connectActionListener = mock(IActionListener.class);
2647         mCmi.connectNetwork(
2648                 new NetworkUpdateResult(FRAMEWORK_NETWORK_ID),
2649                 new ActionListenerWrapper(connectActionListener),
2650                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2651         mLooper.dispatchAll();
2652         verify(connectActionListener).onSuccess();
2653 
2654         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY);
2655         // Disconnection from previous network.
2656         DisconnectEventInfo disconnectEventInfo =
2657                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2658         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2659         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2660                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2661                         SupplicantState.DISCONNECTED));
2662         mLooper.dispatchAll();
2663         verify(mActiveModeWarden).setCurrentNetwork(null);
2664     }
2665 
2666     @Test
testWifiInfoNetworkIdSetInScanningState()2667     public void testWifiInfoNetworkIdSetInScanningState() throws Exception {
2668         triggerConnect();
2669         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, mWifiInfo.getNetworkId());
2670         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2671                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2672                         SupplicantState.SCANNING));
2673         mLooper.dispatchAll();
2674         assertEquals(0, mWifiInfo.getNetworkId());
2675     }
2676 
2677     /**
2678      * If caller tries to connect to a new network while still provisioning the current one,
2679      * the connection attempt should succeed.
2680      */
2681     @Test
connectWhileObtainingIp()2682     public void connectWhileObtainingIp() throws Exception {
2683         initializeAndAddNetworkAndVerifySuccess();
2684 
2685         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
2686 
2687         startConnectSuccess();
2688 
2689         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2690                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
2691         mLooper.dispatchAll();
2692 
2693         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2694                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2695                         SupplicantState.COMPLETED));
2696         mLooper.dispatchAll();
2697 
2698         assertEquals("L3ProvisioningState", getCurrentState().getName());
2699 
2700         // Connect to a different network
2701         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
2702         config.networkId = FRAMEWORK_NETWORK_ID + 1;
2703         setupAndStartConnectSequence(config);
2704         validateSuccessfulConnectSequence(config);
2705 
2706         // Disconnection from previous network.
2707         DisconnectEventInfo disconnectEventInfo =
2708                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2709         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2710         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2711                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2712                         SupplicantState.DISCONNECTED));
2713         mLooper.dispatchAll();
2714 
2715         // Ensure we don't end the new connection event.
2716         verify(mWifiMetrics, never()).endConnectionEvent(
2717                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
2718                 anyInt(), anyInt(), anyInt(), anyInt());
2719         verify(mWifiConnectivityManager).prepareForForcedConnection(FRAMEWORK_NETWORK_ID + 1);
2720     }
2721 
2722     /**
2723      * If there is a network removal while still connecting to it, the connection
2724      * should be aborted.
2725      */
2726     @Test
networkRemovalWhileObtainingIp()2727     public void networkRemovalWhileObtainingIp() throws Exception {
2728         initializeAndAddNetworkAndVerifySuccess();
2729 
2730         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
2731 
2732         startConnectSuccess();
2733 
2734         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2735                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
2736         mLooper.dispatchAll();
2737 
2738         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2739                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2740                         SupplicantState.COMPLETED));
2741         mLooper.dispatchAll();
2742 
2743         assertEquals("L3ProvisioningState", getCurrentState().getName());
2744         reset(mWifiNative);
2745 
2746         // Simulate the target network removal & the disconnect trigger.
2747         WifiConfiguration removedNetwork = new WifiConfiguration();
2748         removedNetwork.networkId = FRAMEWORK_NETWORK_ID;
2749         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
2750                 .getAllValues()) {
2751             listener.onNetworkRemoved(removedNetwork);
2752         }
2753         mLooper.dispatchAll();
2754 
2755         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
2756         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
2757         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
2758                 eq(StaEvent.DISCONNECT_NETWORK_REMOVED));
2759 
2760         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)).thenReturn(null);
2761         DisconnectEventInfo disconnectEventInfo =
2762                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2763         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2764         mLooper.dispatchAll();
2765 
2766         assertEquals("DisconnectedState", getCurrentState().getName());
2767     }
2768 
2769     /**
2770      * Tests that manual connection to a network (from settings app) logs the correct nominator ID.
2771      */
2772     @Test
testManualConnectNominator()2773     public void testManualConnectNominator() throws Exception {
2774         initializeAndAddNetworkAndVerifySuccess();
2775 
2776         WifiConfiguration config = new WifiConfiguration();
2777         config.networkId = TEST_NETWORK_ID;
2778         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
2779 
2780         IActionListener connectActionListener = mock(IActionListener.class);
2781         mCmi.connectNetwork(
2782                 new NetworkUpdateResult(TEST_NETWORK_ID),
2783                 new ActionListenerWrapper(connectActionListener),
2784                 Process.SYSTEM_UID, OP_PACKAGE_NAME, null);
2785         mLooper.dispatchAll();
2786         verify(connectActionListener).onSuccess();
2787 
2788         verify(mWifiMetrics).setNominatorForNetwork(TEST_NETWORK_ID,
2789                 WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
2790     }
2791 
startConnectSuccess()2792     private void startConnectSuccess() throws Exception {
2793         startConnectSuccess(FRAMEWORK_NETWORK_ID);
2794     }
2795 
startConnectSuccess(int networkId)2796     private void startConnectSuccess(int networkId) throws Exception {
2797         IActionListener connectActionListener = mock(IActionListener.class);
2798         mCmi.connectNetwork(
2799                 new NetworkUpdateResult(networkId),
2800                 new ActionListenerWrapper(connectActionListener),
2801                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
2802         mLooper.dispatchAll();
2803         verify(connectActionListener).onSuccess();
2804     }
2805 
2806     @Test
testDhcpFailure()2807     public void testDhcpFailure() throws Exception {
2808         initializeAndAddNetworkAndVerifySuccess();
2809 
2810         startConnectSuccess();
2811 
2812         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2813                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2814                         SupplicantState.ASSOCIATED));
2815         mLooper.dispatchAll();
2816 
2817         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
2818                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
2819         mLooper.dispatchAll();
2820         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
2821 
2822         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
2823                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
2824                         SupplicantState.COMPLETED));
2825         mLooper.dispatchAll();
2826 
2827         assertEquals("L3ProvisioningState", getCurrentState().getName());
2828         injectDhcpFailure();
2829         mLooper.dispatchAll();
2830 
2831         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
2832         // Verify this is not counted as a IP renewal failure
2833         verify(mWifiMetrics, never()).incrementIpRenewalFailure();
2834         // Verifies that WifiLastResortWatchdog be notified
2835         // by DHCP failure
2836         verify(mWifiLastResortWatchdog, times(2)).noteConnectionFailureAndTriggerIfNeeded(
2837                 eq(TEST_SSID), eq(TEST_BSSID_STR),
2838                 eq(WifiLastResortWatchdog.FAILURE_CODE_DHCP), anyBoolean());
2839         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
2840                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_DHCP_FAILURE), anyInt());
2841         verify(mWifiBlocklistMonitor, never()).handleDhcpProvisioningSuccess(
2842                 TEST_BSSID_STR, TEST_SSID);
2843         verify(mWifiBlocklistMonitor, never()).handleNetworkValidationSuccess(
2844                 TEST_BSSID_STR, TEST_SSID);
2845         DisconnectEventInfo disconnectEventInfo =
2846                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 3, true);
2847         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2848         mLooper.dispatchAll();
2849     }
2850 
2851     /**
2852      * Verify that a IP renewal failure is logged when IP provisioning fail in the
2853      * L3ConnectedState.
2854      */
2855     @Test
testDhcpRenewalMetrics()2856     public void testDhcpRenewalMetrics() throws Exception {
2857         connect();
2858         injectDhcpFailure();
2859         mLooper.dispatchAll();
2860 
2861         verify(mWifiMetrics).incrementIpRenewalFailure();
2862     }
2863 
2864     /**
2865      * Verify that the network selection status will be updated with DISABLED_AUTHENTICATION_FAILURE
2866      * when wrong password authentication failure is detected and the network had been
2867      * connected previously.
2868      */
2869     @Test
testWrongPasswordWithPreviouslyConnected()2870     public void testWrongPasswordWithPreviouslyConnected() throws Exception {
2871         initializeAndAddNetworkAndVerifySuccess();
2872 
2873         startConnectSuccess();
2874 
2875         WifiConfiguration config = createTestNetwork(false);
2876         config.getNetworkSelectionStatus().setHasEverConnected(true);
2877         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
2878 
2879         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
2880                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
2881                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
2882         DisconnectEventInfo disconnectEventInfo =
2883                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2884         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2885         mLooper.dispatchAll();
2886 
2887         verify(mWrongPasswordNotifier, never()).onWrongPasswordError(any());
2888         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
2889                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE));
2890 
2891         assertEquals("DisconnectedState", getCurrentState().getName());
2892     }
2893 
2894     /**
2895      * Verify that when wrong password authentication failure notification is not sent when
2896      * the network was local only.
2897      */
2898     @Test
testWrongPasswordWithLocalOnlyConnection()2899     public void testWrongPasswordWithLocalOnlyConnection() throws Exception {
2900         initializeAndAddNetworkAndVerifySuccess();
2901 
2902         startConnectSuccess();
2903 
2904         WifiConfiguration config = createTestNetwork(false);
2905         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
2906 
2907         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
2908                 .thenReturn(Set.of(TEST_UID));
2909         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
2910                 .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME));
2911         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
2912                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
2913                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
2914         DisconnectEventInfo disconnectEventInfo =
2915                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2916         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2917         mLooper.dispatchAll();
2918 
2919         verify(mWrongPasswordNotifier, never()).onWrongPasswordError(any());
2920         assertEquals("DisconnectedState", getCurrentState().getName());
2921     }
2922 
2923     /**
2924      * Verify that when wrong password authentication failure notification is sent when
2925      * the network was NOT local only.
2926      */
2927     @Test
testWrongPasswordWithNonLocalOnlyConnection()2928     public void testWrongPasswordWithNonLocalOnlyConnection() throws Exception {
2929         initializeAndAddNetworkAndVerifySuccess();
2930 
2931         startConnectSuccess();
2932 
2933         WifiConfiguration config = createTestNetwork(false);
2934         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
2935 
2936         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
2937                 .thenReturn(Collections.emptySet());
2938         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
2939                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
2940         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
2941                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
2942                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
2943         DisconnectEventInfo disconnectEventInfo =
2944                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2945         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2946         mLooper.dispatchAll();
2947 
2948         verify(mWrongPasswordNotifier).onWrongPasswordError(any());
2949         assertEquals("DisconnectedState", getCurrentState().getName());
2950     }
2951 
2952     /**
2953      * It is observed sometimes the WifiMonitor.NETWORK_DISCONNECTION_EVENT is observed before the
2954      * actual connection failure messages while making a connection.
2955      * The test make sure that make sure that the connection event is ended properly in the above
2956      * case.
2957      */
2958     @Test
testDisconnectionEventInL2ConnectingStateEndsConnectionEvent()2959     public void testDisconnectionEventInL2ConnectingStateEndsConnectionEvent() throws Exception {
2960         initializeAndAddNetworkAndVerifySuccess();
2961 
2962         startConnectSuccess();
2963 
2964         WifiConfiguration config = createTestNetwork(false);
2965         config.getNetworkSelectionStatus().setHasEverConnected(true);
2966         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
2967 
2968         DisconnectEventInfo disconnectEventInfo =
2969                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
2970         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
2971         mLooper.dispatchAll();
2972 
2973         verify(mWifiMetrics).endConnectionEvent(
2974                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
2975                 anyInt(), anyInt(), anyInt(), anyInt());
2976         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
2977                 any(), anyInt(), anyInt(), any(), any());
2978         assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, mWifiInfo.getCurrentSecurityType());
2979         assertEquals("DisconnectedState", getCurrentState().getName());
2980     }
2981 
2982     /**
2983      * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD
2984      * when wrong password authentication failure is detected and the network has never been
2985      * connected.
2986      */
2987     @Test
testWrongPasswordWithNeverConnected()2988     public void testWrongPasswordWithNeverConnected() throws Exception {
2989         initializeAndAddNetworkAndVerifySuccess();
2990 
2991         startConnectSuccess();
2992 
2993         WifiConfiguration config = new WifiConfiguration();
2994         config.SSID = TEST_SSID;
2995         config.getNetworkSelectionStatus().setHasEverConnected(false);
2996         config.carrierId = CARRIER_ID_1;
2997         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
2998 
2999         // Need to add supplicant state changed event to simulate broadcasts correctly
3000         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3001                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
3002                         SupplicantState.ASSOCIATED));
3003         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3004                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
3005                         SupplicantState.FOUR_WAY_HANDSHAKE));
3006 
3007         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3008                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3009                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
3010         DisconnectEventInfo disconnectEventInfo =
3011                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
3012         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3013         mLooper.dispatchAll();
3014 
3015         verify(mWrongPasswordNotifier).onWrongPasswordError(config);
3016         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
3017                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));
3018         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionAuthFailure();
3019         // Verify broadcasts corresponding to supplicant ASSOCIATED, FOUR_WAY_HANDSHAKE, then
3020         // finally wrong password causing disconnect.
3021         inOrderVerifyNetworkStateChangedBroadcasts(
3022                 new NetworkStateChangedIntentMatcher(CONNECTING),
3023                 new NetworkStateChangedIntentMatcher(AUTHENTICATING),
3024                 new NetworkStateChangedIntentMatcher(DISCONNECTED));
3025         assertEquals("DisconnectedState", getCurrentState().getName());
3026     }
3027 
3028     /**
3029      * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager
3030      * is called when a Authentication failure is detected with a vendor specific EAP Error
3031      * of certification expired while using EAP-SIM
3032      * In this test case, it is assumed that the network had been connected previously.
3033      */
3034     @Test
testEapSimErrorVendorSpecific()3035     public void testEapSimErrorVendorSpecific() throws Exception {
3036         when(mWifiMetrics.startConnectionEvent(any(), any(), anyString(), anyInt(), anyBoolean(),
3037                 anyInt(), anyInt())).thenReturn(80000);
3038         initializeAndAddNetworkAndVerifySuccess();
3039 
3040         startConnectSuccess();
3041 
3042         WifiConfiguration config = new WifiConfiguration();
3043         config.SSID = TEST_SSID;
3044         config.getNetworkSelectionStatus().setHasEverConnected(true);
3045         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
3046         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
3047         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
3048         when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
3049                 .thenReturn(WifiHealthMonitor.REASON_AUTH_FAILURE);
3050 
3051         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3052                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3053                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
3054                         WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED));
3055         mLooper.dispatchAll();
3056 
3057         verify(mEapFailureNotifier).onEapFailure(
3058                 WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED, config, true);
3059         verify(mWifiCarrierInfoManager).resetCarrierKeysForImsiEncryption(any());
3060         verify(mDeviceConfigFacade).isAbnormalConnectionFailureBugreportEnabled();
3061         verify(mWifiScoreCard).detectAbnormalConnectionFailure(anyString());
3062         verify(mWifiDiagnostics, times(2)).takeBugReport(anyString(), anyString());
3063     }
3064 
3065     @Test
testEapAkaRetrieveOobPseudonymTriggeredByAuthenticationFailure()3066     public void testEapAkaRetrieveOobPseudonymTriggeredByAuthenticationFailure() throws Exception {
3067         when(mWifiMetrics.startConnectionEvent(any(), any(), anyString(), anyInt(), anyBoolean(),
3068                 anyInt(), anyInt())).thenReturn(80000);
3069         when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true);
3070         initializeAndAddNetworkAndVerifySuccess();
3071 
3072         startConnectSuccess();
3073 
3074         WifiConfiguration config = new WifiConfiguration();
3075         config.SSID = TEST_SSID;
3076         config.getNetworkSelectionStatus().setHasEverConnected(true);
3077         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
3078         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.AKA);
3079         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
3080         when(mWifiScoreCard.detectAbnormalConnectionFailure(anyString()))
3081                 .thenReturn(WifiHealthMonitor.REASON_AUTH_FAILURE);
3082 
3083         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3084                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3085                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
3086                         -1));
3087         mLooper.dispatchAll();
3088 
3089         verify(mEapFailureNotifier).onEapFailure(
3090                 -1, config, true);
3091         verify(mWifiPseudonymManager).retrieveOobPseudonymWithRateLimit(anyInt());
3092         verify(mDeviceConfigFacade).isAbnormalConnectionFailureBugreportEnabled();
3093         verify(mWifiScoreCard).detectAbnormalConnectionFailure(anyString());
3094         verify(mWifiDiagnostics, times(2)).takeBugReport(anyString(), anyString());
3095     }
3096 
3097     /**
3098      * Verify that the function resetCarrierKeysForImsiEncryption() in TelephonyManager
3099      * is not called when a Authentication failure is detected with a vendor specific EAP Error
3100      * of certification expired while using other methods than EAP-SIM, EAP-AKA, or EAP-AKA'.
3101      */
3102     @Test
testEapTlsErrorVendorSpecific()3103     public void testEapTlsErrorVendorSpecific() throws Exception {
3104         initializeAndAddNetworkAndVerifySuccess();
3105 
3106         startConnectSuccess();
3107 
3108         WifiConfiguration config = new WifiConfiguration();
3109         config.getNetworkSelectionStatus().setHasEverConnected(true);
3110         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
3111         config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
3112         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
3113 
3114         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3115                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3116                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
3117                         WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED));
3118         mLooper.dispatchAll();
3119 
3120         verify(mWifiCarrierInfoManager, never()).resetCarrierKeysForImsiEncryption(any());
3121     }
3122 
3123     @Test
testAuthFailureOnDifferentSsidIsIgnored()3124     public void testAuthFailureOnDifferentSsidIsIgnored() throws Exception {
3125         initializeAndAddNetworkAndVerifySuccess();
3126 
3127         startConnectSuccess();
3128         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3129                 new AuthenticationFailureEventInfo("WRONG_SSID",
3130                         MacAddress.fromString(TEST_BSSID_STR),
3131                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
3132                         WifiNative.EAP_SIM_NOT_SUBSCRIBED));
3133         mLooper.dispatchAll();
3134         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
3135                 eq(WifiConfiguration.NetworkSelectionStatus
3136                         .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION));
3137     }
3138 
3139     /**
3140      * Verify that the network selection status will be updated with
3141      * DISABLED_AUTHENTICATION_NO_SUBSCRIBED when service is not subscribed.
3142      */
3143     @Test
testEapSimNoSubscribedError()3144     public void testEapSimNoSubscribedError() throws Exception {
3145         initializeAndAddNetworkAndVerifySuccess();
3146 
3147         startConnectSuccess();
3148 
3149         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3150                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3151                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE,
3152                         WifiNative.EAP_SIM_NOT_SUBSCRIBED));
3153         mLooper.dispatchAll();
3154 
3155         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
3156                 eq(WifiConfiguration.NetworkSelectionStatus
3157                         .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION));
3158     }
3159 
3160     @Test
testBadNetworkEvent()3161     public void testBadNetworkEvent() throws Exception {
3162         initializeAndAddNetworkAndVerifySuccess();
3163 
3164         startConnectSuccess();
3165 
3166         DisconnectEventInfo disconnectEventInfo =
3167                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
3168         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3169         mLooper.dispatchAll();
3170 
3171         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3172                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
3173                         SupplicantState.COMPLETED));
3174         mLooper.dispatchAll();
3175 
3176         assertEquals("DisconnectedState", getCurrentState().getName());
3177         verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString());
3178     }
3179 
3180 
3181     @Test
getWhatToString()3182     public void getWhatToString() throws Exception {
3183         assertEquals("CMD_PRE_DHCP_ACTION", mCmi.getWhatToString(CMD_PRE_DHCP_ACTION));
3184         assertEquals("CMD_IP_REACHABILITY_LOST", mCmi.getWhatToString(
3185                 ClientModeImpl.CMD_IP_REACHABILITY_LOST));
3186         assertEquals("CMD_IP_REACHABILITY_FAILURE", mCmi.getWhatToString(
3187                 ClientModeImpl.CMD_IP_REACHABILITY_FAILURE));
3188     }
3189 
3190     @Test
disconnect()3191     public void disconnect() throws Exception {
3192         when(mWifiScoreCard.detectAbnormalDisconnection(any()))
3193                 .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL);
3194         InOrder inOrderWifiLockManager = inOrder(mWifiLockManager);
3195         connect();
3196         inOrderWifiLockManager.verify(mWifiLockManager)
3197                 .updateWifiClientConnected(mClientModeManager, true);
3198 
3199         DisconnectEventInfo disconnectEventInfo =
3200                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
3201         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3202         mLooper.dispatchAll();
3203         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3204                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
3205                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
3206         mLooper.dispatchAll();
3207 
3208         verify(mWifiStateTracker).updateState(WIFI_IFACE_NAME, WifiStateTracker.DISCONNECTED);
3209         assertEquals("DisconnectedState", getCurrentState().getName());
3210         verify(mCmiMonitor).onConnectionEnd(mClientModeManager);
3211         inOrderWifiLockManager.verify(mWifiLockManager)
3212                 .updateWifiClientConnected(mClientModeManager, false);
3213         verify(mWifiScoreCard).detectAbnormalDisconnection(WIFI_IFACE_NAME);
3214         verify(mWifiDiagnostics).takeBugReport(anyString(), anyString());
3215         verify(mWifiNative).disableNetwork(WIFI_IFACE_NAME);
3216         // Set MAC address thrice - once at bootup, once for new connection, once for disconnect.
3217         verify(mWifiNative, times(3)).setStaMacAddress(eq(WIFI_IFACE_NAME), any());
3218         // ClientModeManager should only be stopped when in lingering mode
3219         verify(mClientModeManager, never()).stop();
3220     }
3221 
3222     @Test
secondaryRoleCmmDisconnected_stopsClientModeManager()3223     public void secondaryRoleCmmDisconnected_stopsClientModeManager() throws Exception {
3224         // Owning ClientModeManager has role SECONDARY_TRANSIENT
3225         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
3226 
3227         connect();
3228 
3229         // ClientModeManager never stopped
3230         verify(mClientModeManager, never()).stop();
3231 
3232         // Disconnected from network
3233         DisconnectEventInfo disconnectEventInfo =
3234                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
3235         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3236         mLooper.dispatchAll();
3237         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3238                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
3239                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
3240         mLooper.dispatchAll();
3241 
3242         assertEquals("DisconnectedState", getCurrentState().getName());
3243 
3244         // Since in lingering mode, disconnect => stop ClientModeManager
3245         verify(mClientModeManager).stop();
3246     }
3247 
3248     @Test
primaryCmmDisconnected_doesntStopsClientModeManager()3249     public void primaryCmmDisconnected_doesntStopsClientModeManager() throws Exception {
3250         // Owning ClientModeManager is primary
3251         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
3252 
3253         connect();
3254 
3255         // ClientModeManager never stopped
3256         verify(mClientModeManager, never()).stop();
3257 
3258         // Disconnected from network
3259         DisconnectEventInfo disconnectEventInfo =
3260                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
3261         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3262         mLooper.dispatchAll();
3263         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3264                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
3265                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
3266         mLooper.dispatchAll();
3267 
3268         assertEquals("DisconnectedState", getCurrentState().getName());
3269 
3270         // Since primary => don't stop ClientModeManager
3271         verify(mClientModeManager, never()).stop();
3272     }
3273 
3274     /**
3275      * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
3276      * to true.
3277      *
3278      * Test: Successfully create and connect to a network. Check the config and verify
3279      * WifiConfiguration.getHasEverConnected() is true.
3280      */
3281     @Test
setHasEverConnectedTrueOnConnect()3282     public void setHasEverConnectedTrueOnConnect() throws Exception {
3283         connect();
3284         verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(eq(0), eq(true),
3285                 eq(false),
3286                 anyInt());
3287     }
3288 
3289     /**
3290      * Fail network connection attempt and verify HasEverConnected remains false.
3291      *
3292      * Test: Successfully create a network but fail when connecting. Check the config and verify
3293      * WifiConfiguration.getHasEverConnected() is false.
3294      */
3295     @Test
connectionFailureDoesNotSetHasEverConnectedTrue()3296     public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
3297         testDhcpFailure();
3298         verify(mWifiConfigManager, never())
3299                 .updateNetworkAfterConnect(eq(0), eq(true), eq(false), anyInt());
3300     }
3301 
3302     @Test
iconQueryTest()3303     public void iconQueryTest() throws Exception {
3304         // TODO(b/31065385): Passpoint config management.
3305     }
3306 
3307     @Test
verboseLogRecSizeIsGreaterThanNormalSize()3308     public void verboseLogRecSizeIsGreaterThanNormalSize() {
3309         assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > mWifiGlobals.getClientModeImplNumLogRecs());
3310     }
3311 
3312     /**
3313      * Verifies that, by default, we allow only the "normal" number of log records.
3314      */
3315     @Test
normalLogRecSizeIsUsedByDefault()3316     public void normalLogRecSizeIsUsedByDefault() {
3317         mCmi.enableVerboseLogging(false);
3318         assertEquals(mWifiGlobals.getClientModeImplNumLogRecs(), mCmi.getLogRecMaxSize());
3319     }
3320 
3321     /**
3322      * Verifies that, in verbose mode, we allow a larger number of log records.
3323      */
3324     @Test
enablingVerboseLoggingUpdatesLogRecSize()3325     public void enablingVerboseLoggingUpdatesLogRecSize() {
3326         when(mActivityManager.isLowRamDevice()).thenReturn(false);
3327         mCmi.enableVerboseLogging(true);
3328         assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mCmi.getLogRecMaxSize());
3329     }
3330 
3331     /**
3332      * Verifies that, in verbose mode, we allow a larger number of log records on a low ram device.
3333      */
3334     @Test
enablingVerboseLoggingUpdatesLogRecSizeLowRamDevice()3335     public void enablingVerboseLoggingUpdatesLogRecSizeLowRamDevice() {
3336         when(mActivityManager.isLowRamDevice()).thenReturn(true);
3337         mCmi.enableVerboseLogging(true);
3338         assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE_LOW_RAM, mCmi.getLogRecMaxSize());
3339     }
3340 
3341     @Test
disablingVerboseLoggingClearsRecords()3342     public void disablingVerboseLoggingClearsRecords() {
3343         mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT);
3344         mLooper.dispatchAll();
3345         assertTrue(mCmi.getLogRecSize() >= 1);
3346 
3347         mCmi.enableVerboseLogging(false);
3348         assertEquals(0, mCmi.getLogRecSize());
3349     }
3350 
3351     @Test
disablingVerboseLoggingUpdatesLogRecSize()3352     public void disablingVerboseLoggingUpdatesLogRecSize() {
3353         mCmi.enableVerboseLogging(true);
3354         mCmi.enableVerboseLogging(false);
3355         assertEquals(mWifiGlobals.getClientModeImplNumLogRecs(), mCmi.getLogRecMaxSize());
3356     }
3357 
3358     @Test
logRecsIncludeDisconnectCommand()3359     public void logRecsIncludeDisconnectCommand() {
3360         // There's nothing special about the DISCONNECT command. It's just representative of
3361         // "normal" commands.
3362         mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT);
3363         mLooper.dispatchAll();
3364         assertEquals(2, mCmi.copyLogRecs()
3365                 .stream()
3366                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_DISCONNECT)
3367                 .count());
3368     }
3369 
3370     @Test
logRecsExcludeRssiPollCommandByDefault()3371     public void logRecsExcludeRssiPollCommandByDefault() {
3372         mCmi.enableVerboseLogging(false);
3373         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL);
3374         mLooper.dispatchAll();
3375         assertEquals(0, mCmi.copyLogRecs()
3376                 .stream()
3377                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL)
3378                 .count());
3379     }
3380 
3381     @Test
logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled()3382     public void logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled() {
3383         mCmi.enableVerboseLogging(true);
3384         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL);
3385         mLooper.dispatchAll();
3386         assertEquals(1, mCmi.copyLogRecs()
3387                 .stream()
3388                 .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_RSSI_POLL)
3389                 .count());
3390     }
3391 
3392     /**
3393      * Verify that syncStartSubscriptionProvisioning will redirect calls with right parameters
3394      * to {@link PasspointManager} with expected true being returned when in client mode.
3395      */
3396     @Test
syncStartSubscriptionProvisioningInClientMode()3397     public void syncStartSubscriptionProvisioningInClientMode() throws Exception {
3398         when(mPasspointManager.startSubscriptionProvisioning(anyInt(),
3399                 any(OsuProvider.class), any(IProvisioningCallback.class))).thenReturn(true);
3400         mLooper.startAutoDispatch();
3401         assertTrue(mCmi.syncStartSubscriptionProvisioning(
3402                 OTHER_USER_UID, mOsuProvider, mProvisioningCallback));
3403         verify(mPasspointManager).startSubscriptionProvisioning(OTHER_USER_UID, mOsuProvider,
3404                 mProvisioningCallback);
3405         mLooper.stopAutoDispatch();
3406     }
3407 
3408     @Test
testGetCurrentNetwork()3409     public void testGetCurrentNetwork() throws Exception {
3410         // getCurrentNetwork() returns null when disconnected
3411         assertNull(mCmi.getCurrentNetwork());
3412         connect();
3413 
3414         assertEquals("L3ConnectedState", getCurrentState().getName());
3415         // getCurrentNetwork() returns non-null Network when connected
3416         assertEquals(mNetwork, mCmi.getCurrentNetwork());
3417         // Now trigger disconnect
3418         mCmi.disconnect();
3419         DisconnectEventInfo disconnectEventInfo =
3420                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
3421         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3422         mLooper.dispatchAll();
3423         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3424                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
3425                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
3426         mLooper.dispatchAll();
3427         assertEquals("DisconnectedState", getCurrentState().getName());
3428         assertNull(mCmi.getCurrentNetwork());
3429     }
3430 
3431     /**
3432      *  Test that we disconnect from a network if it was removed while we are in the
3433      *  L3ProvisioningState.
3434      */
3435     @Test
disconnectFromNetworkWhenRemovedWhileObtainingIpAddr()3436     public void disconnectFromNetworkWhenRemovedWhileObtainingIpAddr() throws Exception {
3437         initializeAndAddNetworkAndVerifySuccess();
3438 
3439         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
3440 
3441         startConnectSuccess();
3442 
3443         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
3444                 .thenReturn(mScanDetailCache);
3445 
3446         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
3447                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
3448         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
3449                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
3450 
3451         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
3452                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
3453         mLooper.dispatchAll();
3454 
3455         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3456                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
3457                         SupplicantState.COMPLETED));
3458         mLooper.dispatchAll();
3459 
3460         assertEquals("L3ProvisioningState", getCurrentState().getName());
3461 
3462         // trigger removal callback to trigger disconnect.
3463         WifiConfiguration removedConfig = new WifiConfiguration();
3464         removedConfig.networkId = FRAMEWORK_NETWORK_ID;
3465         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
3466                 .getAllValues()) {
3467             listener.onNetworkRemoved(removedConfig);
3468         }
3469 
3470         reset(mWifiConfigManager);
3471 
3472         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID)).thenReturn(null);
3473 
3474         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
3475         dhcpResults.baseConfiguration = new StaticIpConfiguration();
3476         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
3477         dhcpResults.baseConfiguration.ipAddress =
3478                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
3479         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
3480         dhcpResults.leaseDuration = 3600;
3481 
3482         injectDhcpSuccess(dhcpResults);
3483         mLooper.dispatchAll();
3484 
3485         verify(mWifiNative, times(2)).disconnect(WIFI_IFACE_NAME);
3486     }
3487 
3488     /**
3489      * Verifies that WifiInfo is updated upon SUPPLICANT_STATE_CHANGE_EVENT.
3490      */
3491     @Test
testWifiInfoUpdatedUponSupplicantStateChangedEvent()3492     public void testWifiInfoUpdatedUponSupplicantStateChangedEvent() throws Exception {
3493         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
3494         connect();
3495 
3496         // Set the scan detail cache for roaming target.
3497         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
3498                 .thenReturn(mScanDetailCache);
3499         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR1)).thenReturn(
3500                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1));
3501         when(mScanDetailCache.getScanResult(TEST_BSSID_STR1)).thenReturn(
3502                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1).getScanResult());
3503 
3504         // This simulates the behavior of roaming to network with |TEST_BSSID_STR1|, |sFreq1|.
3505         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated.
3506         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3507                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
3508                         SupplicantState.COMPLETED));
3509         mLooper.dispatchAll();
3510 
3511         WifiInfo wifiInfo = mWifiInfo;
3512         assertEquals(TEST_BSSID_STR1, wifiInfo.getBSSID());
3513         assertEquals(sFreq1, wifiInfo.getFrequency());
3514         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
3515 
3516         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3517                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
3518                         SupplicantState.DISCONNECTED));
3519         mLooper.dispatchAll();
3520 
3521         wifiInfo = mWifiInfo;
3522         assertNull(wifiInfo.getBSSID());
3523         assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
3524         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiInfo.getNetworkId());
3525         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
3526         assertEquals("DisconnectedState", getCurrentState().getName());
3527     }
3528 
3529 
3530     /**
3531      * Verifies that WifiInfo is updated upon SUPPLICANT_STATE_CHANGE_EVENT.
3532      */
3533     @Test
testWifiInfoUpdatedUponSupplicantStateChangedEventWithWrongSsid()3534     public void testWifiInfoUpdatedUponSupplicantStateChangedEventWithWrongSsid() throws Exception {
3535         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
3536         connect();
3537 
3538         // Set the scan detail cache for roaming target.
3539         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
3540                 .thenReturn(mScanDetailCache);
3541         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR1)).thenReturn(
3542                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1));
3543         when(mScanDetailCache.getScanResult(TEST_BSSID_STR1)).thenReturn(
3544                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1).getScanResult());
3545 
3546         // This simulates the behavior of roaming to network with |TEST_BSSID_STR1|, |sFreq1|.
3547         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated.
3548         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3549                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
3550                         SupplicantState.COMPLETED));
3551         mLooper.dispatchAll();
3552 
3553         WifiInfo wifiInfo = mWifiInfo;
3554         assertEquals(TEST_BSSID_STR1, wifiInfo.getBSSID());
3555         assertEquals(sFreq1, wifiInfo.getFrequency());
3556         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
3557 
3558         // Send state change event with wrong ssid.
3559         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3560                 new StateChangeResult(0, TEST_WIFI_SSID1, TEST_BSSID_STR, sFreq,
3561                         SupplicantState.DISCONNECTED));
3562         mLooper.dispatchAll();
3563 
3564         wifiInfo = mWifiInfo;
3565         assertNull(wifiInfo.getBSSID());
3566         assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
3567         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiInfo.getNetworkId());
3568         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
3569         assertEquals("DisconnectedState", getCurrentState().getName());
3570     }
3571 
3572     @Test
testTriggerWifiNetworkStateChangedListener()3573     public void testTriggerWifiNetworkStateChangedListener() throws Exception {
3574         InOrder inOrder = inOrder(mActiveModeWarden);
3575         connect();
3576         inOrder.verify(mActiveModeWarden).onNetworkStateChanged(
3577                 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY,
3578                 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTING);
3579         inOrder.verify(mActiveModeWarden).onNetworkStateChanged(
3580                 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY,
3581                 WifiManager.WifiNetworkStateChangedListener
3582                         .WIFI_NETWORK_STATUS_OBTAINING_IPADDR);
3583         inOrder.verify(mActiveModeWarden).onNetworkStateChanged(
3584                 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY,
3585                 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTED);
3586         inOrder.verify(mActiveModeWarden, never()).onNetworkStateChanged(
3587                 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY,
3588                 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED);
3589     }
3590 
3591     /**
3592      * Verifies that WifiInfo is updated upon CMD_ASSOCIATED_BSSID event.
3593      */
3594     @Test
testWifiInfoUpdatedUponAssociatedBSSIDEvent()3595     public void testWifiInfoUpdatedUponAssociatedBSSIDEvent() throws Exception {
3596         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
3597         connect();
3598 
3599         // Set the scan detail cache for roaming target.
3600         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
3601                 .thenReturn(mScanDetailCache);
3602         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR1)).thenReturn(
3603                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1));
3604         when(mScanDetailCache.getScanResult(TEST_BSSID_STR1)).thenReturn(
3605                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq1).getScanResult());
3606 
3607         // This simulates the behavior of roaming to network with |TEST_BSSID_STR1|, |sFreq1|.
3608         // Send a CMD_ASSOCIATED_BSSID, verify WifiInfo is updated.
3609         mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, TEST_BSSID_STR1);
3610         mLooper.dispatchAll();
3611 
3612         WifiInfo wifiInfo = mWifiInfo;
3613         assertEquals(TEST_BSSID_STR1, wifiInfo.getBSSID());
3614         assertEquals(sFreq1, wifiInfo.getFrequency());
3615         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
3616         verifyNetworkStateChangedBroadcast(times(2),
3617                 new NetworkStateChangedIntentMatcher(CONNECTED));
3618     }
3619 
callmethod(VerificationMode mode, ArgumentMatcher<Intent> intentMatcher)3620     private void callmethod(VerificationMode mode, ArgumentMatcher<Intent> intentMatcher) {
3621         if (SdkLevel.isAtLeastU()) {
3622             verify(mUserAllContext, mode).sendStickyBroadcast(
3623                     argThat(intentMatcher), any());
3624         } else {
3625             verify(mContext, mode).sendStickyBroadcastAsUser(
3626                     argThat(intentMatcher), any());
3627         }
3628     }
3629 
3630     /**
3631      * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not
3632      * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState.
3633      * This protects ClientModeImpl from  getting into a bad state where WifiInfo says wifi is
3634      * already Connected or Connecting, (when it is in-fact Disconnected), so
3635      * WifiConnectivityManager does not attempt any new Connections, freezing wifi.
3636      */
3637     @Test
testWifiInfoCleanedUpEnteringExitingConnectableState()3638     public void testWifiInfoCleanedUpEnteringExitingConnectableState() throws Exception {
3639         InOrder inOrderMetrics = inOrder(mWifiMetrics);
3640         Log.i(TAG, mCmi.getCurrentState().getName());
3641         String initialBSSID = "aa:bb:cc:dd:ee:ff";
3642         WifiInfo wifiInfo = mWifiInfo;
3643         wifiInfo.setBSSID(initialBSSID);
3644 
3645         // reset mWifiNative since initializeCmi() was called in setup()
3646         resetWifiNative();
3647 
3648         // Set CMI to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager
3649         initializeCmi();
3650         inOrderMetrics.verify(mWifiMetrics)
3651                 .setWifiState(WIFI_IFACE_NAME, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
3652         inOrderMetrics.verify(mWifiMetrics)
3653                 .logStaEvent(WIFI_IFACE_NAME, StaEvent.TYPE_WIFI_ENABLED);
3654         assertNull(wifiInfo.getBSSID());
3655 
3656         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated
3657         connect();
3658         assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID());
3659         assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
3660 
3661         // Set CMI to DISABLED_MODE, verify state and wifi disabled in ConnectivityManager, and
3662         // WifiInfo is reset() and state set to DISCONNECTED
3663         mCmi.stop();
3664         mLooper.dispatchAll();
3665 
3666         inOrderMetrics.verify(mWifiMetrics).setWifiState(WIFI_IFACE_NAME,
3667                 WifiMetricsProto.WifiLog.WIFI_DISABLED);
3668         inOrderMetrics.verify(mWifiMetrics)
3669                 .logStaEvent(WIFI_IFACE_NAME, StaEvent.TYPE_WIFI_DISABLED);
3670         assertNull(wifiInfo.getBSSID());
3671         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
3672     }
3673 
3674     @Test
testWifiInfoCleanedUpEnteringExitingConnectableState2()3675     public void testWifiInfoCleanedUpEnteringExitingConnectableState2() throws Exception {
3676         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated
3677         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
3678                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
3679                         SupplicantState.COMPLETED));
3680         mLooper.dispatchAll();
3681         assertNull(mWifiInfo.getBSSID());
3682         assertEquals(SupplicantState.DISCONNECTED, mWifiInfo.getSupplicantState());
3683     }
3684 
3685     @Test
testWifiInfoCleanedUpEnteringExitingConnectableState3()3686     public void testWifiInfoCleanedUpEnteringExitingConnectableState3() throws Exception {
3687         String initialBSSID = "aa:bb:cc:dd:ee:ff";
3688         InOrder inOrderMetrics = inOrder(mWifiMetrics);
3689 
3690         // Set the bssid to something, so we can verify it is cleared (just in case)
3691         mWifiInfo.setBSSID(initialBSSID);
3692 
3693         initializeCmi();
3694 
3695         inOrderMetrics.verify(mWifiMetrics)
3696                 .setWifiState(WIFI_IFACE_NAME, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
3697         inOrderMetrics.verify(mWifiMetrics)
3698                 .logStaEvent(WIFI_IFACE_NAME, StaEvent.TYPE_WIFI_ENABLED);
3699         assertEquals("DisconnectedState", getCurrentState().getName());
3700         assertEquals(SupplicantState.DISCONNECTED, mWifiInfo.getSupplicantState());
3701         assertNull(mWifiInfo.getBSSID());
3702     }
3703 
3704     /**
3705      * Test that connected SSID and BSSID are exposed to system server.
3706      * Also tests that {@link ClientModeImpl#getConnectionInfo()} always
3707      * returns a copy of WifiInfo.
3708      */
3709     @Test
testConnectedIdsAreVisibleFromSystemServer()3710     public void testConnectedIdsAreVisibleFromSystemServer() throws Exception {
3711         WifiInfo wifiInfo = mWifiInfo;
3712         // Get into a connected state, with known BSSID and SSID
3713         connect();
3714         assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID());
3715         assertEquals(TEST_WIFI_SSID, wifiInfo.getWifiSsid());
3716 
3717         WifiInfo connectionInfo = mCmi.getConnectionInfo();
3718         assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID());
3719         assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID());
3720         assertEquals(wifiInfo.getMacAddress(), connectionInfo.getMacAddress());
3721     }
3722 
3723     /**
3724      * Test that reconnectCommand() triggers connectivity scan when ClientModeImpl
3725      * is in DisconnectedMode.
3726      */
3727     @Test
testReconnectCommandWhenDisconnected()3728     public void testReconnectCommandWhenDisconnected() throws Exception {
3729         // Connect to network with |TEST_BSSID_STR|, |sFreq|, and then disconnect.
3730         disconnect();
3731         verify(mActiveModeWarden).onNetworkStateChanged(
3732                 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY,
3733                 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED);
3734 
3735         mCmi.reconnect(ClientModeImpl.WIFI_WORK_SOURCE);
3736         mLooper.dispatchAll();
3737         verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
3738     }
3739 
3740     /**
3741      * Test that reconnectCommand() doesn't trigger connectivity scan when ClientModeImpl
3742      * is in ConnectedMode.
3743      */
3744     @Test
testReconnectCommandWhenConnected()3745     public void testReconnectCommandWhenConnected() throws Exception {
3746         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
3747         connect();
3748 
3749         mCmi.reconnect(ClientModeImpl.WIFI_WORK_SOURCE);
3750         mLooper.dispatchAll();
3751         verify(mWifiConnectivityManager, never())
3752                 .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
3753     }
3754 
3755     /**
3756      * Verifies that ClientModeImpl sets and unsets appropriate 'RecentFailureReason' values
3757      * on a WifiConfiguration when it fails association, authentication, or successfully connects
3758      */
3759     @Test
testExtraFailureReason_ApIsBusy()3760     public void testExtraFailureReason_ApIsBusy() throws Exception {
3761         // Setup CONNECT_MODE & a WifiConfiguration
3762         initializeAndAddNetworkAndVerifySuccess();
3763         // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up
3764         // targetNetworkId state)
3765         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
3766         mLooper.dispatchAll();
3767         // Simulate an ASSOCIATION_REJECTION_EVENT, due to the AP being busy
3768         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
3769                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
3770                         ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA,
3771                         false));
3772         mLooper.dispatchAll();
3773         verify(mWifiConfigManager).setRecentFailureAssociationStatus(eq(0),
3774                 eq(WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA));
3775         assertEquals("DisconnectedState", getCurrentState().getName());
3776 
3777         // Simulate an AUTHENTICATION_FAILURE_EVENT, which should clear the ExtraFailureReason
3778         reset(mWifiConfigManager);
3779         initializeAndAddNetworkAndVerifySuccess();
3780         // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up
3781         // targetNetworkId state)
3782         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
3783         mLooper.dispatchAll();
3784         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
3785                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
3786                         WifiManager.ERROR_AUTH_FAILURE_TIMEOUT, -1));
3787         DisconnectEventInfo disconnectEventInfo =
3788                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
3789         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
3790         mLooper.dispatchAll();
3791         verify(mWifiConfigManager).clearRecentFailureReason(eq(0));
3792         verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt());
3793 
3794         // Simulate a NETWORK_CONNECTION_EVENT which should clear the ExtraFailureReason
3795         reset(mWifiConfigManager);
3796         initializeAndAddNetworkAndVerifySuccess();
3797         // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up
3798         // targetNetworkId state)
3799         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
3800         mLooper.dispatchAll();
3801         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
3802                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, null, false, null));
3803         mLooper.dispatchAll();
3804         verify(mWifiConfigManager).clearRecentFailureReason(eq(0));
3805         verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt());
3806     }
3807 
makeLastSelectedWifiConfiguration(int lastSelectedNetworkId, long timeSinceLastSelected)3808     private WifiConfiguration makeLastSelectedWifiConfiguration(int lastSelectedNetworkId,
3809             long timeSinceLastSelected) {
3810         long lastSelectedTimestamp = 45666743454L;
3811 
3812         when(mClock.getElapsedSinceBootMillis()).thenReturn(
3813                 lastSelectedTimestamp + timeSinceLastSelected);
3814         when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp);
3815         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId);
3816 
3817         WifiConfiguration currentConfig = new WifiConfiguration();
3818         currentConfig.networkId = lastSelectedNetworkId;
3819         return currentConfig;
3820     }
3821 
3822     /**
3823      * Test that the helper method
3824      * {@link ClientModeImpl#isRecentlySelectedByTheUser(WifiConfiguration)}
3825      * returns true when we connect to the last selected network before expiration of
3826      * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
3827      */
3828     @Test
testIsRecentlySelectedByTheUser_SameNetworkNotExpired()3829     public void testIsRecentlySelectedByTheUser_SameNetworkNotExpired() {
3830         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
3831                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
3832         assertTrue(mCmi.isRecentlySelectedByTheUser(currentConfig));
3833     }
3834 
3835     /**
3836      * Test that the helper method
3837      * {@link ClientModeImpl#isRecentlySelectedByTheUser(WifiConfiguration)}
3838      * returns false when we connect to the last selected network after expiration of
3839      * {@link ClientModeImpl#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
3840      */
3841     @Test
testIsRecentlySelectedByTheUser_SameNetworkExpired()3842     public void testIsRecentlySelectedByTheUser_SameNetworkExpired() {
3843         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
3844                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1);
3845         assertFalse(mCmi.isRecentlySelectedByTheUser(currentConfig));
3846     }
3847 
3848     /**
3849      * Test that the helper method
3850      * {@link ClientModeImpl#isRecentlySelectedByTheUser(WifiConfiguration)}
3851      * returns false when we connect to a different network to the last selected network.
3852      */
3853     @Test
testIsRecentlySelectedByTheUser_DifferentNetwork()3854     public void testIsRecentlySelectedByTheUser_DifferentNetwork() {
3855         WifiConfiguration currentConfig = makeLastSelectedWifiConfiguration(5,
3856                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
3857         currentConfig.networkId = 4;
3858         assertFalse(mCmi.isRecentlySelectedByTheUser(currentConfig));
3859     }
3860 
expectRegisterNetworkAgent(Consumer<NetworkAgentConfig> configChecker, Consumer<NetworkCapabilities> networkCapabilitiesChecker)3861     private void expectRegisterNetworkAgent(Consumer<NetworkAgentConfig> configChecker,
3862             Consumer<NetworkCapabilities> networkCapabilitiesChecker) {
3863         // Expects that the code calls registerNetworkAgent and provides a way for the test to
3864         // verify the messages sent through the NetworkAgent to ConnectivityService.
3865         // We cannot just use a mock object here because mWifiNetworkAgent is private to CMI.
3866         ArgumentCaptor<NetworkAgentConfig> configCaptor =
3867                 ArgumentCaptor.forClass(NetworkAgentConfig.class);
3868         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
3869                 ArgumentCaptor.forClass(NetworkCapabilities.class);
3870 
3871         verify(mWifiInjector).makeWifiNetworkAgent(
3872                 networkCapabilitiesCaptor.capture(),
3873                 any(),
3874                 configCaptor.capture(),
3875                 any(),
3876                 mWifiNetworkAgentCallbackCaptor.capture());
3877 
3878         configChecker.accept(configCaptor.getValue());
3879         networkCapabilitiesChecker.accept(networkCapabilitiesCaptor.getValue());
3880     }
3881 
expectNetworkAgentUpdateCapabilities( Consumer<NetworkCapabilities> networkCapabilitiesChecker)3882     private void expectNetworkAgentUpdateCapabilities(
3883             Consumer<NetworkCapabilities> networkCapabilitiesChecker) throws Exception {
3884         ArgumentCaptor<NetworkCapabilities> captor = ArgumentCaptor.forClass(
3885                 NetworkCapabilities.class);
3886         mLooper.dispatchAll();
3887         verify(mWifiNetworkAgent).sendNetworkCapabilitiesAndCache(captor.capture());
3888         networkCapabilitiesChecker.accept(captor.getValue());
3889     }
3890 
3891     /**
3892      * Verify that when a network is explicitly selected, but noInternetAccessExpected is false,
3893      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
3894      * acceptUnvalidated and acceptPartialConnectivity.
3895      */
3896     @Test
testExplicitlySelected_ExplicitInternetExpected()3897     public void testExplicitlySelected_ExplicitInternetExpected() throws Exception {
3898         // Network is explicitly selected.
3899         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
3900                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
3901         mConnectedNetwork.noInternetAccessExpected = false;
3902 
3903         connect();
3904         expectRegisterNetworkAgent((agentConfig) -> {
3905             assertTrue(agentConfig.explicitlySelected);
3906             assertFalse(agentConfig.acceptUnvalidated);
3907             assertFalse(agentConfig.acceptPartialConnectivity);
3908         }, (cap) -> { });
3909     }
3910 
3911     /**
3912      * Verify that when a network is explicitly selected, has role SECONDARY_TRANSIENT, but
3913      * noInternetAccessExpected is false, the {@link NetworkAgentConfig} contains the right values
3914      * of explicitlySelected, acceptUnvalidated and acceptPartialConnectivity.
3915      */
3916     @Test
testExplicitlySelected_secondaryTransient_expectNotExplicitlySelected()3917     public void testExplicitlySelected_secondaryTransient_expectNotExplicitlySelected()
3918             throws Exception {
3919         // Network is explicitly selected.
3920         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
3921                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
3922         mConnectedNetwork.noInternetAccessExpected = false;
3923 
3924         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
3925 
3926         connect();
3927         expectRegisterNetworkAgent((agentConfig) -> {
3928             assertFalse(agentConfig.explicitlySelected);
3929             assertFalse(agentConfig.acceptUnvalidated);
3930             assertFalse(agentConfig.acceptPartialConnectivity);
3931         }, (cap) -> { });
3932     }
3933 
3934     /**
3935      * Verify that when a network is not explicitly selected, but noInternetAccessExpected is true,
3936      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
3937      * acceptUnvalidated and acceptPartialConnectivity.
3938      */
3939     @Test
testExplicitlySelected_NotExplicitNoInternetExpected()3940     public void testExplicitlySelected_NotExplicitNoInternetExpected() throws Exception {
3941         // Network is no longer explicitly selected.
3942         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
3943                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1);
3944         mConnectedNetwork.noInternetAccessExpected = true;
3945 
3946         connect();
3947         expectRegisterNetworkAgent((agentConfig) -> {
3948             assertFalse(agentConfig.explicitlySelected);
3949             assertFalse(agentConfig.acceptUnvalidated);
3950             assertTrue(agentConfig.acceptPartialConnectivity);
3951         }, (cap) -> { });
3952     }
3953 
3954     /**
3955      * Verify that when a network is explicitly selected, and noInternetAccessExpected is true,
3956      * the {@link NetworkAgentConfig} contains the right values of explicitlySelected,
3957      * acceptUnvalidated and acceptPartialConnectivity.
3958      */
3959     @Test
testExplicitlySelected_ExplicitNoInternetExpected()3960     public void testExplicitlySelected_ExplicitNoInternetExpected() throws Exception {
3961         // Network is explicitly selected.
3962         WifiConfiguration config = makeLastSelectedWifiConfiguration(FRAMEWORK_NETWORK_ID,
3963                 ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
3964         mConnectedNetwork.noInternetAccessExpected = true;
3965 
3966         connect();
3967         expectRegisterNetworkAgent((agentConfig) -> {
3968             assertTrue(agentConfig.explicitlySelected);
3969             assertTrue(agentConfig.acceptUnvalidated);
3970             assertTrue(agentConfig.acceptPartialConnectivity);
3971         }, (cap) -> { });
3972     }
3973 
3974     /**
3975      * Verify that Rssi Monitoring is started and the callback registered after connecting.
3976      */
3977     @Test
verifyRssiMonitoringCallbackIsRegistered()3978     public void verifyRssiMonitoringCallbackIsRegistered() throws Exception {
3979         // Simulate the first connection.
3980         connect();
3981 
3982         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
3983                 mWifiNetworkAgentCallbackCaptor.capture());
3984 
3985         ArrayList<Integer> thresholdsArray = new ArrayList<>();
3986         thresholdsArray.add(RSSI_THRESHOLD_MAX);
3987         thresholdsArray.add(RSSI_THRESHOLD_MIN);
3988         mWifiNetworkAgentCallbackCaptor.getValue().onSignalStrengthThresholdsUpdated(
3989                 thresholdsArray.stream().mapToInt(Integer::intValue).toArray());
3990         mLooper.dispatchAll();
3991 
3992         ArgumentCaptor<WifiNative.WifiRssiEventHandler> rssiEventHandlerCaptor =
3993                 ArgumentCaptor.forClass(WifiNative.WifiRssiEventHandler.class);
3994         verify(mWifiNative).startRssiMonitoring(anyString(), anyByte(), anyByte(),
3995                 rssiEventHandlerCaptor.capture());
3996 
3997         // breach below min
3998         rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MIN);
3999         mLooper.dispatchAll();
4000         WifiInfo wifiInfo = mWifiInfo;
4001         assertEquals(RSSI_THRESHOLD_BREACH_MIN, wifiInfo.getRssi());
4002 
4003         // breach above max
4004         rssiEventHandlerCaptor.getValue().onRssiThresholdBreached(RSSI_THRESHOLD_BREACH_MAX);
4005         mLooper.dispatchAll();
4006         assertEquals(RSSI_THRESHOLD_BREACH_MAX, wifiInfo.getRssi());
4007     }
4008 
4009     /**
4010      * Verify that RSSI monitoring is not enabled on secondary STA.
4011      */
4012     @Test
testRssiMonitoringOnSecondaryIsNotEnabled()4013     public void testRssiMonitoringOnSecondaryIsNotEnabled() throws Exception {
4014         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
4015         connect();
4016 
4017         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
4018                 mWifiNetworkAgentCallbackCaptor.capture());
4019 
4020         int[] thresholds = {RSSI_THRESHOLD_BREACH_MAX};
4021         mWifiNetworkAgentCallbackCaptor.getValue().onSignalStrengthThresholdsUpdated(thresholds);
4022         mLooper.dispatchAll();
4023 
4024         verify(mWifiNative, never()).startRssiMonitoring(anyString(), anyByte(), anyByte(),
4025                 any());
4026     }
4027 
4028     /**
4029      * Verify that RSSI and link layer stats polling works in connected mode
4030      */
4031     @Test
verifyConnectedModeRssiPolling()4032     public void verifyConnectedModeRssiPolling() throws Exception {
4033         final long startMillis = 1_500_000_000_100L;
4034         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4035         llStats.txmpdu_be = 1000;
4036         llStats.rxmpdu_bk = 2000;
4037         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4038         signalPollResults.addEntry(0, -42, 65, 54, sFreq);
4039         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4040                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4041         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4042         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4043         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
4044         mCmi.enableRssiPolling(true);
4045         connect();
4046         mLooper.dispatchAll();
4047         assertRssiChangeBroadcastSent(1);
4048         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
4049         mLooper.dispatchAll();
4050         WifiInfo wifiInfo = mWifiInfo;
4051         assertEquals(llStats.txmpdu_be, wifiInfo.txSuccess);
4052         assertEquals(llStats.rxmpdu_bk, wifiInfo.rxSuccess);
4053         assertEquals(signalPollResults.getRssi(), wifiInfo.getRssi());
4054         assertEquals(signalPollResults.getTxLinkSpeed(), wifiInfo.getLinkSpeed());
4055         assertEquals(signalPollResults.getTxLinkSpeed(), wifiInfo.getTxLinkSpeedMbps());
4056         assertEquals(signalPollResults.getRxLinkSpeed(), wifiInfo.getRxLinkSpeedMbps());
4057         assertEquals(sFreq, wifiInfo.getFrequency());
4058         verify(mPerNetwork, atLeastOnce()).getTxLinkBandwidthKbps();
4059         verify(mPerNetwork, atLeastOnce()).getRxLinkBandwidthKbps();
4060         verify(mWifiScoreCard).noteSignalPoll(any());
4061     }
4062 
4063     /**
4064      * Verify that RSSI polling will send RSSI broadcasts if the RSSI signal level has changed
4065      */
4066     @Test
verifyConnectedModeRssiPollingWithSameSignalLevel()4067     public void verifyConnectedModeRssiPollingWithSameSignalLevel() throws Exception {
4068         final long startMillis = 1_500_000_000_100L;
4069         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4070         llStats.txmpdu_be = 1000;
4071         llStats.rxmpdu_bk = 2000;
4072         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4073         signalPollResults.addEntry(0, -42, 65, 54, sFreq);
4074         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4075                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4076         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4077         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4078         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
4079         mCmi.enableRssiPolling(true);
4080         connect();
4081         mLooper.dispatchAll();
4082         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
4083         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4084         mLooper.dispatchAll();
4085         // Two broadcasts, one when enabling RSSI polling and the other for RSSI polling after
4086         // IP configuration success resets the current level.
4087         assertRssiChangeBroadcastSent(2);
4088 
4089         // Same RSSI should not send another broadcast
4090         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4091         mLooper.dispatchAll();
4092         assertRssiChangeBroadcastSent(2);
4093 
4094         // Same signal level should not send another broadcast
4095         signalPollResults.addEntry(0, -43, 65, 54, sFreq);
4096         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4097         mLooper.dispatchAll();
4098         assertRssiChangeBroadcastSent(2);
4099 
4100         // Different signal level should send another broadcast
4101         signalPollResults.addEntry(0, -70, 65, 54, sFreq);
4102         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4103         mLooper.dispatchAll();
4104         assertRssiChangeBroadcastSent(3);
4105 
4106         // Setup for invalid RSSI poll, should not send broadcast
4107         signalPollResults.addEntry(0, -999, 65, 54, sFreq);
4108         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4109         mLooper.dispatchAll();
4110         assertRssiChangeBroadcastSent(3);
4111     }
4112 
4113     /**
4114      * Verify that RSSI polling with verbose logging enabled by the user will send RSSI broadcasts
4115      * if the RSSI has changed at all.
4116      */
4117     @Test
verifyConnectedModeRssiPollingWithSameSignalLevelVerboseLoggingEnabled()4118     public void verifyConnectedModeRssiPollingWithSameSignalLevelVerboseLoggingEnabled()
4119             throws Exception {
4120         when(mWifiGlobals.getVerboseLoggingLevel())
4121                 .thenReturn(WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED);
4122         final long startMillis = 1_500_000_000_100L;
4123         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4124         llStats.txmpdu_be = 1000;
4125         llStats.rxmpdu_bk = 2000;
4126         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4127         signalPollResults.addEntry(0, -42, 65, 54, sFreq);
4128         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4129                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4130         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4131         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4132         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
4133         mCmi.enableRssiPolling(true);
4134         connect();
4135         mLooper.dispatchAll();
4136         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
4137         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4138         mLooper.dispatchAll();
4139         // Two broadcasts, one when enabling RSSI polling and the other for RSSI polling after
4140         // IP configuration success resets the current level.
4141         assertRssiChangeBroadcastSent(2);
4142 
4143         // Same RSSI should not send another broadcast
4144         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4145         mLooper.dispatchAll();
4146         assertRssiChangeBroadcastSent(2);
4147 
4148         // Different RSSI but same signal level should send another broadcast since we're verbose.
4149         signalPollResults.addEntry(0, -43, 65, 54, sFreq);
4150         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
4151         mLooper.dispatchAll();
4152         assertRssiChangeBroadcastSent(3);
4153     }
4154 
4155     /**
4156      * Verify that RSSI polling starts/ stops/ one-offs are properly recorded in the capture buffer.
4157      */
4158     @Test
testCaptureBufferRssiOnOff()4159     public void testCaptureBufferRssiOnOff() throws Exception {
4160         // Log should indicate RSSI polling turned on.
4161         mCmi.enableRssiPolling(true);
4162         connect();
4163         verify(mWifiMetrics).logAsynchronousEvent(
4164                 eq(WIFI_IFACE_NAME),
4165                 eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED));
4166         reset(mWifiMetrics);
4167 
4168         // Normal RSSI polling loop. No events should be logged.
4169         mLooper.moveTimeForward(3000);
4170         mLooper.dispatchAll();
4171         verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt());
4172         verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt(), anyInt());
4173         reset(mWifiMetrics);
4174 
4175         // Normal RSSI polling loop. No events should be logged here either.
4176         mLooper.moveTimeForward(3000);
4177         mLooper.dispatchAll();
4178         verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt());
4179         verify(mWifiMetrics, never()).logAsynchronousEvent(anyString(), anyInt(), anyInt());
4180         reset(mWifiMetrics);
4181 
4182         // Turn off RSSI polling. This should show up in the capture buffer.
4183         mCmi.enableRssiPolling(false);
4184         mLooper.moveTimeForward(3000);
4185         mLooper.dispatchAll();
4186         verify(mWifiMetrics).logAsynchronousEvent(
4187                 eq(WIFI_IFACE_NAME),
4188                 eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_DISABLED));
4189         reset(mWifiMetrics);
4190     }
4191 
4192     /**
4193      * Verify that IP reachability problems are recorded in the capture buffer.
4194      */
4195     @Test
testCaptureBufferReachabilityLost()4196     public void testCaptureBufferReachabilityLost() throws Exception {
4197         // Log should indicate RSSI polling turned on.
4198         connect();
4199         verify(mWifiMetrics).logAsynchronousEvent(
4200                 eq(WIFI_IFACE_NAME),
4201                 eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_RSSI_POLLING_ENABLED));
4202         reset(mWifiMetrics);
4203 
4204         // Simulate an IP_REACHABILITY_LOST event.
4205         mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
4206         mLooper.dispatchAll();
4207         verify(mWifiMetrics).logAsynchronousEvent(
4208                 eq(WIFI_IFACE_NAME),
4209                 eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_LOST),
4210                 eq(-1));
4211         reset(mWifiMetrics);
4212 
4213         // Simulate an IP_REACHABILITY_FAILURE event.
4214         ReachabilityLossInfoParcelable lossInfo =
4215                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
4216         mIpClientCallback.onReachabilityFailure(lossInfo);
4217         mLooper.dispatchAll();
4218         verify(mWifiMetrics).logAsynchronousEvent(
4219                 eq(WIFI_IFACE_NAME),
4220                 eq(WifiUsabilityStatsEntry.CAPTURE_EVENT_TYPE_IP_REACHABILITY_FAILURE),
4221                 eq(ReachabilityLossReason.CONFIRM));
4222         reset(mWifiMetrics);
4223     }
4224 
4225     /**
4226      * Verify link bandwidth update in connected mode
4227      */
4228     @Test
verifyConnectedModeNetworkCapabilitiesBandwidthUpdate()4229     public void verifyConnectedModeNetworkCapabilitiesBandwidthUpdate() throws Exception {
4230         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(40_000);
4231         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(50_000);
4232         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
4233                 .thenReturn(Collections.emptySet());
4234         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
4235                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
4236         mCmi.enableRssiPolling(true);
4237         // Simulate the first connection.
4238         connectWithValidInitRssi(-42);
4239 
4240         // NetworkCapabilities should be always updated after the connection
4241         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
4242                 ArgumentCaptor.forClass(NetworkCapabilities.class);
4243         verify(mWifiInjector).makeWifiNetworkAgent(
4244                 networkCapabilitiesCaptor.capture(), any(), any(), any(), any());
4245         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
4246         assertNotNull(networkCapabilities);
4247         assertEquals(-42, mWifiInfo.getRssi());
4248         assertEquals(40_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
4249         assertEquals(50_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
4250         verify(mCmi.mNetworkAgent, times(2))
4251                 .sendNetworkCapabilitiesAndCache(networkCapabilitiesCaptor.capture());
4252 
4253         // Enable RSSI polling
4254         final long startMillis = 1_500_000_000_100L;
4255         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4256         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4257         signalPollResults.addEntry(0, -42, 65, 54, sFreq);
4258         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4259                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4260         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4261         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4262         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
4263         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(82_000);
4264         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(92_000);
4265         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
4266         mLooper.dispatchAll();
4267         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
4268         mLooper.dispatchAll();
4269 
4270         // NetworkCapabilities should be updated after a big change of bandwidth
4271         verify(mCmi.mNetworkAgent, times(3))
4272                 .sendNetworkCapabilitiesAndCache(networkCapabilitiesCaptor.capture());
4273         networkCapabilities = networkCapabilitiesCaptor.getValue();
4274         assertEquals(82_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
4275         assertEquals(92_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
4276 
4277         // NetworkCapabilities should be updated when the connected channel frequency is changed
4278         // For example due to AP channel switch announcement(CSA).
4279         WifiSignalPollResults signalPollResults1 = new WifiSignalPollResults();
4280         signalPollResults1.addEntry(0, -42, 65, 54, sFreq1);
4281         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults1);
4282         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
4283         mLooper.dispatchAll();
4284 
4285         verify(mCmi.mNetworkAgent, times(4))
4286                 .sendNetworkCapabilitiesAndCache(networkCapabilitiesCaptor.capture());
4287         assertEquals(sFreq1, mWifiInfo.getFrequency());
4288 
4289         // No update after a small change of bandwidth
4290         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(72_000);
4291         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(82_000);
4292         when(mClock.getWallClockMillis()).thenReturn(startMillis + 3333);
4293         mLooper.dispatchAll();
4294         verify(mCmi.mNetworkAgent, times(4))
4295                 .sendNetworkCapabilitiesAndCache(networkCapabilitiesCaptor.capture());
4296         networkCapabilities = networkCapabilitiesCaptor.getValue();
4297         assertEquals(82_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
4298         assertEquals(92_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
4299     }
4300 
4301     /**
4302      * Verify RSSI polling with verbose logging
4303      */
4304     @Test
verifyConnectedModeRssiPollingWithVerboseLogging()4305     public void verifyConnectedModeRssiPollingWithVerboseLogging() throws Exception {
4306         mCmi.enableVerboseLogging(true);
4307         verifyConnectedModeRssiPolling();
4308     }
4309 
4310     /**
4311      * Verify that calls to start and stop filtering multicast packets are passed on to the IpClient
4312      * instance.
4313      */
4314     @Test
verifyMcastLockManagerFilterControllerCallsUpdateIpClient()4315     public void verifyMcastLockManagerFilterControllerCallsUpdateIpClient() throws Exception {
4316         reset(mIpClient);
4317         WifiMulticastLockManager.FilterController filterController =
4318                 mCmi.getMcastLockManagerFilterController();
4319         filterController.startFilteringMulticastPackets();
4320         verify(mIpClient).setMulticastFilter(eq(true));
4321         filterController.stopFilteringMulticastPackets();
4322         verify(mIpClient).setMulticastFilter(eq(false));
4323     }
4324 
4325     /**
4326      * Verifies that when
4327      * 1. Global feature support flag is set to false
4328      * 2. connected MAC randomization is on and
4329      * 3. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_AUTO and
4330      * 4. randomized MAC for the network to connect to is different from the current MAC.
4331      *
4332      * The factory MAC address is used for the connection, and no attempt is made to change it.
4333      */
4334     @Test
testConnectedMacRandomizationNotSupported()4335     public void testConnectedMacRandomizationNotSupported() throws Exception {
4336         // reset mWifiNative since initializeCmi() was called in setup()
4337         resetWifiNative();
4338 
4339         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(false);
4340         initializeCmi();
4341         initializeAndAddNetworkAndVerifySuccess();
4342 
4343         connect();
4344         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4345         verify(mWifiNative, never()).setStaMacAddress(any(), any());
4346         // try to retrieve factory MAC address (once at bootup, once for this connection)
4347         verify(mSettingsConfigStore, times(2)).get(any());
4348     }
4349 
4350     /**
4351      * Verifies that when
4352      * 1. connected MAC randomization is on and
4353      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_AUTO and
4354      * 3. current MAC set to the driver is a randomized MAC address.
4355      * 4. SSID of network to connect is in the MAC randomization forced disable list.
4356      *
4357      * Then the current MAC will be set to the factory MAC when CMD_START_CONNECT executes.
4358      */
4359     @Test
testConnectedMacRandomizationRandomizationForceDisabled()4360     public void testConnectedMacRandomizationRandomizationForceDisabled() throws Exception {
4361         initializeAndAddNetworkAndVerifySuccess();
4362 
4363         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
4364                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
4365         mResources.setStringArray(R.array.config_wifiForceDisableMacRandomizationSsidList,
4366                 new String[]{mConnectedNetwork.SSID});
4367 
4368         connect();
4369         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS);
4370         verify(mWifiMetrics).logStaEvent(
4371                 eq(WIFI_IFACE_NAME), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4372         verify(mWifiConfigManager).addOrUpdateNetwork(any(), eq(Process.SYSTEM_UID));
4373         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4374     }
4375 
4376     @Test
testConnectedMacRandomizationForceDisabledSsidPrefix()4377     public void testConnectedMacRandomizationForceDisabledSsidPrefix() throws Exception {
4378         initializeAndAddNetworkAndVerifySuccess();
4379 
4380         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
4381                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
4382 
4383         Set<String> ssidPrefixSet = new ArraySet<>();
4384         // Take the prefix of 2 characters, which should include the " and the first letter of
4385         // actual SSID
4386         ssidPrefixSet.add(mConnectedNetwork.SSID.substring(0, 2));
4387         when(mWifiGlobals.getMacRandomizationUnsupportedSsidPrefixes()).thenReturn(ssidPrefixSet);
4388 
4389         // Verify MAC randomization is disabled
4390         connect();
4391         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS);
4392         verify(mWifiMetrics).logStaEvent(
4393                 eq(WIFI_IFACE_NAME), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4394         verify(mWifiConfigManager).addOrUpdateNetwork(any(), eq(Process.SYSTEM_UID));
4395         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4396     }
4397 
4398     /**
4399      * Verifies that when
4400      * 1. connected MAC randomization is on and
4401      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_AUTO and
4402      * 3. randomized MAC for the network to connect to is different from the current MAC.
4403      *
4404      * Then the current MAC gets set to the randomized MAC when CMD_START_CONNECT executes.
4405      */
4406     @Test
testConnectedMacRandomizationRandomizationPersistentDifferentMac()4407     public void testConnectedMacRandomizationRandomizationPersistentDifferentMac()
4408             throws Exception {
4409         initializeAndAddNetworkAndVerifySuccess();
4410 
4411         connect();
4412         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
4413         verify(mWifiMetrics).logStaEvent(
4414                 eq(WIFI_IFACE_NAME), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4415         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4416     }
4417 
4418     /**
4419      * Verifies that when
4420      * 1. connected MAC randomization is on and
4421      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_AUTO and
4422      * 3. randomized MAC for the network to connect to is same as the current MAC.
4423      *
4424      * Then MAC change should not occur when CMD_START_CONNECT executes.
4425      */
4426     @Test
testConnectedMacRandomizationRandomizationPersistentSameMac()4427     public void testConnectedMacRandomizationRandomizationPersistentSameMac() throws Exception {
4428         initializeAndAddNetworkAndVerifySuccess();
4429 
4430         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
4431                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
4432 
4433         connect();
4434         verify(mWifiNative, never()).setStaMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
4435         verify(mWifiMetrics, never()).logStaEvent(
4436                 any(), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4437         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4438     }
4439 
4440     /** Verifies connecting to secondary DBS network with Mac randomization, the MAC address is
4441      * the expected secondary Mac address.
4442      * @throws Exception
4443      */
4444     @Test
testConnectedMacRandomizationRandomizationSecondaryDbs()4445     public void testConnectedMacRandomizationRandomizationSecondaryDbs()
4446             throws Exception {
4447         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED);
4448         when(mClientModeManager.isSecondaryInternet()).thenReturn(true);
4449         when(mClientModeManager.isSecondaryInternetDbsAp()).thenReturn(true);
4450         initializeAndAddNetworkAndVerifySuccess();
4451         connect();
4452         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS_SECONDARY_DBS);
4453         verify(mWifiMetrics).logStaEvent(
4454                 eq(WIFI_IFACE_NAME), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4455         assertEquals(TEST_LOCAL_MAC_ADDRESS_SECONDARY_DBS.toString(), mWifiInfo.getMacAddress());
4456     }
4457 
4458     /**
4459      * Verifies that when
4460      * 1. connected MAC randomization is on and
4461      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and
4462      * 3. current MAC address is not the factory MAC.
4463      *
4464      * Then the current MAC gets set to the factory MAC when CMD_START_CONNECT executes.
4465      * @throws Exception
4466      */
4467     @Test
testConnectedMacRandomizationRandomizationNoneDifferentMac()4468     public void testConnectedMacRandomizationRandomizationNoneDifferentMac() throws Exception {
4469         initializeAndAddNetworkAndVerifySuccess();
4470 
4471         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
4472                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
4473 
4474         WifiConfiguration config = new WifiConfiguration();
4475         config.SSID = TEST_SSID;
4476         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
4477         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
4478         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4479 
4480         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4481         mLooper.dispatchAll();
4482 
4483         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_GLOBAL_MAC_ADDRESS);
4484         verify(mWifiMetrics).logStaEvent(
4485                 eq(WIFI_IFACE_NAME), eq(StaEvent.TYPE_MAC_CHANGE), any(WifiConfiguration.class));
4486         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4487     }
4488 
4489     /**
4490      * Verifies that when
4491      * 1. connected MAC randomization is on and
4492      * 2. macRandomizationSetting of the WifiConfiguration is RANDOMIZATION_NONE and
4493      *
4494      * Then the factory MAC should be used to connect to the network.
4495      * @throws Exception
4496      */
4497     @Test
testConnectedMacRandomizationRandomizationNoneSameMac()4498     public void testConnectedMacRandomizationRandomizationNoneSameMac() throws Exception {
4499         initializeAndAddNetworkAndVerifySuccess();
4500 
4501         clearInvocations(mWifiNative, mSettingsConfigStore);
4502 
4503         WifiConfiguration config = new WifiConfiguration();
4504         config.SSID = TEST_SSID;
4505         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
4506         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
4507         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4508 
4509         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4510         mLooper.dispatchAll();
4511 
4512         verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS);
4513         verify(mWifiNative, never()).getStaFactoryMacAddress(WIFI_IFACE_NAME);
4514         verify(mSettingsConfigStore, never()).put(
4515                 WIFI_STA_FACTORY_MAC_ADDRESS, TEST_GLOBAL_MAC_ADDRESS.toString());
4516 
4517         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4518 
4519         // Now disconnect & reconnect - should use the cached factory MAC address.
4520         mCmi.disconnect();
4521         mLooper.dispatchAll();
4522 
4523         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4524         mLooper.dispatchAll();
4525 
4526         verify(mSettingsConfigStore, times(2)).get(WIFI_STA_FACTORY_MAC_ADDRESS);
4527         // No new call to retrieve & store factory MAC address.
4528         verify(mWifiNative, never()).getStaFactoryMacAddress(WIFI_IFACE_NAME);
4529         verify(mSettingsConfigStore, never()).put(
4530                 WIFI_STA_FACTORY_MAC_ADDRESS, TEST_GLOBAL_MAC_ADDRESS.toString());
4531     }
4532 
4533     /**
4534      * Verifies that WifiInfo returns DEFAULT_MAC_ADDRESS as mac address when Connected MAC
4535      * Randomization is on and the device is not connected to a wifi network.
4536      */
4537     @Test
testWifiInfoReturnDefaultMacWhenDisconnectedWithRandomization()4538     public void testWifiInfoReturnDefaultMacWhenDisconnectedWithRandomization() throws Exception {
4539         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
4540                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
4541 
4542         connect();
4543         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
4544 
4545         DisconnectEventInfo disconnectEventInfo =
4546                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
4547         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
4548         mLooper.dispatchAll();
4549         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
4550                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
4551                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
4552         mLooper.dispatchAll();
4553 
4554         assertEquals("DisconnectedState", getCurrentState().getName());
4555         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mWifiInfo.getMacAddress());
4556         assertFalse(mWifiInfo.hasRealMacAddress());
4557     }
4558 
4559     /**
4560      * Verifies that we don't set MAC address when config returns an invalid MAC address.
4561      */
4562     @Test
testDoNotSetMacWhenInvalid()4563     public void testDoNotSetMacWhenInvalid() throws Exception {
4564         initializeAndAddNetworkAndVerifySuccess();
4565 
4566         WifiConfiguration config = new WifiConfiguration();
4567         config.SSID = TEST_SSID;
4568         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
4569         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
4570         config.setRandomizedMacAddress(MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS));
4571         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(0)).thenReturn(config);
4572 
4573         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4574         mLooper.dispatchAll();
4575 
4576         // setStaMacAddress is invoked once when ClientModeImpl starts to prevent leak of factory
4577         // MAC.
4578         verify(mWifiNative).setStaMacAddress(eq(WIFI_IFACE_NAME), any(MacAddress.class));
4579     }
4580 
4581     /**
4582      * Verify that we don't crash when WifiNative returns null as the current MAC address.
4583      * @throws Exception
4584      */
4585     @Test
testMacRandomizationWifiNativeReturningNull()4586     public void testMacRandomizationWifiNativeReturningNull() throws Exception {
4587         when(mWifiNative.getMacAddress(anyString())).thenReturn(null);
4588         initializeAndAddNetworkAndVerifySuccess();
4589 
4590         connect();
4591         verify(mWifiNative).setStaMacAddress(WIFI_IFACE_NAME, TEST_LOCAL_MAC_ADDRESS);
4592     }
4593 
4594     /**
4595      * Verifies that a notification is posted when a connection failure happens on a network
4596      * in the hotlist. Then verify that tapping on the notification launches an dialog, which
4597      * could be used to set the randomization setting for a network to "Trusted".
4598      */
4599     @Test
testConnectionFailureSendRandomizationSettingsNotification()4600     public void testConnectionFailureSendRandomizationSettingsNotification() throws Exception {
4601         when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true);
4602         // Setup CONNECT_MODE & a WifiConfiguration
4603         initializeAndAddNetworkAndVerifySuccess();
4604         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, TEST_BSSID_STR);
4605         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
4606                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
4607                         WifiManager.ERROR_AUTH_FAILURE_TIMEOUT, -1));
4608         mLooper.dispatchAll();
4609 
4610         WifiConfiguration config = mCmi.getConnectedWifiConfiguration();
4611         verify(mConnectionFailureNotifier)
4612                 .showFailedToConnectDueToNoRandomizedMacSupportNotification(FRAMEWORK_NETWORK_ID);
4613     }
4614 
4615     /**
4616      * Verifies that a notification is not posted when a wrong password failure happens on a
4617      * network in the hotlist.
4618      */
4619     @Test
testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword()4620     public void testNotCallingIsInFlakyRandomizationSsidHotlistOnWrongPassword() throws Exception {
4621         when(mWifiConfigManager.isInFlakyRandomizationSsidHotlist(anyInt())).thenReturn(true);
4622         // Setup CONNECT_MODE & a WifiConfiguration
4623         initializeAndAddNetworkAndVerifySuccess();
4624         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, TEST_BSSID_STR);
4625         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
4626                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
4627                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
4628         mLooper.dispatchAll();
4629 
4630         verify(mConnectionFailureNotifier, never())
4631                 .showFailedToConnectDueToNoRandomizedMacSupportNotification(anyInt());
4632     }
4633 
4634     /**
4635      * Verifies that CMD_START_CONNECT make WifiDiagnostics report
4636      * CONNECTION_EVENT_STARTED
4637      * @throws Exception
4638      */
4639     @Test
testReportConnectionEventIsCalledAfterCmdStartConnect()4640     public void testReportConnectionEventIsCalledAfterCmdStartConnect() throws Exception {
4641         // Setup CONNECT_MODE & a WifiConfiguration
4642         initializeAndAddNetworkAndVerifySuccess();
4643         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4644         verify(mWifiDiagnostics, never()).reportConnectionEvent(
4645                 eq(WifiDiagnostics.CONNECTION_EVENT_STARTED), any());
4646         mLooper.dispatchAll();
4647         verify(mWifiDiagnostics).reportConnectionEvent(
4648                 eq(WifiDiagnostics.CONNECTION_EVENT_STARTED), any());
4649     }
4650 
4651     @Test
testApNoResponseTriggerTimeout()4652     public void testApNoResponseTriggerTimeout() throws Exception {
4653         initializeAndAddNetworkAndVerifySuccess();
4654         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4655         mLooper.dispatchAll();
4656         verify(mWifiBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(),
4657                 anyInt(), anyInt());
4658 
4659         mLooper.moveTimeForward(ClientModeImpl.CONNECTING_WATCHDOG_TIMEOUT_MS);
4660         mLooper.dispatchAll();
4661         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(any(), any(),
4662                 eq(WifiBlocklistMonitor.REASON_FAILURE_NO_RESPONSE), anyInt());
4663         verify(mWifiDiagnostics).reportConnectionEvent(
4664                 eq(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT), any());
4665     }
4666 
4667     @Test
testApNoResponseTimerCanceledAfterConnectionSuccess()4668     public void testApNoResponseTimerCanceledAfterConnectionSuccess() throws Exception {
4669         connect();
4670         mLooper.moveTimeForward(ClientModeImpl.CONNECTING_WATCHDOG_TIMEOUT_MS);
4671         mLooper.dispatchAll();
4672         verify(mWifiBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(),
4673                 anyInt(), anyInt());
4674         verify(mWifiDiagnostics, never()).reportConnectionEvent(
4675                 eq(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT), any());
4676     }
4677 
verifyConnectionEventTimeoutDoesNotOccur()4678     private void verifyConnectionEventTimeoutDoesNotOccur() {
4679         mLooper.moveTimeForward(ClientModeImpl.CONNECTING_WATCHDOG_TIMEOUT_MS);
4680         mLooper.dispatchAll();
4681         verify(mWifiDiagnostics, never()).reportConnectionEvent(
4682                 eq(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT), any());
4683     }
4684 
4685     /**
4686      * Verifies that association failures make WifiDiagnostics report CONNECTION_EVENT_FAILED
4687      * and then cancel any pending timeouts.
4688      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
4689      * @throws Exception
4690      */
4691     @Test
testReportConnectionEventIsCalledAfterAssociationFailure()4692     public void testReportConnectionEventIsCalledAfterAssociationFailure() throws Exception {
4693         mConnectedNetwork.getNetworkSelectionStatus()
4694                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq)
4695                         .getScanResult());
4696         // Setup CONNECT_MODE & a WifiConfiguration
4697         initializeAndAddNetworkAndVerifySuccess();
4698         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4699         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
4700                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
4701                         ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, false));
4702         verify(mWifiDiagnostics, never()).reportConnectionEvent(
4703                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED), any());
4704         mLooper.dispatchAll();
4705         verify(mWifiDiagnostics).reportConnectionEvent(
4706                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED), any());
4707         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
4708                 mClientModeManager,
4709                 WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
4710                 WifiMetricsProto.ConnectionEvent.ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA,
4711                 TEST_BSSID_STR,
4712                 mTestConfig);
4713         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
4714                 eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION),
4715                 eq(mTestConfig), eq(TEST_BSSID_STR), eq(WifiMetricsProto.ConnectionEvent
4716                         .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA));
4717         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
4718                 eq(WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION),
4719                 eq(mTestConfig), eq(null));
4720         verify(mWifiMetrics, never())
4721                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
4722         verifyConnectionEventTimeoutDoesNotOccur();
4723 
4724         clearInvocations(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
4725                 mWifiNetworkSuggestionsManager);
4726 
4727         // Now trigger a disconnect event from supplicant, this should be ignored since the
4728         // connection tracking should have already ended.
4729         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
4730                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false));
4731         mLooper.dispatchAll();
4732 
4733         verifyNoMoreInteractions(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
4734                 mWifiNetworkSuggestionsManager);
4735     }
4736 
4737     /**
4738      * Verifies that authentication failures make WifiDiagnostics report
4739      * CONNECTION_EVENT_FAILED and then cancel any pending timeouts.
4740      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
4741      * @throws Exception
4742      */
4743     @Test
testReportConnectionEventIsCalledAfterAuthenticationFailure()4744     public void testReportConnectionEventIsCalledAfterAuthenticationFailure() throws Exception {
4745         mConnectedNetwork.getNetworkSelectionStatus()
4746                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq)
4747                         .getScanResult());
4748         // Setup CONNECT_MODE & a WifiConfiguration
4749         initializeAndAddNetworkAndVerifySuccess();
4750         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4751         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
4752                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
4753                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
4754         mLooper.dispatchAll();
4755         verify(mWifiDiagnostics).reportConnectionEvent(
4756                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED), any());
4757         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
4758                 mClientModeManager,
4759                 WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
4760                 WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD, TEST_BSSID_STR,
4761                 mTestConfig);
4762         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
4763                 eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE),
4764                 eq(mTestConfig), eq(TEST_BSSID_STR), eq(WifiMetricsProto.ConnectionEvent
4765                         .AUTH_FAILURE_WRONG_PSWD));
4766         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
4767                 eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE),
4768                 eq(mTestConfig), eq(null));
4769         verify(mWifiMetrics, never())
4770                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
4771         verifyConnectionEventTimeoutDoesNotOccur();
4772 
4773         clearInvocations(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
4774                 mWifiNetworkSuggestionsManager);
4775 
4776         // Now trigger a disconnect event from supplicant, this should be ignored since the
4777         // connection tracking should have already ended.
4778         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
4779                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false));
4780         mLooper.dispatchAll();
4781 
4782         verifyNoMoreInteractions(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
4783                 mWifiNetworkSuggestionsManager);
4784     }
4785 
4786     /**
4787      * Verify that if a NETWORK_DISCONNECTION_EVENT is received in L3ConnectedState, then an
4788      * abnormal disconnect is reported to WifiBlocklistMonitor.
4789      */
4790     @Test
testAbnormalDisconnectNotifiesWifiBlocklistMonitor()4791     public void testAbnormalDisconnectNotifiesWifiBlocklistMonitor() throws Exception {
4792         // trigger RSSI poll to update WifiInfo
4793         mCmi.enableRssiPolling(true);
4794         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4795         llStats.txmpdu_be = 1000;
4796         llStats.rxmpdu_bk = 2000;
4797         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4798         signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq);
4799         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4800                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4801         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4802         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4803 
4804         connect();
4805         mLooper.dispatchAll();
4806         DisconnectEventInfo disconnectEventInfo =
4807                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
4808         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
4809         mLooper.dispatchAll();
4810 
4811         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
4812                 eq(mConnectedNetwork), eq(WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT),
4813                 anyInt());
4814     }
4815 
4816     @Test
testAbnormalDisconnectIpReachabilityLostNotifiesWifiBlocklistMonitor()4817     public void testAbnormalDisconnectIpReachabilityLostNotifiesWifiBlocklistMonitor()
4818             throws Exception {
4819         // trigger RSSI poll to update WifiInfo
4820         mCmi.enableRssiPolling(true);
4821         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
4822         llStats.txmpdu_be = 1000;
4823         llStats.rxmpdu_bk = 2000;
4824         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
4825         signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq);
4826         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
4827                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
4828         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
4829         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
4830 
4831         // Connect, trigger CMD_IP_REACHABILITY_LOST and verifiy REASON_ABNORMAL_DISCONNECT is
4832         // sent to mWifiBlocklistMonitor
4833         connect();
4834         mLooper.dispatchAll();
4835         DisconnectEventInfo disconnectEventInfo =
4836                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
4837         mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
4838         mLooper.dispatchAll();
4839 
4840         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
4841                 eq(mConnectedNetwork), eq(WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT),
4842                 anyInt());
4843     }
4844 
4845     /**
4846      * Verify that ClientModeImpl notifies WifiBlocklistMonitor correctly when the RSSI is
4847      * too low.
4848      */
4849     @Test
testNotifiesWifiBlocklistMonitorLowRssi()4850     public void testNotifiesWifiBlocklistMonitorLowRssi() throws Exception {
4851         int testLowRssi = -80;
4852         initializeAndAddNetworkAndVerifySuccess();
4853         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0,
4854                 ClientModeImpl.SUPPLICANT_BSSID_ANY);
4855         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
4856                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, true));
4857         when(mWifiConfigManager.findScanRssi(eq(FRAMEWORK_NETWORK_ID), anyInt()))
4858                 .thenReturn(testLowRssi);
4859         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
4860                 .thenReturn(mScanDetailCache);
4861         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
4862                 getGoogleGuestScanDetail(testLowRssi, TEST_BSSID_STR, sFreq));
4863         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
4864                 getGoogleGuestScanDetail(testLowRssi, TEST_BSSID_STR, sFreq).getScanResult());
4865         mLooper.dispatchAll();
4866 
4867         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(TEST_BSSID_STR, mTestConfig,
4868                 WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, testLowRssi);
4869     }
4870 
4871     /**
4872      * Verify that the recent failure association status is updated properly when
4873      * ASSOC_REJECTED_TEMPORARILY occurs.
4874      */
4875     @Test
testAssocRejectedTemporarilyUpdatesRecentAssociationFailureStatus()4876     public void testAssocRejectedTemporarilyUpdatesRecentAssociationFailureStatus()
4877             throws Exception {
4878         initializeAndAddNetworkAndVerifySuccess();
4879         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4880         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
4881                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
4882                         ISupplicantStaIfaceCallback.StatusCode.ASSOC_REJECTED_TEMPORARILY,
4883                         false));
4884         mLooper.dispatchAll();
4885         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
4886                 eq(WifiConfiguration.RECENT_FAILURE_REFUSED_TEMPORARILY));
4887     }
4888 
4889     /**
4890      * Verify that WifiScoreCard and WifiBlocklistMonitor are notified properly when
4891      * disconnection occurs in middle of connection states.
4892      */
4893     @Test
testDisconnectConnecting()4894     public void testDisconnectConnecting() throws Exception {
4895         initializeAndAddNetworkAndVerifySuccess();
4896         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
4897         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
4898                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR,
4899                         ISupplicantStaIfaceCallback.ReasonCode.FOURWAY_HANDSHAKE_TIMEOUT,
4900                         false));
4901         mLooper.dispatchAll();
4902         verify(mWifiScoreCard).noteConnectionFailure(any(), anyInt(), anyString(), anyInt());
4903         verify(mWifiScoreCard).resetConnectionState(WIFI_IFACE_NAME);
4904         // Verify that the WifiBlocklistMonitor is notified of a non-locally generated disconnect
4905         // that occurred mid connection attempt.
4906         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(anyString(), eq(mTestConfig),
4907                 eq(WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING), anyInt());
4908         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
4909                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES));
4910     }
4911 
triggerConnectionWithConsecutiveFailure()4912     private void triggerConnectionWithConsecutiveFailure() throws Exception {
4913         when(mPerNetworkRecentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE))
4914                 .thenReturn(WifiBlocklistMonitor.NUM_CONSECUTIVE_FAILURES_PER_NETWORK_EXP_BACKOFF);
4915         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0, TEST_BSSID_STR);
4916         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
4917                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR,
4918                         ISupplicantStaIfaceCallback.ReasonCode.FOURWAY_HANDSHAKE_TIMEOUT,
4919                         false));
4920         mLooper.dispatchAll();
4921     }
4922 
4923     /**
4924      * Verify that the WifiConfigManager is notified when a network experiences consecutive
4925      * connection failures.
4926      */
4927     @Test
testDisableNetworkConsecutiveFailures()4928     public void testDisableNetworkConsecutiveFailures() throws Exception {
4929         initializeAndAddNetworkAndVerifySuccess();
4930         triggerConnectionWithConsecutiveFailure();
4931 
4932         verify(mWifiScoreCard).noteConnectionFailure(any(), anyInt(), anyString(), anyInt());
4933         verify(mWifiScoreCard).resetConnectionState(WIFI_IFACE_NAME);
4934         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(anyString(), eq(mTestConfig),
4935                 eq(WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING), anyInt());
4936         verify(mWifiConfigManager).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
4937                 WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES);
4938     }
4939 
4940     @Test
testDisableNetworkConsecutiveFailuresDoNotOverrideDisabledNetworks()4941     public void testDisableNetworkConsecutiveFailuresDoNotOverrideDisabledNetworks()
4942             throws Exception {
4943         initializeAndAddNetworkAndVerifySuccess();
4944         // Now mock the connecting network to be already disabled
4945         mTestConfig.getNetworkSelectionStatus().setNetworkSelectionStatus(
4946                 NETWORK_SELECTION_PERMANENTLY_DISABLED);
4947         triggerConnectionWithConsecutiveFailure();
4948 
4949         verify(mWifiScoreCard).noteConnectionFailure(any(), anyInt(), anyString(), anyInt());
4950         verify(mWifiScoreCard).resetConnectionState(WIFI_IFACE_NAME);
4951         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(anyString(), eq(mTestConfig),
4952                 eq(WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING), anyInt());
4953 
4954         // should not disable due to DISABLED_CONSECUTIVE_FAILURES
4955         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
4956                 WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES);
4957     }
4958 
4959     /**
4960      * Verify that a network that was successfully connected to before will get permanently disabled
4961      * for wrong password when the number of wrong password failures exceed a threshold.
4962      */
4963     @Test
testUpgradeMultipleWrongPasswordFailuresToPermanentWrongPassword()4964     public void testUpgradeMultipleWrongPasswordFailuresToPermanentWrongPassword()
4965             throws Exception {
4966         initializeAndAddNetworkAndVerifySuccess();
4967         startConnectSuccess();
4968 
4969         // mock the target network to be something that had been successfully connected before
4970         WifiConfiguration config = createTestNetwork(false);
4971         config.getNetworkSelectionStatus().setHasEverConnected(true);
4972         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
4973 
4974         // mock number of wrong password failures to be less than the threshold
4975         when(mPerNetworkRecentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE))
4976                 .thenReturn(ClientModeImpl.THRESHOLD_TO_PERM_WRONG_PASSWORD - 1);
4977 
4978         // trigger the wrong password failure
4979         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
4980                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
4981                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
4982         DisconnectEventInfo disconnectEventInfo =
4983                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
4984         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
4985         mLooper.dispatchAll();
4986 
4987         // should not disable network permanently
4988         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
4989                 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
4990 
4991         // Bump up the wrong password count to reach the threshold and verify the network is
4992         // disabled permanently.
4993         when(mPerNetworkRecentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE))
4994                 .thenReturn(ClientModeImpl.THRESHOLD_TO_PERM_WRONG_PASSWORD);
4995 
4996         startConnectSuccess();
4997         // trigger the wrong password failure
4998         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
4999                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
5000                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
5001         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
5002         mLooper.dispatchAll();
5003 
5004         verify(mWifiConfigManager).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
5005                 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
5006     }
5007 
5008     /**
5009      * Verify that the recent failure association status is updated properly when
5010      * DENIED_POOR_CHANNEL_CONDITIONS occurs.
5011      */
5012     @Test
testAssocRejectedPoorChannelConditionsUpdatesRecentAssociationFailureStatus()5013     public void testAssocRejectedPoorChannelConditionsUpdatesRecentAssociationFailureStatus()
5014             throws Exception {
5015         initializeAndAddNetworkAndVerifySuccess();
5016         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5017         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5018                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
5019                         ISupplicantStaIfaceCallback.StatusCode.DENIED_POOR_CHANNEL_CONDITIONS,
5020                         false));
5021         mLooper.dispatchAll();
5022         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
5023                 eq(WifiConfiguration.RECENT_FAILURE_POOR_CHANNEL_CONDITIONS));
5024     }
5025 
5026     /**
5027      * Verify that the recent failure association status is updated properly when a disconnection
5028      * with reason code DISASSOC_AP_BUSY occurs.
5029      */
5030     @Test
testNetworkDisconnectionApBusyUpdatesRecentAssociationFailureStatus()5031     public void testNetworkDisconnectionApBusyUpdatesRecentAssociationFailureStatus()
5032             throws Exception {
5033         connect();
5034         // Disconnection with reason = DISASSOC_AP_BUSY
5035         DisconnectEventInfo disconnectEventInfo =
5036                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR,
5037                         SupplicantStaIfaceHal.StaIfaceReasonCode.DISASSOC_AP_BUSY, false);
5038         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
5039         mLooper.dispatchAll();
5040         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
5041                 eq(WifiConfiguration.RECENT_FAILURE_DISCONNECTION_AP_BUSY));
5042         verify(mWifiBlocklistMonitor).blockBssidForDurationMs(any(), any(),
5043                 anyLong(), eq(WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA), anyInt());
5044     }
5045 
5046     /**
5047      * Verify that the recent failure association status is updated properly when a disconnection
5048      * with reason code DISASSOC_AP_BUSY occurs.
5049      */
5050     @Test
testMidConnectionDisconnectionApBusyUpdatesRecentAssociationFailureStatus()5051     public void testMidConnectionDisconnectionApBusyUpdatesRecentAssociationFailureStatus()
5052             throws Exception {
5053         initializeAndAddNetworkAndVerifySuccess();
5054         startConnectSuccess();
5055         assertEquals("L2ConnectingState", getCurrentState().getName());
5056 
5057         // Disconnection with reason = DISASSOC_AP_BUSY
5058         DisconnectEventInfo disconnectEventInfo =
5059                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 5, false);
5060         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
5061         mLooper.dispatchAll();
5062         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
5063                 eq(WifiConfiguration.RECENT_FAILURE_DISCONNECTION_AP_BUSY));
5064     }
5065 
5066     /**
5067      * Verify that the recent failure association status is updated properly when
5068      * ASSOCIATION_REJECTION_EVENT with OCE RSSI based association rejection attribute is received.
5069      */
5070     @Test
testOceRssiBasedAssociationRejectionUpdatesRecentAssociationFailureStatus()5071     public void testOceRssiBasedAssociationRejectionUpdatesRecentAssociationFailureStatus()
5072             throws Exception {
5073         assumeTrue(SdkLevel.isAtLeastS());
5074         initializeAndAddNetworkAndVerifySuccess();
5075         AssociationRejectionData assocRejectData = new AssociationRejectionData();
5076         assocRejectData.ssid = NativeUtil.decodeSsid(TEST_SSID);
5077         assocRejectData.bssid = NativeUtil.macAddressToByteArray(TEST_BSSID_STR);
5078         assocRejectData.statusCode =
5079                 ISupplicantStaIfaceCallback.StatusCode.DENIED_POOR_CHANNEL_CONDITIONS;
5080         assocRejectData.isOceRssiBasedAssocRejectAttrPresent = true;
5081         assocRejectData.oceRssiBasedAssocRejectData.retryDelayS = 10;
5082         assocRejectData.oceRssiBasedAssocRejectData.deltaRssi = 20;
5083         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5084         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5085                 new AssocRejectEventInfo(assocRejectData));
5086         mLooper.dispatchAll();
5087         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
5088                 eq(WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION));
5089     }
5090 
5091     /**
5092      * Verify that the recent failure association status is updated properly when
5093      * ASSOCIATION_REJECTION_EVENT with MBO association disallowed attribute is received.
5094      */
5095     @Test
testMboAssocDisallowedIndInAssocRejectUpdatesRecentAssociationFailureStatus()5096     public void testMboAssocDisallowedIndInAssocRejectUpdatesRecentAssociationFailureStatus()
5097             throws Exception {
5098         assumeTrue(SdkLevel.isAtLeastS());
5099         initializeAndAddNetworkAndVerifySuccess();
5100         AssociationRejectionData assocRejectData = new AssociationRejectionData();
5101         assocRejectData.ssid = NativeUtil.decodeSsid(TEST_SSID);
5102         assocRejectData.bssid = NativeUtil.macAddressToByteArray(TEST_BSSID_STR);
5103         assocRejectData.statusCode =
5104                 ISupplicantStaIfaceCallback.StatusCode.DENIED_POOR_CHANNEL_CONDITIONS;
5105         assocRejectData.isMboAssocDisallowedReasonCodePresent = true;
5106         assocRejectData.mboAssocDisallowedReason = MboAssocDisallowedReasonCode
5107                 .MAX_NUM_STA_ASSOCIATED;
5108         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5109         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5110                 new AssocRejectEventInfo(assocRejectData));
5111         mLooper.dispatchAll();
5112         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
5113                 eq(WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED));
5114     }
5115 
5116     /**
5117      * Verifies that the WifiBlocklistMonitor is notified, but the WifiLastResortWatchdog is
5118      * not notified of association rejections of type REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA.
5119      * @throws Exception
5120      */
5121     @Test
testAssociationRejectionWithReasonApUnableToHandleNewStaUpdatesWatchdog()5122     public void testAssociationRejectionWithReasonApUnableToHandleNewStaUpdatesWatchdog()
5123             throws Exception {
5124         initializeAndAddNetworkAndVerifySuccess();
5125         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5126         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5127                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
5128                         ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, false));
5129         mLooper.dispatchAll();
5130         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
5131                 anyString(), anyString(), anyInt(), anyBoolean());
5132         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5133                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA),
5134                 anyInt());
5135     }
5136 
5137     /**
5138      * Verifies that the WifiBlocklistMonitor is notified, but the WifiLastResortWatchdog is
5139      * not notified of association rejections of type DENIED_INSUFFICIENT_BANDWIDTH.
5140      * @throws Exception
5141      */
5142     @Test
testAssociationRejectionWithReasonDeniedInsufficientBandwidth()5143     public void testAssociationRejectionWithReasonDeniedInsufficientBandwidth()
5144             throws Exception {
5145         initializeAndAddNetworkAndVerifySuccess();
5146         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5147         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5148                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR, ISupplicantStaIfaceCallback
5149                         .StatusCode.DENIED_INSUFFICIENT_BANDWIDTH, false));
5150         mLooper.dispatchAll();
5151         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
5152                 anyString(), anyString(), anyInt(), anyBoolean());
5153         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5154                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA),
5155                 anyInt());
5156     }
5157 
5158     /**
5159      * Verifies that WifiLastResortWatchdog and WifiBlocklistMonitor is notified of
5160      * general association rejection failures.
5161      * @throws Exception
5162      */
5163     @Test
testAssociationRejectionUpdatesWatchdog()5164     public void testAssociationRejectionUpdatesWatchdog() throws Exception {
5165         initializeAndAddNetworkAndVerifySuccess();
5166         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID);
5167         config.carrierId = CARRIER_ID_1;
5168         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5169         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5170                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false));
5171         mLooper.dispatchAll();
5172         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
5173                 anyString(), anyString(), anyInt(), anyBoolean());
5174         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5175                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION), anyInt());
5176         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionNonAuthFailure();
5177     }
5178 
testAssociationRejectionForRole(boolean isSecondary)5179     private void testAssociationRejectionForRole(boolean isSecondary) throws Exception {
5180         if (isSecondary) {
5181             when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED);
5182             when(mClientModeManager.isSecondaryInternet()).thenReturn(true);
5183         }
5184         when(mPerNetworkRecentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE))
5185                 .thenReturn(WifiBlocklistMonitor.NUM_CONSECUTIVE_FAILURES_PER_NETWORK_EXP_BACKOFF);
5186         initializeAndAddNetworkAndVerifySuccess();
5187         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5188         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
5189                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR,
5190                         ISupplicantStaIfaceCallback.StatusCode.SUPPORTED_CHANNEL_NOT_VALID, false));
5191         mLooper.dispatchAll();
5192         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5193                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION),
5194                 anyInt());
5195         if (isSecondary) {
5196             verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
5197                     WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
5198             verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
5199                     WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES);
5200             verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
5201                     anyString(), anyString(), anyInt(), anyBoolean());
5202         }
5203         else {
5204             verify(mWifiConfigManager).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
5205                     WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
5206             verify(mWifiConfigManager).updateNetworkSelectionStatus(FRAMEWORK_NETWORK_ID,
5207                     WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES);
5208             verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
5209                     anyString(), anyString(), anyInt(), anyBoolean());
5210         }
5211     }
5212 
5213     @Test
testAssociationRejectionPrimary()5214     public void testAssociationRejectionPrimary() throws Exception {
5215         testAssociationRejectionForRole(false);
5216     }
5217 
5218     @Test
testAssociationRejectionSecondary()5219     public void testAssociationRejectionSecondary() throws Exception {
5220         testAssociationRejectionForRole(true);
5221     }
5222 
5223     /**
5224      * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type
5225      * ERROR_AUTH_FAILURE_WRONG_PSWD.
5226      * @throws Exception
5227      */
5228     @Test
testFailureWrongPassIsIgnoredByWatchdog()5229     public void testFailureWrongPassIsIgnoredByWatchdog() throws Exception {
5230         // Setup CONNECT_MODE & a WifiConfiguration
5231         initializeAndAddNetworkAndVerifySuccess();
5232         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5233         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5234                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
5235                         SupplicantState.COMPLETED));
5236         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
5237                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
5238                         WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1));
5239         mLooper.dispatchAll();
5240         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
5241                 anyString(), anyString(), anyInt(), anyBoolean());
5242         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5243                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_WRONG_PASSWORD), anyInt());
5244     }
5245 
5246     /**
5247      * Verifies that WifiLastResortWatchdog is not notified of authentication failures of type
5248      * ERROR_AUTH_FAILURE_EAP_FAILURE.
5249      * @throws Exception
5250      */
5251     @Test
testEapFailureIsIgnoredByWatchdog()5252     public void testEapFailureIsIgnoredByWatchdog() throws Exception {
5253         // Setup CONNECT_MODE & a WifiConfiguration
5254         initializeAndAddNetworkAndVerifySuccess();
5255         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5256         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5257                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
5258                         SupplicantState.COMPLETED));
5259         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
5260                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
5261                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1));
5262         mLooper.dispatchAll();
5263         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
5264                 anyString(), anyString(), anyInt(), anyBoolean());
5265         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5266                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_EAP_FAILURE), anyInt());
5267     }
5268 
5269     /**
5270      * Verifies that WifiLastResortWatchdog is notified of other types of authentication failures.
5271      * @throws Exception
5272      */
5273     @Test
testAuthenticationFailureUpdatesWatchdog()5274     public void testAuthenticationFailureUpdatesWatchdog() throws Exception {
5275         // Setup CONNECT_MODE & a WifiConfiguration
5276         initializeAndAddNetworkAndVerifySuccess();
5277         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5278         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5279                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
5280                         SupplicantState.COMPLETED));
5281         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
5282                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
5283                         WifiManager.ERROR_AUTH_FAILURE_TIMEOUT, -1));
5284         mLooper.dispatchAll();
5285         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
5286                 anyString(), anyString(), anyInt(), anyBoolean());
5287         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(eq(TEST_BSSID_STR),
5288                 eq(mTestConfig), eq(WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE), anyInt());
5289     }
5290 
5291     /**
5292      * Verify that WifiBlocklistMonitor is notified of the SSID pre-connection so that it could
5293      * send down to firmware the list of blocked BSSIDs.
5294      */
5295     @Test
testBssidBlocklistSentToFirmwareAfterCmdStartConnect()5296     public void testBssidBlocklistSentToFirmwareAfterCmdStartConnect() throws Exception {
5297         initializeAndAddNetworkAndVerifySuccess();
5298         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5299         verify(mWifiBlocklistMonitor, never()).updateFirmwareRoamingConfiguration(
5300                 Set.of(TEST_SSID));
5301         mLooper.dispatchAll();
5302         verify(mWifiBlocklistMonitor).updateFirmwareRoamingConfiguration(Set.of(TEST_SSID));
5303         // But don't expect to see connection success yet
5304         verify(mWifiScoreCard, never()).noteIpConfiguration(any());
5305         // And certainly not validation success
5306         verify(mWifiScoreCard, never()).noteValidationSuccess(any());
5307     }
5308 
5309     /**
5310      * Verifies that dhcp failures make WifiDiagnostics report CONNECTION_EVENT_FAILED and then
5311      * cancel any pending timeouts.
5312      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
5313      * @throws Exception
5314      */
5315     @Test
testReportConnectionEventIsCalledAfterDhcpFailure()5316     public void testReportConnectionEventIsCalledAfterDhcpFailure() throws Exception {
5317         mConnectedNetwork.getNetworkSelectionStatus()
5318                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq)
5319                         .getScanResult());
5320         testDhcpFailure();
5321         verify(mWifiDiagnostics).reportConnectionEvent(
5322                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED), any());
5323         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
5324                 mClientModeManager,
5325                 WifiMetrics.ConnectionEvent.FAILURE_DHCP,
5326                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_BSSID_STR,
5327                 mTestConfig);
5328         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
5329                 eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class),
5330                 eq(TEST_BSSID_STR), eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN));
5331         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
5332                 eq(WifiMetrics.ConnectionEvent.FAILURE_DHCP), any(WifiConfiguration.class),
5333                 any(String.class));
5334         verify(mWifiMetrics, never())
5335                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
5336         verifyConnectionEventTimeoutDoesNotOccur();
5337     }
5338 
5339     /**
5340      * Verifies that a successful validation make WifiDiagnostics report CONNECTION_EVENT_SUCCEEDED
5341      * and then cancel any pending timeouts.
5342      * Also, send connection status to {@link WifiNetworkFactory} & {@link WifiConnectivityManager}.
5343      */
5344     @Test
testReportConnectionEventIsCalledAfterSuccessfulConnection()5345     public void testReportConnectionEventIsCalledAfterSuccessfulConnection() throws Exception {
5346         mConnectedNetwork.getNetworkSelectionStatus()
5347                 .setCandidate(getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR1, sFreq)
5348                         .getScanResult());
5349         connect();
5350         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5351                 mWifiNetworkAgentCallbackCaptor.capture());
5352         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5353                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
5354         mLooper.dispatchAll();
5355 
5356         verify(mWifiDiagnostics).reportConnectionEvent(
5357                 eq(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED), any());
5358         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
5359                 mClientModeManager,
5360                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
5361                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_BSSID_STR,
5362                 mConnectedNetwork);
5363         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
5364                 eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), eq(mConnectedNetwork),
5365                 eq(TEST_BSSID_STR), eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN));
5366         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
5367                 eq(WifiMetrics.ConnectionEvent.FAILURE_NONE), eq(mConnectedNetwork),
5368                 any(String.class));
5369         verify(mCmiMonitor).onInternetValidated(mClientModeManager);
5370         // BSSID different, record this connection.
5371         verify(mWifiMetrics).incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
5372         verifyConnectionEventTimeoutDoesNotOccur();
5373 
5374         // Disconnect now should not trigger handleConnectionAttemptEnded
5375         DisconnectEventInfo disconnectEventInfo =
5376                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
5377         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
5378         mLooper.dispatchAll();
5379 
5380         verify(mWifiMetrics, never()).endConnectionEvent(
5381                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
5382                 anyInt(), anyInt(), anyInt(), anyInt());
5383         verify(mWifiConnectivityManager, never()).handleConnectionAttemptEnded(
5384                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
5385                 anyInt(), any(), any());
5386     }
5387 
5388     /**
5389      * Verify that score card is notified of a connection attempt
5390      */
5391     @Test
testScoreCardNoteConnectionAttemptAfterCmdStartConnect()5392     public void testScoreCardNoteConnectionAttemptAfterCmdStartConnect() throws Exception {
5393         initializeAndAddNetworkAndVerifySuccess();
5394         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
5395         verify(mWifiScoreCard, never()).noteConnectionAttempt(any(), anyInt(), anyString());
5396         mLooper.dispatchAll();
5397         verify(mWifiScoreCard).noteConnectionAttempt(any(), anyInt(), anyString());
5398         verify(mWifiConfigManager).findScanRssi(anyInt(), anyInt());
5399         // But don't expect to see connection success yet
5400         verify(mWifiScoreCard, never()).noteIpConfiguration(any());
5401         // And certainly not validation success
5402         verify(mWifiScoreCard, never()).noteValidationSuccess(any());
5403 
5404     }
5405 
5406     /**
5407      * Verify that score card is notified of a successful connection
5408      */
5409     @Test
testScoreCardNoteConnectionComplete()5410     public void testScoreCardNoteConnectionComplete() throws Exception {
5411         Pair<String, String> l2KeyAndCluster = Pair.create("Wad", "Gab");
5412         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(l2KeyAndCluster);
5413         connect();
5414         mLooper.dispatchAll();
5415         verify(mWifiScoreCard).noteIpConfiguration(any());
5416         ArgumentCaptor<Layer2InformationParcelable> captor =
5417                 ArgumentCaptor.forClass(Layer2InformationParcelable.class);
5418         verify(mIpClient, atLeastOnce()).updateLayer2Information(captor.capture());
5419         final Layer2InformationParcelable info = captor.getValue();
5420         assertEquals(info.l2Key, "Wad");
5421         assertEquals(info.cluster, "Gab");
5422     }
5423 
5424     /**
5425      * Verifies that Layer2 information is updated only when supplicant state change moves
5426      * to COMPLETED and on Wi-Fi disconnection. ie when device connect, roam & disconnect.
5427      */
5428     @Test
testLayer2InformationUpdate()5429     public void testLayer2InformationUpdate() throws Exception {
5430         InOrder inOrder = inOrder(mIpClient);
5431         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(
5432                 Pair.create("Wad", "Gab"));
5433         // Simulate connection
5434         connect();
5435 
5436         inOrder.verify(mIpClient).updateLayer2Information(any());
5437         inOrder.verify(mIpClient).startProvisioning(any());
5438 
5439         // Simulate Roaming
5440         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(
5441                 Pair.create("aaa", "bbb"));
5442         // Now send a network connection (indicating a roam) event
5443         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
5444                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null));
5445         mLooper.dispatchAll();
5446 
5447         inOrder.verify(mIpClient).updateLayer2Information(any());
5448 
5449         // Simulate disconnection
5450         when(mWifiScoreCard.getL2KeyAndGroupHint(any())).thenReturn(new Pair<>(null, null));
5451         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5452                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
5453                         SupplicantState.DISCONNECTED));
5454         mLooper.dispatchAll();
5455 
5456         verify(mWifiScoreCard, times(3)).getL2KeyAndGroupHint(any());
5457         verify(mIpClient, times(3)).updateLayer2Information(any());
5458 
5459 
5460 
5461     }
5462 
5463     /**
5464      * Verify that score card/health monitor are notified when wifi is disabled while disconnected
5465      */
5466     @Test
testScoreCardNoteWifiDisabledWhileDisconnected()5467     public void testScoreCardNoteWifiDisabledWhileDisconnected() throws Exception {
5468         // connecting and disconnecting shouldn't note wifi disabled
5469         disconnect();
5470         mLooper.dispatchAll();
5471 
5472         verify(mWifiScoreCard, times(1)).resetConnectionState(WIFI_IFACE_NAME);
5473         verify(mWifiScoreCard, never()).noteWifiDisabled(any());
5474 
5475         // disabling while disconnected should note wifi disabled
5476         mCmi.stop();
5477         mLooper.dispatchAll();
5478         verify(mWifiScoreCard, times(2)).resetConnectionState(WIFI_IFACE_NAME);
5479     }
5480 
5481     /**
5482      * Verify that score card/health monitor are notified when wifi is disabled while connected
5483      */
5484     @Test
testScoreCardNoteWifiDisabledWhileConnected()5485     public void testScoreCardNoteWifiDisabledWhileConnected() throws Exception {
5486         // Get into connected state
5487         connect();
5488         mLooper.dispatchAll();
5489         verify(mWifiScoreCard, never()).noteWifiDisabled(any());
5490 
5491         // disabling while connected should note wifi disabled
5492         mCmi.stop();
5493         mLooper.dispatchAll();
5494 
5495         verify(mWifiScoreCard).noteWifiDisabled(any());
5496         verify(mWifiScoreCard).resetConnectionState(WIFI_IFACE_NAME);
5497     }
5498 
5499     /**
5500      * Verify that IPClient instance is shutdown when wifi is disabled.
5501      */
5502     @Test
verifyIpClientShutdownWhenDisabled()5503     public void verifyIpClientShutdownWhenDisabled() throws Exception {
5504         mCmi.stop();
5505         mLooper.dispatchAll();
5506         verify(mIpClient).shutdown();
5507     }
5508 
5509     /**
5510      * Verify that WifiInfo's MAC address is updated when the state machine receives
5511      * NETWORK_CONNECTION_EVENT while in L3ConnectedState.
5512      */
5513     @Test
verifyWifiInfoMacUpdatedWithNetworkConnectionWhileConnected()5514     public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileConnected() throws Exception {
5515         connect();
5516         assertEquals("L3ConnectedState", getCurrentState().getName());
5517         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
5518 
5519         // Verify receiving a NETWORK_CONNECTION_EVENT changes the MAC in WifiInfo
5520         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
5521                 .thenReturn(TEST_GLOBAL_MAC_ADDRESS.toString());
5522         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
5523                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
5524         mLooper.dispatchAll();
5525         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
5526     }
5527 
5528     /**
5529      * Verify that WifiInfo's MAC address is updated when the state machine receives
5530      * NETWORK_CONNECTION_EVENT while in DisconnectedState.
5531      */
5532     @Test
verifyWifiInfoMacUpdatedWithNetworkConnectionWhileDisconnected()5533     public void verifyWifiInfoMacUpdatedWithNetworkConnectionWhileDisconnected() throws Exception {
5534         disconnect();
5535         assertEquals("DisconnectedState", getCurrentState().getName());
5536         // Since MAC randomization is enabled, wifiInfo's MAC should be set to default MAC
5537         // when disconnect happens.
5538         assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mWifiInfo.getMacAddress());
5539 
5540         setupAndStartConnectSequence(mConnectedNetwork);
5541         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
5542                 .thenReturn(TEST_LOCAL_MAC_ADDRESS.toString());
5543         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
5544                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
5545         mLooper.dispatchAll();
5546         assertEquals(TEST_LOCAL_MAC_ADDRESS.toString(), mWifiInfo.getMacAddress());
5547     }
5548 
5549     @Test
internetValidationFailure_notUserSelected_expectTemporarilyDisabled()5550     public void internetValidationFailure_notUserSelected_expectTemporarilyDisabled()
5551             throws Exception {
5552         // Setup RSSI poll to update WifiInfo with low RSSI
5553         mCmi.enableRssiPolling(true);
5554         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
5555         llStats.txmpdu_be = 1000;
5556         llStats.rxmpdu_bk = 2000;
5557         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
5558         signalPollResults.addEntry(0, RSSI_THRESHOLD_BREACH_MIN, 65, 54, sFreq);
5559         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
5560                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
5561         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
5562         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
5563 
5564         connect();
5565         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5566                 mWifiNetworkAgentCallbackCaptor.capture());
5567 
5568         WifiConfiguration currentNetwork = new WifiConfiguration();
5569         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
5570         currentNetwork.SSID = DEFAULT_TEST_SSID;
5571         currentNetwork.noInternetAccessExpected = false;
5572         currentNetwork.numNoInternetAccessReports = 1;
5573         currentNetwork.getNetworkSelectionStatus().setHasEverValidatedInternetAccess(true);
5574 
5575         // not user selected
5576         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
5577                 .thenReturn(currentNetwork);
5578         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(FRAMEWORK_NETWORK_ID))
5579                 .thenReturn(currentNetwork);
5580 
5581         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
5582 
5583         // internet validation failure
5584         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5585                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, null /* captivePortalUr; */);
5586         mLooper.dispatchAll();
5587 
5588         verify(mWifiConfigManager)
5589                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
5590         // expect temporarily disabled
5591         verify(mWifiConfigManager).updateNetworkSelectionStatus(
5592                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
5593         verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(TEST_BSSID_STR,
5594                 currentNetwork, WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE,
5595                 RSSI_THRESHOLD_BREACH_MIN);
5596         verify(mWifiScoreCard).noteValidationFailure(any());
5597     }
5598 
5599     @Test
testMbbInternetValidationErrorExpectDisconnect()5600     public void testMbbInternetValidationErrorExpectDisconnect() throws Exception {
5601         connect();
5602         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5603                 mWifiNetworkAgentCallbackCaptor.capture());
5604 
5605         // Make Before Break CMM
5606         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
5607         when(mActiveModeWarden.getClientModeManagerInRole(
5608                 ROLE_CLIENT_SECONDARY_TRANSIENT)).thenReturn(mock(ConcreteClientModeManager.class));
5609 
5610         // internet validation failure without detecting captive portal
5611         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5612                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, null /* captivePortalUr; */);
5613         mLooper.dispatchAll();
5614         verify(mCmiMonitor).onInternetValidationFailed(mClientModeManager, false);
5615     }
5616 
5617     @Test
testMbbNetworkUnwantedExpectDisconnect()5618     public void testMbbNetworkUnwantedExpectDisconnect() throws Exception {
5619         connect();
5620         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5621                 mWifiNetworkAgentCallbackCaptor.capture());
5622 
5623         // Make Before Break CMM
5624         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
5625         when(mActiveModeWarden.getClientModeManagerInRole(
5626                 ROLE_CLIENT_SECONDARY_TRANSIENT)).thenReturn(mock(ConcreteClientModeManager.class));
5627 
5628         // internet was lost and network got unwanted.
5629         mWifiNetworkAgentCallbackCaptor.getValue().onNetworkUnwanted();
5630         mLooper.dispatchAll();
5631         // expect disconnection
5632         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
5633     }
5634 
5635     @Test
testMbbInternetValidationErrorCaptivePortalNoDisconnect()5636     public void testMbbInternetValidationErrorCaptivePortalNoDisconnect() throws Exception {
5637         connect();
5638         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5639                 mWifiNetworkAgentCallbackCaptor.capture());
5640 
5641         // Make Before Break CMM
5642         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
5643 
5644         // mock internet validation failure with captive portal detected
5645         when(mMockUri.toString()).thenReturn("TEST_URI");
5646         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5647                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, mMockUri);
5648         mLooper.dispatchAll();
5649 
5650         // expect no disconnection
5651         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
5652     }
5653 
5654     @Test
testCaptivePortalDetectedNotifiesCmiMonitor()5655     public void testCaptivePortalDetectedNotifiesCmiMonitor() throws Exception {
5656         connect();
5657         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5658                 mWifiNetworkAgentCallbackCaptor.capture());
5659 
5660         // captive portal detected
5661         when(mMockUri.toString()).thenReturn("TEST_URI");
5662         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5663                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, mMockUri);
5664         mLooper.dispatchAll();
5665 
5666         verify(mWifiConfigManager).noteCaptivePortalDetected(anyInt());
5667         verify(mCmiMonitor).onCaptivePortalDetected(mClientModeManager);
5668     }
5669 
5670     @Test
testInternetValidationFailureUserSelectedRecently_ExpectDisabled()5671     public void testInternetValidationFailureUserSelectedRecently_ExpectDisabled()
5672             throws Exception {
5673         testInternetValidationUserSelectedRecently(false);
5674         // expect disabled because the network has never had internet validation passed
5675         verify(mWifiConfigManager).updateNetworkSelectionStatus(
5676                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_PERMANENT);
5677     }
5678 
5679     @Test
testInternetValidationFailureUserSelectedRecently_ExpectNotDisabled()5680     public void testInternetValidationFailureUserSelectedRecently_ExpectNotDisabled()
5681             throws Exception {
5682         testInternetValidationUserSelectedRecently(true);
5683         // expect not disabled
5684         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(
5685                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_PERMANENT);
5686         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(
5687                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
5688     }
5689 
testInternetValidationUserSelectedRecently(boolean hasEverValidatedInternetAccess)5690     private void testInternetValidationUserSelectedRecently(boolean hasEverValidatedInternetAccess)
5691             throws Exception {
5692         connect();
5693         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5694                 mWifiNetworkAgentCallbackCaptor.capture());
5695 
5696         WifiConfiguration currentNetwork = new WifiConfiguration();
5697         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
5698         currentNetwork.noInternetAccessExpected = false;
5699         currentNetwork.numNoInternetAccessReports = 1;
5700         currentNetwork.getNetworkSelectionStatus().setHasEverValidatedInternetAccess(
5701                 hasEverValidatedInternetAccess);
5702 
5703         // user last picked this network
5704         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
5705                 .thenReturn(currentNetwork);
5706         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID);
5707 
5708         // user recently picked this network
5709         when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(1234L);
5710         when(mClock.getElapsedSinceBootMillis()).thenReturn(1235L);
5711 
5712         // internet validation failure
5713         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5714                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, null /* captivePortalUrl */);
5715         mLooper.dispatchAll();
5716 
5717         verify(mWifiConfigManager)
5718                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
5719     }
5720 
5721     @Test
testInternetValidationFailureUserSelectedTooLongAgoExpectTemporarilyDisabled()5722     public void testInternetValidationFailureUserSelectedTooLongAgoExpectTemporarilyDisabled()
5723             throws Exception {
5724         connect();
5725         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5726                 mWifiNetworkAgentCallbackCaptor.capture());
5727 
5728         WifiConfiguration currentNetwork = new WifiConfiguration();
5729         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
5730         currentNetwork.noInternetAccessExpected = false;
5731         currentNetwork.numNoInternetAccessReports = 1;
5732         currentNetwork.getNetworkSelectionStatus().setHasEverValidatedInternetAccess(true);
5733 
5734         // user last picked this network
5735         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
5736                 .thenReturn(currentNetwork);
5737         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID);
5738 
5739         // user picked this network a long time ago
5740         when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(1234L);
5741         when(mClock.getElapsedSinceBootMillis())
5742                 .thenReturn(1235L + ClientModeImpl.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS);
5743 
5744         // internet validation failure
5745         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5746                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, null /* captivePortalUrl */);
5747         mLooper.dispatchAll();
5748 
5749         verify(mWifiConfigManager)
5750                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
5751         // expect temporarily disabled
5752         verify(mWifiConfigManager).updateNetworkSelectionStatus(
5753                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
5754     }
5755 
5756     @Test
testNetworkInternetValidationFailureNoInternetExpected_ExpectNotDisabled()5757     public void testNetworkInternetValidationFailureNoInternetExpected_ExpectNotDisabled()
5758             throws Exception {
5759         connect();
5760         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5761                 mWifiNetworkAgentCallbackCaptor.capture());
5762 
5763         WifiConfiguration currentNetwork = new WifiConfiguration();
5764         currentNetwork.networkId = FRAMEWORK_NETWORK_ID;
5765         // no internet expected
5766         currentNetwork.noInternetAccessExpected = true;
5767         currentNetwork.numNoInternetAccessReports = 1;
5768 
5769         // user didn't pick this network
5770         when(mWifiConfigManager.getConfiguredNetwork(FRAMEWORK_NETWORK_ID))
5771                 .thenReturn(currentNetwork);
5772         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(FRAMEWORK_NETWORK_ID))
5773                 .thenReturn(currentNetwork);
5774         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
5775 
5776         // internet validation failure
5777         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5778                 NetworkAgent.VALIDATION_STATUS_NOT_VALID, null /* captivePortalUrl */);
5779         mLooper.dispatchAll();
5780 
5781         verify(mWifiConfigManager)
5782                 .incrementNetworkNoInternetAccessReports(FRAMEWORK_NETWORK_ID);
5783         // expect not disabled since no internet is expected on this network
5784         verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(
5785                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
5786     }
5787 
5788     /**
5789      * Verify that we do not set the user connect choice after a successful connection if the
5790      * connection is not made by the user.
5791      */
5792     @Test
testNonSettingsConnectionNotSetUserConnectChoice()5793     public void testNonSettingsConnectionNotSetUserConnectChoice() throws Exception {
5794         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
5795         connect();
5796         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5797         verify(mWifiConfigManager).updateNetworkAfterConnect(eq(FRAMEWORK_NETWORK_ID),
5798                 eq(false), eq(false),
5799                 anyInt());
5800     }
5801 
5802     /**
5803      * Verify that we do not set the user connect choice after connecting to a newly added saved
5804      * network.
5805      */
5806     @Test
testNoSetUserConnectChoiceOnFirstConnection()5807     public void testNoSetUserConnectChoiceOnFirstConnection() throws Exception {
5808         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
5809         connect();
5810         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5811         verify(mWifiConfigManager).updateNetworkAfterConnect(eq(FRAMEWORK_NETWORK_ID),
5812                 eq(true), eq(false),
5813                 anyInt());
5814     }
5815 
verifyUserConnectChoice(boolean shouldSetUcc)5816     private void verifyUserConnectChoice(boolean shouldSetUcc) throws Exception {
5817         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
5818         mTestNetworkParams.hasEverConnected = true;
5819         connect();
5820         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5821         verify(mWifiConfigManager).updateNetworkAfterConnect(eq(FRAMEWORK_NETWORK_ID),
5822                 eq(shouldSetUcc), eq(shouldSetUcc),
5823                 anyInt());
5824     }
5825 
5826     /**
5827      * Verify that on the second successful connection to a saved network we set the user connect
5828      * choice.
5829      */
5830     @Test
testConnectionSetUserConnectChoiceOnSecondConnection()5831     public void testConnectionSetUserConnectChoiceOnSecondConnection() throws Exception {
5832         verifyUserConnectChoice(true);
5833     }
5834 
5835     @Test
testDisallowUserConnectChoice()5836     public void testDisallowUserConnectChoice() throws Exception {
5837         mAttributionTagForConnect = ClientModeImpl.ATTRIBUTION_TAG_DISALLOW_CONNECT_CHOICE;
5838         verifyUserConnectChoice(false);
5839     }
5840 
5841     /**
5842      * Verify that on the first successful connection to an ephemeral network we set the user
5843      * connect choice.
5844      */
5845     @Test
testConnectionSetUserConnectChoiceOnEphemeralConfig()5846     public void testConnectionSetUserConnectChoiceOnEphemeralConfig() throws Exception {
5847         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
5848         mConnectedNetwork.ephemeral = true;
5849         connect();
5850         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5851         verify(mWifiConfigManager).updateNetworkAfterConnect(eq(FRAMEWORK_NETWORK_ID),
5852                 eq(true), eq(true),
5853                 anyInt());
5854     }
5855 
5856     /**
5857      * Verify that we enable the network when we detect validated internet access.
5858      */
5859     @Test
verifyNetworkSelectionEnableOnInternetValidation()5860     public void verifyNetworkSelectionEnableOnInternetValidation() throws Exception {
5861         // Simulate the first connection.
5862         connect();
5863         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5864         verify(mWifiBlocklistMonitor).handleDhcpProvisioningSuccess(TEST_BSSID_STR, TEST_SSID);
5865         verify(mWifiBlocklistMonitor, never()).handleNetworkValidationSuccess(
5866                 TEST_BSSID_STR, TEST_SSID);
5867 
5868         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5869                 mWifiNetworkAgentCallbackCaptor.capture());
5870 
5871         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
5872 
5873         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5874                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
5875         mLooper.dispatchAll();
5876 
5877         verify(mWifiConfigManager)
5878                 .setNetworkValidatedInternetAccess(FRAMEWORK_NETWORK_ID, true);
5879         verify(mWifiConfigManager).updateNetworkSelectionStatus(
5880                 FRAMEWORK_NETWORK_ID, DISABLED_NONE);
5881         verify(mWifiScoreCard).noteValidationSuccess(any());
5882         verify(mWifiBlocklistMonitor).handleNetworkValidationSuccess(TEST_BSSID_STR, TEST_SSID);
5883     }
5884 
5885     /**
5886      * Verify that the logic clears the terms and conditions URL after we got a notification that
5887      * the network was validated (i.e. the user accepted and internt access is available).
5888      */
5889     @Test
testTermsAndConditionsClearUrlAfterNetworkValidation()5890     public void testTermsAndConditionsClearUrlAfterNetworkValidation() throws Exception {
5891         assumeTrue(SdkLevel.isAtLeastS());
5892         InOrder inOrder = inOrder(mWifiNetworkAgent);
5893 
5894         // Simulate the first connection.
5895         mConnectedNetwork = spy(WifiConfigurationTestUtil.createPasspointNetwork());
5896         WnmData wnmData = WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
5897                 TEST_TERMS_AND_CONDITIONS_URL);
5898         when(mPasspointManager.handleTermsAndConditionsEvent(eq(wnmData),
5899                 any(WifiConfiguration.class))).thenReturn(new URL(TEST_TERMS_AND_CONDITIONS_URL));
5900         connect(wnmData);
5901         // Verify that link properties contains the T&C URL and captive is set to true
5902         inOrder.verify(mWifiNetworkAgent)
5903                 .sendLinkProperties(argThat(linkProperties -> TEST_TERMS_AND_CONDITIONS_URL.equals(
5904                         linkProperties.getCaptivePortalData().getUserPortalUrl().toString())
5905                         && linkProperties.getCaptivePortalData().isCaptive()));
5906         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
5907         verify(mWifiBlocklistMonitor).handleDhcpProvisioningSuccess(TEST_BSSID_STR, TEST_SSID);
5908         verify(mWifiBlocklistMonitor, never())
5909                 .handleNetworkValidationSuccess(TEST_BSSID_STR, TEST_SSID);
5910         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
5911                 mWifiNetworkAgentCallbackCaptor.capture());
5912 
5913         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(FRAMEWORK_NETWORK_ID + 1);
5914         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
5915                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
5916         mLooper.dispatchAll();
5917 
5918         verify(mWifiConfigManager)
5919                 .setNetworkValidatedInternetAccess(FRAMEWORK_NETWORK_ID, true);
5920         verify(mWifiConfigManager).updateNetworkSelectionStatus(
5921                 FRAMEWORK_NETWORK_ID, DISABLED_NONE);
5922         verify(mWifiScoreCard).noteValidationSuccess(any());
5923         verify(mWifiBlocklistMonitor).handleNetworkValidationSuccess(TEST_BSSID_STR, TEST_SSID);
5924 
5925         // Now that the network has been validated, link properties must not have a T&C URL anymore
5926         // and captive is set to false
5927         inOrder.verify(mWifiNetworkAgent)
5928                 .sendLinkProperties(argThat(linkProperties ->
5929                         linkProperties.getCaptivePortalData().getUserPortalUrl() == null
5930                                 && !linkProperties.getCaptivePortalData().isCaptive()));
5931     }
5932 
connectWithValidInitRssi(int initRssiDbm)5933     private void connectWithValidInitRssi(int initRssiDbm) throws Exception {
5934         triggerConnect();
5935         mWifiInfo.setRssi(initRssiDbm);
5936         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5937                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
5938                         SupplicantState.ASSOCIATED));
5939         mLooper.dispatchAll();
5940 
5941         WifiSsid wifiSsid = WifiSsid.fromBytes(
5942                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
5943         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
5944                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
5945         mLooper.dispatchAll();
5946 
5947         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
5948                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
5949                         SupplicantState.COMPLETED));
5950         mLooper.dispatchAll();
5951 
5952         assertEquals("L3ProvisioningState", getCurrentState().getName());
5953 
5954         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
5955         dhcpResults.baseConfiguration = new StaticIpConfiguration();
5956         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
5957         dhcpResults.baseConfiguration.ipAddress =
5958                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
5959         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
5960         dhcpResults.leaseDuration = 3600;
5961 
5962         injectDhcpSuccess(dhcpResults);
5963         mLooper.dispatchAll();
5964 
5965     }
5966 
5967     /**
5968      * Verify that we set the INTERNET and bandwidth capability in the network agent when connected
5969      * as a result of auto-join/legacy API's. Also verify up/down stream bandwidth values when
5970      * Rx link speed is unavailable.
5971      */
5972     @Test
verifyNetworkCapabilities()5973     public void verifyNetworkCapabilities() throws Exception {
5974         mWifiInfo.setFrequency(5825);
5975         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(40_000);
5976         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(50_000);
5977         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
5978                 .thenReturn(Collections.emptySet());
5979         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
5980                 .thenReturn(Pair.create(Process.INVALID_UID, ""));
5981         // Simulate the first connection.
5982         connectWithValidInitRssi(-42);
5983 
5984         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
5985                 ArgumentCaptor.forClass(NetworkCapabilities.class);
5986         verify(mWifiInjector).makeWifiNetworkAgent(
5987                 networkCapabilitiesCaptor.capture(), any(), any(), any(), any());
5988 
5989         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
5990         assertNotNull(networkCapabilities);
5991 
5992         // Should have internet capability.
5993         assertTrue(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
5994 
5995         assertEquals(mConnectedNetwork.creatorUid, networkCapabilities.getOwnerUid());
5996         if (SdkLevel.isAtLeastT()) {
5997             assertEquals(Set.of(mConnectedNetwork.creatorUid),
5998                     networkCapabilities.getAllowedUids());
5999         }
6000         assertArrayEquals(
6001                 new int[] {mConnectedNetwork.creatorUid},
6002                 networkCapabilities.getAdministratorUids());
6003 
6004         // Should set bandwidth correctly
6005         assertEquals(-42, mWifiInfo.getRssi());
6006         assertEquals(40_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
6007         assertEquals(50_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
6008 
6009         // Should set band correctly.
6010         // There is no accessor to get the band from the WifiNetworkAgentSpecifier, so match against
6011         // a WifiNetworkSpecifier.
6012         // TODO: should there be?
6013         final NetworkSpecifier spec = networkCapabilities.getNetworkSpecifier();
6014         assertTrue(spec instanceof WifiNetworkAgentSpecifier);
6015         final WifiNetworkAgentSpecifier wnas = (WifiNetworkAgentSpecifier) spec;
6016         assertTrue(wnas.satisfiesNetworkSpecifier(
6017                 new WifiNetworkSpecifier.Builder().setBand(ScanResult.WIFI_BAND_5_GHZ).build()));
6018     }
6019 
6020     /**
6021      * Verify that we don't set the INTERNET capability in the network agent when connected
6022      * as a result of the new network request API. Also verify up/down stream bandwidth values
6023      * when both Tx and Rx link speed are unavailable.
6024      */
6025     @Test
verifyNetworkCapabilitiesForSpecificRequestWithInternet()6026     public void verifyNetworkCapabilitiesForSpecificRequestWithInternet() throws Exception {
6027         mWifiInfo.setFrequency(2437);
6028         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(30_000);
6029         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(40_000);
6030         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
6031                 .thenReturn(Set.of(TEST_UID));
6032         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
6033                 .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME));
6034         when(mWifiConnectivityManager.hasMultiInternetConnection()).thenReturn(true);
6035         // Simulate the first connection.
6036         connectWithValidInitRssi(-42);
6037         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
6038                 ArgumentCaptor.forClass(NetworkCapabilities.class);
6039 
6040         verify(mWifiInjector).makeWifiNetworkAgent(
6041                 networkCapabilitiesCaptor.capture(), any(), any(), any(), any());
6042 
6043         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
6044         assertNotNull(networkCapabilities);
6045 
6046         // should not have internet capability.
6047         assertFalse(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
6048 
6049         NetworkSpecifier networkSpecifier = networkCapabilities.getNetworkSpecifier();
6050         assertTrue(networkSpecifier instanceof WifiNetworkAgentSpecifier);
6051         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
6052                 (WifiNetworkAgentSpecifier) networkSpecifier;
6053 
6054         // createNetworkAgentSpecifier does not write the BSSID to the current wifi configuration.
6055         WifiConfiguration expectedConfig = new WifiConfiguration(
6056                 mCmi.getConnectedWifiConfiguration());
6057         expectedConfig.BSSID = TEST_BSSID_STR;
6058         WifiNetworkAgentSpecifier expectedWifiNetworkAgentSpecifier =
6059                 new WifiNetworkAgentSpecifier(expectedConfig, ScanResult.WIFI_BAND_24_GHZ,
6060                         true /* matchLocalOnlySpecifiers */);
6061         assertEquals(expectedWifiNetworkAgentSpecifier, wifiNetworkAgentSpecifier);
6062         if (SdkLevel.isAtLeastS()) {
6063             assertEquals(Set.of(new Range<Integer>(TEST_UID, TEST_UID)),
6064                     networkCapabilities.getUids());
6065         } else {
6066             assertEquals(TEST_UID, networkCapabilities.getRequestorUid());
6067             assertEquals(OP_PACKAGE_NAME, networkCapabilities.getRequestorPackageName());
6068         }
6069         assertEquals(30_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
6070         assertEquals(40_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
6071     }
6072 
6073     /**
6074      * Verify that we set the INTERNET capability in the network agent when connected
6075      * as a result of the new network which indicate the internet capabilites should be set.
6076      */
6077     @Test
verifyNetworkCapabilitiesForSpecificRequest()6078     public void verifyNetworkCapabilitiesForSpecificRequest() throws Exception {
6079         mWifiInfo.setFrequency(2437);
6080         when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(30_000);
6081         when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(40_000);
6082         when(mWifiNetworkFactory.getSpecificNetworkRequestUids(any(), any()))
6083                 .thenReturn(Set.of(TEST_UID));
6084         when(mWifiNetworkFactory.getSpecificNetworkRequestUidAndPackageName(any(), any()))
6085                 .thenReturn(Pair.create(TEST_UID, OP_PACKAGE_NAME));
6086         when(mWifiNetworkFactory.shouldHaveInternetCapabilities()).thenReturn(true);
6087         when(mWifiConnectivityManager.hasMultiInternetConnection()).thenReturn(true);
6088         // Simulate the first connection.
6089         connectWithValidInitRssi(-42);
6090         ArgumentCaptor<NetworkCapabilities> networkCapabilitiesCaptor =
6091                 ArgumentCaptor.forClass(NetworkCapabilities.class);
6092 
6093         verify(mWifiInjector).makeWifiNetworkAgent(
6094                 networkCapabilitiesCaptor.capture(), any(), any(), any(), any());
6095 
6096         NetworkCapabilities networkCapabilities = networkCapabilitiesCaptor.getValue();
6097         assertNotNull(networkCapabilities);
6098 
6099         // should not have internet capability.
6100         assertTrue(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
6101 
6102         NetworkSpecifier networkSpecifier = networkCapabilities.getNetworkSpecifier();
6103         assertTrue(networkSpecifier instanceof WifiNetworkAgentSpecifier);
6104         WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
6105                 (WifiNetworkAgentSpecifier) networkSpecifier;
6106 
6107         // createNetworkAgentSpecifier does not write the BSSID to the current wifi configuration.
6108         WifiConfiguration expectedConfig = new WifiConfiguration(
6109                 mCmi.getConnectedWifiConfiguration());
6110         expectedConfig.BSSID = TEST_BSSID_STR;
6111         WifiNetworkAgentSpecifier expectedWifiNetworkAgentSpecifier =
6112                 new WifiNetworkAgentSpecifier(expectedConfig, ScanResult.WIFI_BAND_24_GHZ,
6113                         true /* matchLocalOnlySpecifiers */);
6114         assertEquals(expectedWifiNetworkAgentSpecifier, wifiNetworkAgentSpecifier);
6115         if (SdkLevel.isAtLeastS()) {
6116             assertEquals(Set.of(new Range<Integer>(TEST_UID, TEST_UID)),
6117                     networkCapabilities.getUids());
6118         } else {
6119             assertEquals(TEST_UID, networkCapabilities.getRequestorUid());
6120             assertEquals(OP_PACKAGE_NAME, networkCapabilities.getRequestorPackageName());
6121         }
6122         assertEquals(30_000, networkCapabilities.getLinkUpstreamBandwidthKbps());
6123         assertEquals(40_000, networkCapabilities.getLinkDownstreamBandwidthKbps());
6124     }
6125 
6126     /**
6127      *  Verifies that no RSSI change broadcast should be sent
6128      */
failOnRssiChangeBroadcast()6129     private void failOnRssiChangeBroadcast() throws Exception {
6130         mCmi.enableVerboseLogging(true);
6131         doAnswer(invocation -> {
6132             final Intent intent = invocation.getArgument(0);
6133             if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) {
6134                 fail("Should not send RSSI_CHANGED broadcast!");
6135             }
6136             return null;
6137         }).when(mContext).sendBroadcastAsUser(any(), any());
6138 
6139         doAnswer(invocation -> {
6140             final Intent intent = invocation.getArgument(0);
6141             if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) {
6142                 fail("Should not send RSSI_CHANGED broadcast!");
6143             }
6144             return null;
6145         }).when(mContext).sendBroadcastAsUser(any(), any(), anyString());
6146 
6147         doAnswer(invocation -> {
6148             final Intent intent = invocation.getArgument(0);
6149             if (WifiManager.RSSI_CHANGED_ACTION.equals(intent.getAction())) {
6150                 fail("Should not send RSSI_CHANGED broadcast!");
6151             }
6152             return null;
6153         }).when(mContext).sendBroadcastAsUser(any(), any(), anyString(), any());
6154     }
6155 
6156     /**
6157      * Verifies that RSSI change broadcast is sent.
6158      */
assertRssiChangeBroadcastSent(int times)6159     private void assertRssiChangeBroadcastSent(int times) throws Exception {
6160         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
6161         verify(mContext, times(times)).sendBroadcastAsUser(intentCaptor.capture(),
6162                 eq(UserHandle.ALL), eq(Manifest.permission.ACCESS_WIFI_STATE), any());
6163         if (times > 0) {
6164             Intent intent = intentCaptor.getValue();
6165             assertNotNull(intent);
6166             assertEquals(WifiManager.RSSI_CHANGED_ACTION, intent.getAction());
6167         }
6168     }
6169 
6170     /**
6171      * Verify that we check for data stall during rssi poll
6172      * and then check that wifi link layer usage data are being updated.
6173      */
6174     @Test
verifyRssiPollChecksDataStall()6175     public void verifyRssiPollChecksDataStall() throws Exception {
6176         mCmi.enableRssiPolling(true);
6177         connect();
6178 
6179         failOnRssiChangeBroadcast();
6180         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
6181                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
6182         WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
6183         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
6184         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
6185         mLooper.dispatchAll();
6186         WifiLinkLayerStats newLLStats = new WifiLinkLayerStats();
6187         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(newLLStats);
6188         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
6189         mLooper.dispatchAll();
6190         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
6191                 mConnectionCapabilities, oldLLStats, newLLStats, mWifiInfo, TEST_TX_BYTES,
6192                 TEST_RX_BYTES);
6193         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, newLLStats);
6194     }
6195 
6196     /**
6197      * Verify that we update wifi usability stats entries during rssi poll and that when we get
6198      * a data stall we label and save the current list of usability stats entries.
6199      * @throws Exception
6200      */
6201     @Test
verifyRssiPollUpdatesWifiUsabilityMetrics()6202     public void verifyRssiPollUpdatesWifiUsabilityMetrics() throws Exception {
6203         mCmi.enableRssiPolling(true);
6204         connect();
6205 
6206         failOnRssiChangeBroadcast();
6207         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
6208                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
6209         WifiLinkLayerStats stats = new WifiLinkLayerStats();
6210         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats);
6211         when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(),
6212                 any(), any(), any(), any(), anyLong(), anyLong()))
6213                 .thenReturn(WifiIsUnusableEvent.TYPE_UNKNOWN);
6214         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
6215         mLooper.dispatchAll();
6216         verify(mWifiMetrics).updateWifiUsabilityStatsEntries(any(), any(), eq(stats), eq(false),
6217                 anyInt());
6218 
6219         when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), any(), any(), any(),
6220                 any(), anyLong(), anyLong()))
6221                 .thenReturn(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX);
6222         when(mClock.getElapsedSinceBootMillis()).thenReturn(10L);
6223         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
6224         mLooper.dispatchAll();
6225         verify(mWifiMetrics, times(2)).updateWifiUsabilityStatsEntries(any(), any(), eq(stats),
6226                 eq(false), anyInt());
6227     }
6228 
6229     /**
6230      * Verify that when ordered to setPowerSave(true) while Interface is created,
6231      * WifiNative is called with the right powerSave mode.
6232      */
6233     @Test
verifySetPowerSaveTrueSuccess()6234     public void verifySetPowerSaveTrueSuccess() throws Exception {
6235         // called once during setup()
6236         verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true);
6237 
6238         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, true));
6239         assertTrue(mCmi.enablePowerSave());
6240         verify(mWifiNative, times(3)).setPowerSave(WIFI_IFACE_NAME, true);
6241     }
6242 
6243     /**
6244      * Verify that when ordered to setPowerSave(false) while Interface is created,
6245      * WifiNative is called with the right powerSave mode.
6246      */
6247     @Test
verifySetPowerSaveFalseSuccess()6248     public void verifySetPowerSaveFalseSuccess() throws Exception {
6249         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, false));
6250         verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6251     }
6252 
6253     /**
6254      * Verify that using setPowerSave with multiple clients (DHCP/WifiLock) operates correctly:
6255      * - Disable power save if ANY client disables it
6256      * - Enable power save only if ALL clients no longer disable it
6257      */
6258     @Test
verifySetPowerSaveMultipleSources()6259     public void verifySetPowerSaveMultipleSources() {
6260         InOrder inOrderWifiNative = inOrder(mWifiNative);
6261 
6262         // #1 Disable-> #2 Disable-> #2 Enable-> #1 Enable
6263         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, false));
6264         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6265 
6266         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, false));
6267         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6268 
6269         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, true));
6270         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6271 
6272         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, true));
6273         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true);
6274 
6275         // #1 Disable-> #2 Disable-> #1 Enable-> #2 Enable
6276         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, false));
6277         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6278 
6279         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, false));
6280         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6281 
6282         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, true));
6283         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6284 
6285         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, true));
6286         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true);
6287 
6288         // #1 Disable-> #2 Disable-> global enable
6289         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, false));
6290         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6291 
6292         assertTrue(mCmi.setPowerSave(ClientMode.POWER_SAVE_CLIENT_DHCP, false));
6293         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, false);
6294 
6295         assertTrue(mCmi.enablePowerSave());
6296         inOrderWifiNative.verify(mWifiNative).setPowerSave(WIFI_IFACE_NAME, true);
6297     }
6298 
6299     /**
6300      * Verify that we call into WifiTrafficPoller during rssi poll
6301      */
6302     @Test
verifyRssiPollCallsWifiTrafficPoller()6303     public void verifyRssiPollCallsWifiTrafficPoller() throws Exception {
6304         mCmi.enableRssiPolling(true);
6305         connect();
6306 
6307         verify(mWifiTrafficPoller).notifyOnDataActivity(anyLong(), anyLong());
6308     }
6309 
6310     /**
6311      * Verify that when ordered to setLowLatencyMode(true),
6312      * WifiNative is called with the right lowLatency mode.
6313      */
6314     @Test
verifySetLowLatencyTrueSuccess()6315     public void verifySetLowLatencyTrueSuccess() throws Exception {
6316         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true);
6317         assertTrue(mCmi.setLowLatencyMode(true));
6318         verify(mWifiNative).setLowLatencyMode(true);
6319     }
6320 
6321     /**
6322      * Verify that when ordered to setLowLatencyMode(false),
6323      * WifiNative is called with the right lowLatency mode.
6324      */
6325     @Test
verifySetLowLatencyFalseSuccess()6326     public void verifySetLowLatencyFalseSuccess() throws Exception {
6327         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(true);
6328         assertTrue(mCmi.setLowLatencyMode(false));
6329         verify(mWifiNative).setLowLatencyMode(false);
6330     }
6331 
6332     /**
6333      * Verify that when WifiNative fails to set low latency mode,
6334      * then the call setLowLatencyMode() returns with failure,
6335      */
6336     @Test
verifySetLowLatencyModeFailure()6337     public void verifySetLowLatencyModeFailure() throws Exception {
6338         final boolean lowLatencyMode = true;
6339         when(mWifiNative.setLowLatencyMode(anyBoolean())).thenReturn(false);
6340         assertFalse(mCmi.setLowLatencyMode(lowLatencyMode));
6341         verify(mWifiNative).setLowLatencyMode(eq(lowLatencyMode));
6342     }
6343 
6344     /**
6345      * Verify the wifi module can be confiured to always get the factory MAC address from
6346      * WifiNative instead of using saved value in WifiConfigStore.
6347      */
6348     @Test
testGetFactoryMacAddressAlwaysFromWifiNative()6349     public void testGetFactoryMacAddressAlwaysFromWifiNative() throws Exception {
6350         // Configure overlay to always retrieve the MAC address from WifiNative.
6351         when(mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled()).thenReturn(false);
6352         initializeAndAddNetworkAndVerifySuccess();
6353 
6354         clearInvocations(mWifiNative, mSettingsConfigStore);
6355         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6356         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6357         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6358 
6359         verify(mWifiNative, times(3)).getStaFactoryMacAddress(WIFI_IFACE_NAME);
6360     }
6361 
6362     /**
6363      * Verify getting the factory MAC address success case.
6364      */
6365     @Test
testGetFactoryMacAddressSuccess()6366     public void testGetFactoryMacAddressSuccess() throws Exception {
6367         initializeAndAddNetworkAndVerifySuccess();
6368 
6369         clearInvocations(mWifiNative, mSettingsConfigStore);
6370 
6371         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6372         verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS); // try config store.
6373         verify(mWifiNative, never()).getStaFactoryMacAddress(WIFI_IFACE_NAME); // not native
6374         verify(mSettingsConfigStore, never()).put(eq(WIFI_STA_FACTORY_MAC_ADDRESS), any());
6375 
6376         clearInvocations(mWifiNative, mSettingsConfigStore);
6377 
6378         // get it again, should now use the config store MAC address, not native.
6379         assertEquals(TEST_GLOBAL_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6380         verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS);
6381 
6382         // Verify secondary MAC is not stored
6383         verify(mSettingsConfigStore, never()).put(
6384                 eq(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS), any());
6385         verify(mSettingsConfigStore, never()).get(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS);
6386 
6387         // Query again as secondary STA, and then verify the result is saved to secondary.
6388         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED);
6389         mCmi.getFactoryMacAddress();
6390         verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME);
6391         verify(mSettingsConfigStore).put(eq(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS), any());
6392         verify(mSettingsConfigStore).get(SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS);
6393 
6394         verifyNoMoreInteractions(mWifiNative, mSettingsConfigStore);
6395     }
6396 
6397     /**
6398      * Verify getting the factory MAC address failure case.
6399      */
6400     @Test
testGetFactoryMacAddressFail()6401     public void testGetFactoryMacAddressFail() throws Exception {
6402         initializeAndAddNetworkAndVerifySuccess();
6403 
6404         clearInvocations(mWifiNative, mSettingsConfigStore);
6405 
6406         when(mSettingsConfigStore.get(WIFI_STA_FACTORY_MAC_ADDRESS)).thenReturn(null);
6407         when(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
6408         assertNull(mCmi.getFactoryMacAddress());
6409         verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS);
6410         verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME);
6411 
6412         verifyNoMoreInteractions(mWifiNative, mSettingsConfigStore);
6413     }
6414 
6415     /**
6416      * Verify that when WifiNative#getStaFactoryMacAddress fails, if the device does not support
6417      * MAC randomization then the currently programmed MAC address gets returned.
6418      */
6419     @Test
testGetFactoryMacAddressFailWithNoMacRandomizationSupport()6420     public void testGetFactoryMacAddressFailWithNoMacRandomizationSupport() throws Exception {
6421         // reset mWifiNative since initializeCmi() was called in setup()
6422         resetWifiNative();
6423 
6424         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(false);
6425         initializeCmi();
6426         initializeAndAddNetworkAndVerifySuccess();
6427 
6428         clearInvocations(mWifiNative, mSettingsConfigStore);
6429 
6430         when(mSettingsConfigStore.get(WIFI_STA_FACTORY_MAC_ADDRESS)).thenReturn(null);
6431         when(mWifiNative.getStaFactoryMacAddress(WIFI_IFACE_NAME)).thenReturn(null);
6432         when(mWifiNative.getMacAddress(WIFI_IFACE_NAME))
6433                 .thenReturn(TEST_DEFAULT_MAC_ADDRESS.toString());
6434         assertEquals(TEST_DEFAULT_MAC_ADDRESS.toString(), mCmi.getFactoryMacAddress());
6435 
6436         verify(mSettingsConfigStore).get(WIFI_STA_FACTORY_MAC_ADDRESS);
6437         verify(mWifiNative).getStaFactoryMacAddress(WIFI_IFACE_NAME);
6438         verify(mWifiNative).getMacAddress(WIFI_IFACE_NAME);
6439 
6440         verifyNoMoreInteractions(mWifiNative, mSettingsConfigStore);
6441     }
6442 
6443     /**
6444      * Verify the MAC address is being randomized at start to prevent leaking the factory MAC.
6445      */
6446     @Test
testRandomizeMacAddressOnStart()6447     public void testRandomizeMacAddressOnStart() throws Exception {
6448         ArgumentCaptor<MacAddress> macAddressCaptor = ArgumentCaptor.forClass(MacAddress.class);
6449         verify(mWifiNative).setStaMacAddress(anyString(), macAddressCaptor.capture());
6450         MacAddress currentMac = macAddressCaptor.getValue();
6451 
6452         assertNotEquals("The currently programmed MAC address should be different from the factory "
6453                 + "MAC address after ClientModeImpl starts",
6454                 mCmi.getFactoryMacAddress(), currentMac.toString());
6455 
6456         // Verify interface up will not re-randomize the MAC address again.
6457         mCmi.onUpChanged(true);
6458         verify(mWifiNative).setStaMacAddress(anyString(), macAddressCaptor.capture());
6459     }
6460 
6461     /**
6462      * Verify if re-randomizing had failed, then we will retry the next time the interface comes up.
6463      */
6464     @Test
testRandomizeMacAddressFailedRetryOnInterfaceUp()6465     public void testRandomizeMacAddressFailedRetryOnInterfaceUp() throws Exception {
6466         // mock setting the MAC address to fail
6467         when(mWifiNative.setStaMacAddress(eq(WIFI_IFACE_NAME), any())).thenReturn(false);
6468         initializeCmi();
6469 
6470         ArgumentCaptor<MacAddress> macAddressCaptor = ArgumentCaptor.forClass(MacAddress.class);
6471         verify(mWifiNative, times(2)).setStaMacAddress(anyString(), macAddressCaptor.capture());
6472         MacAddress currentMac = macAddressCaptor.getValue();
6473 
6474         // mock setting the MAC address to succeed
6475         when(mWifiNative.setStaMacAddress(eq(WIFI_IFACE_NAME), any()))
6476                 .then(new AnswerWithArguments() {
6477                     public boolean answer(String iface, MacAddress mac) {
6478                         when(mWifiNative.getMacAddress(iface)).thenReturn(mac.toString());
6479                         return true;
6480                     }
6481                 });
6482 
6483         // Verify interface up will re-randomize the MAC address since the last attempt failed.
6484         mCmi.onUpChanged(true);
6485         verify(mWifiNative, times(3)).setStaMacAddress(anyString(), macAddressCaptor.capture());
6486         assertNotEquals("The currently programmed MAC address should be different from the factory "
6487                         + "MAC address after ClientModeImpl starts",
6488                 mCmi.getFactoryMacAddress(), currentMac.toString());
6489 
6490         // Verify interface up will not re-randomize the MAC address since the last attempt
6491         // succeeded.
6492         mCmi.onUpChanged(true);
6493         verify(mWifiNative, times(3)).setStaMacAddress(anyString(), macAddressCaptor.capture());
6494     }
6495 
6496     /**
6497      * Verify the MAC address is being randomized at start to prevent leaking the factory MAC.
6498      */
6499     @Test
testNoRandomizeMacAddressOnStartIfMacRandomizationNotEnabled()6500     public void testNoRandomizeMacAddressOnStartIfMacRandomizationNotEnabled() throws Exception {
6501         // reset mWifiNative since initializeCmi() was called in setup()
6502         resetWifiNative();
6503 
6504         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(false);
6505         initializeCmi();
6506         verify(mWifiNative, never()).setStaMacAddress(anyString(), any());
6507     }
6508 
6509     /**
6510      * Verify bugreport will be taken when get IP_REACHABILITY_LOST
6511      */
6512     @Test
testTakebugreportbyIpReachabilityLost()6513     public void testTakebugreportbyIpReachabilityLost() throws Exception {
6514         connect();
6515 
6516         mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
6517         mLooper.dispatchAll();
6518         verify(mWifiDiagnostics).triggerBugReportDataCapture(
6519                 eq(WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST));
6520     }
6521 
6522     /**
6523      * Verify bugreport will be taken when get IP_REACHABILITY_FAILURE
6524      */
6525     @Test
testTakeBugReportByIpReachabilityFailure()6526     public void testTakeBugReportByIpReachabilityFailure() throws Exception {
6527         assumeTrue(SdkLevel.isAtLeastT());
6528         connect();
6529 
6530         ReachabilityLossInfoParcelable lossInfo =
6531                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ROAM);
6532         mIpClientCallback.onReachabilityFailure(lossInfo);
6533         mLooper.dispatchAll();
6534         verify(mWifiDiagnostics).triggerBugReportDataCapture(
6535                 eq(WifiDiagnostics.REPORT_REASON_REACHABILITY_FAILURE));
6536     }
6537     /**
6538      * Verifies that WifiLastResortWatchdog is notified of FOURWAY_HANDSHAKE_TIMEOUT.
6539      */
6540     @Test
testHandshakeTimeoutUpdatesWatchdog()6541     public void testHandshakeTimeoutUpdatesWatchdog() throws Exception {
6542         // Setup CONNECT_MODE & a WifiConfiguration
6543         initializeAndAddNetworkAndVerifySuccess();
6544         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
6545         mLooper.dispatchAll();
6546         // Verifies that WifiLastResortWatchdog won't be notified
6547         // by other reason code
6548         DisconnectEventInfo disconnectEventInfo =
6549                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 2, false);
6550         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
6551         mLooper.dispatchAll();
6552 
6553         assertEquals("DisconnectedState", getCurrentState().getName());
6554         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
6555                 eq(TEST_SSID), eq(TEST_BSSID_STR),
6556                 eq(WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION), anyBoolean());
6557 
6558         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
6559         mLooper.dispatchAll();
6560         // Verifies that WifiLastResortWatchdog be notified
6561         // for FOURWAY_HANDSHAKE_TIMEOUT.
6562         disconnectEventInfo = new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 15, false);
6563         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
6564         mLooper.dispatchAll();
6565 
6566         assertEquals("DisconnectedState", getCurrentState().getName());
6567         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
6568                 eq(TEST_SSID), eq(TEST_BSSID_STR),
6569                 eq(WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION), anyBoolean());
6570 
6571     }
6572 
6573     /**
6574      * Verify that WifiInfo is correctly populated after connection.
6575      */
6576     @Test
verifyWifiInfoGetNetworkSpecifierPackageName()6577     public void verifyWifiInfoGetNetworkSpecifierPackageName() throws Exception {
6578         mConnectedNetwork.fromWifiNetworkSpecifier = true;
6579         mConnectedNetwork.ephemeral = true;
6580         mConnectedNetwork.trusted = true;
6581         mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
6582         mConnectedNetwork.restricted = true;
6583         connect();
6584 
6585         assertTrue(mWifiInfo.isEphemeral());
6586         assertTrue(mWifiInfo.isTrusted());
6587         assumeTrue(mWifiInfo.isRestricted());
6588         assertEquals(OP_PACKAGE_NAME,
6589                 mWifiInfo.getRequestingPackageName());
6590 
6591         verify(mWifiConfigManager, never()).userTemporarilyDisabledNetwork(
6592                 eq(mConnectedNetwork.SSID), anyInt());
6593         // Setup new manual connection to another network
6594         WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork();
6595         config.networkId = TEST_NETWORK_ID;
6596         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
6597 
6598         IActionListener connectActionListener = mock(IActionListener.class);
6599         mCmi.connectNetwork(
6600                 new NetworkUpdateResult(TEST_NETWORK_ID),
6601                 new ActionListenerWrapper(connectActionListener),
6602                 Process.SYSTEM_UID, OP_PACKAGE_NAME, null);
6603         mLooper.dispatchAll();
6604         verify(connectActionListener).onSuccess();
6605 
6606         // verify new manual connection will add the wifi network specifier network to temporary
6607         // blocklist
6608         verify(mWifiConfigManager).userTemporarilyDisabledNetwork(eq(mConnectedNetwork.SSID),
6609                 anyInt());
6610     }
6611 
6612     /**
6613      * Verify that WifiInfo is correctly populated after connection.
6614      */
6615     @Test
verifyWifiInfoGetNetworkSuggestionPackageName()6616     public void verifyWifiInfoGetNetworkSuggestionPackageName() throws Exception {
6617         mConnectedNetwork.fromWifiNetworkSuggestion = true;
6618         mConnectedNetwork.ephemeral = true;
6619         mConnectedNetwork.trusted = true;
6620         mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
6621         mConnectedNetwork.restricted = true;
6622         connect();
6623 
6624         assertTrue(mWifiInfo.isEphemeral());
6625         assertTrue(mWifiInfo.isTrusted());
6626         assumeTrue(mWifiInfo.isRestricted());
6627         assertEquals(OP_PACKAGE_NAME,
6628                 mWifiInfo.getRequestingPackageName());
6629     }
6630 
6631     /**
6632      * Verify that a WifiIsUnusableEvent is logged and the current list of usability stats entries
6633      * are labeled and saved when receiving an IP reachability lost message.
6634      * @throws Exception
6635      */
6636     @Test
verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics()6637     public void verifyIpReachabilityLostMsgUpdatesWifiUsabilityMetrics() throws Exception {
6638         connect();
6639 
6640         mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
6641         mLooper.dispatchAll();
6642         verify(mWifiMetrics).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
6643                 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
6644     }
6645 
6646     /**
6647      * Verify that a WifiIsUnusableEvent is logged and the current list of usability stats entries
6648      * are labeled and saved when receiving an IP reachability failure message with non roam type.
6649      * @throws Exception
6650      */
6651     @Test
verifyIpReachabilityFailureMsgUpdatesWifiUsabilityMetrics()6652     public void verifyIpReachabilityFailureMsgUpdatesWifiUsabilityMetrics() throws Exception {
6653         assumeTrue(SdkLevel.isAtLeastT());
6654         connect();
6655 
6656         ReachabilityLossInfoParcelable lossInfo =
6657                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
6658         mIpClientCallback.onReachabilityFailure(lossInfo);
6659         mLooper.dispatchAll();
6660         verify(mWifiMetrics).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
6661                 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
6662     }
6663 
6664     /**
6665      * Verify that a WifiIsUnusableEvent isn't logged and the current list of usability stats
6666      * entries are not labeled and saved when receiving an IP reachability failure message with
6667      * non roam type but {@link isHandleRssiOrganicKernelFailuresEnabled} is enabled.
6668      * @throws Exception
6669      */
6670     @Test
verifyIpReachabilityFailureMsgUpdatesWifiUsabilityMetrics_enableFlag()6671     public void verifyIpReachabilityFailureMsgUpdatesWifiUsabilityMetrics_enableFlag()
6672             throws Exception {
6673         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
6674         assumeTrue(SdkLevel.isAtLeastU());
6675         connect();
6676 
6677         ReachabilityLossInfoParcelable lossInfo =
6678                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
6679         mCmi.sendMessage(ClientModeImpl.CMD_IP_REACHABILITY_FAILURE, lossInfo);
6680         mLooper.dispatchAll();
6681         verify(mWifiMetrics, never()).logWifiIsUnusableEvent(WIFI_IFACE_NAME,
6682                 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
6683     }
6684 
6685     /**
6686      * Tests that when {@link ClientModeImpl} receives a SUP_REQUEST_IDENTITY message, it responds
6687      * to the supplicant with the SIM identity.
6688      */
6689     @Test
testSupRequestIdentity_setsIdentityResponse()6690     public void testSupRequestIdentity_setsIdentityResponse() throws Exception {
6691         mConnectedNetwork = spy(WifiConfigurationTestUtil.createEapNetwork(
6692                 WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE));
6693         mConnectedNetwork.SSID = DEFAULT_TEST_SSID;
6694         String expectetIdentity = "13214561234567890@wlan.mnc456.mcc321.3gppnetwork.org";
6695 
6696         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
6697                 .thenReturn(DATA_SUBID);
6698         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
6699         when(mWifiCarrierInfoManager.getSimIdentity(any()))
6700                 .thenReturn(Pair.create(expectetIdentity, ""));
6701 
6702         triggerConnect();
6703 
6704         mCmi.sendMessage(WifiMonitor.SUP_REQUEST_IDENTITY,
6705                 0, FRAMEWORK_NETWORK_ID, DEFAULT_TEST_SSID);
6706         mLooper.dispatchAll();
6707 
6708         verify(mWifiNative).simIdentityResponse(WIFI_IFACE_NAME,
6709                 expectetIdentity, "");
6710     }
6711 
6712     /**
6713      * Verifies that WifiLastResortWatchdog is notified of DHCP failures when recevied
6714      * NETWORK_DISCONNECTION_EVENT while in L3ProvisioningState.
6715      */
6716     @Test
testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr()6717     public void testDhcpFailureUpdatesWatchdog_WhenDisconnectedWhileObtainingIpAddr()
6718             throws Exception {
6719         initializeAndAddNetworkAndVerifySuccess();
6720 
6721         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
6722 
6723         startConnectSuccess();
6724 
6725         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
6726                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
6727         mLooper.dispatchAll();
6728 
6729         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
6730                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
6731                         SupplicantState.COMPLETED));
6732         mLooper.dispatchAll();
6733 
6734         assertEquals("L3ProvisioningState", getCurrentState().getName());
6735 
6736         // Verifies that WifiLastResortWatchdog be notified.
6737         DisconnectEventInfo disconnectEventInfo =
6738                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
6739         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
6740         mLooper.dispatchAll();
6741 
6742         assertEquals("DisconnectedState", getCurrentState().getName());
6743         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
6744                 eq(TEST_SSID), eq(TEST_BSSID_STR),
6745                 eq(WifiLastResortWatchdog.FAILURE_CODE_DHCP), anyBoolean());
6746     }
6747 
6748     /**
6749      * Verifies that we trigger a disconnect when the {@link WifiConfigManager}.
6750      * OnNetworkUpdateListener#onNetworkRemoved(WifiConfiguration)} is invoked.
6751      */
6752     @Test
testOnNetworkRemoved()6753     public void testOnNetworkRemoved() throws Exception {
6754         connect();
6755 
6756         WifiConfiguration removedNetwork = new WifiConfiguration();
6757         removedNetwork.networkId = FRAMEWORK_NETWORK_ID;
6758         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
6759                 .getAllValues()) {
6760             listener.onNetworkRemoved(removedNetwork);
6761         }
6762         mLooper.dispatchAll();
6763 
6764         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
6765         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
6766     }
6767 
6768     /**
6769      * Verifies that we trigger a disconnect when the {@link WifiConfigManager
6770      * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked.
6771      */
6772     @Test
testOnNetworkPermanentlyDisabled()6773     public void testOnNetworkPermanentlyDisabled() throws Exception {
6774         connect();
6775 
6776         // Verify connection failure related disable reason should not trigger disconnect because
6777         // this could be from another STA
6778         WifiConfiguration disabledNetwork = new WifiConfiguration();
6779         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
6780         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
6781                 .getAllValues()) {
6782             listener.onNetworkPermanentlyDisabled(disabledNetwork,
6783                 WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
6784         }
6785         mLooper.dispatchAll();
6786         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
6787 
6788         // Verify that the network is disconnect if the profile is disabled by wifi API call
6789         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
6790                 .getAllValues()) {
6791             listener.onNetworkPermanentlyDisabled(disabledNetwork,
6792                     WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER);
6793         }
6794         mLooper.dispatchAll();
6795         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
6796     }
6797 
6798     @Test
testUnwantedDisconnectTemporarilyDisableNetwork()6799     public void testUnwantedDisconnectTemporarilyDisableNetwork() throws Exception {
6800         connect();
6801         when(mWifiGlobals.disableUnwantedNetworkOnLowRssi()).thenReturn(true);
6802         when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(-1);
6803         mWifiInfo.setRssi(RSSI_THRESHOLD_MIN);
6804         mCmi.sendMessage(CMD_UNWANTED_NETWORK,
6805                 ClientModeImpl.NETWORK_STATUS_UNWANTED_DISCONNECT);
6806         mLooper.dispatchAll();
6807 
6808         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
6809                 eq(DISABLED_UNWANTED_LOW_RSSI));
6810     }
6811 
6812     /**
6813      * Verify that the current network is permanently disabled when
6814      * NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN is received and percent internet availability is
6815      * less than the threshold.
6816      */
6817     @Test
testLowPrababilityInternetPermanentlyDisableNetwork()6818     public void testLowPrababilityInternetPermanentlyDisableNetwork() throws Exception {
6819         connect();
6820         when(mPerBssid.estimatePercentInternetAvailability()).thenReturn(
6821                 ClientModeImpl.PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK - 1);
6822         mCmi.sendMessage(CMD_UNWANTED_NETWORK,
6823                 ClientModeImpl.NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
6824         mLooper.dispatchAll();
6825 
6826         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
6827                 eq(DISABLED_NO_INTERNET_PERMANENT));
6828     }
6829 
6830     /**
6831      * Verify that the current network is temporarily disabled when
6832      * NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN is received and percent internet availability is
6833      * over the threshold.
6834      */
6835     @Test
testHighProbabilityInternetTemporarilyDisableNetwork()6836     public void testHighProbabilityInternetTemporarilyDisableNetwork() throws Exception {
6837         connect();
6838         when(mPerBssid.estimatePercentInternetAvailability()).thenReturn(
6839                 ClientModeImpl.PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK);
6840         mCmi.sendMessage(CMD_UNWANTED_NETWORK,
6841                 ClientModeImpl.NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
6842         mLooper.dispatchAll();
6843 
6844         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
6845                 eq(DISABLED_NO_INTERNET_TEMPORARY));
6846     }
6847 
6848     /**
6849      * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager
6850      * .OnNetworkUpdateListener#onNetworkPermanentlyDisabled(WifiConfiguration, int)} is invoked.
6851      */
6852     @Test
testOnNetworkPermanentlyDisabledWithNoInternet()6853     public void testOnNetworkPermanentlyDisabledWithNoInternet() throws Exception {
6854         connect();
6855 
6856         WifiConfiguration disabledNetwork = new WifiConfiguration();
6857         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
6858         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
6859                 .getAllValues()) {
6860             listener.onNetworkPermanentlyDisabled(disabledNetwork,
6861                 WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT);
6862         }
6863         mLooper.dispatchAll();
6864 
6865         assertEquals("L3ConnectedState", getCurrentState().getName());
6866     }
6867 
6868     /**
6869      * Verifies that we don't trigger a disconnect when the {@link WifiConfigManager
6870      * .OnNetworkUpdateListener#onNetworkTemporarilyDisabled(WifiConfiguration, int)} is invoked.
6871      */
6872     @Test
testOnNetworkTemporarilyDisabledWithNoInternet()6873     public void testOnNetworkTemporarilyDisabledWithNoInternet() throws Exception {
6874         connect();
6875 
6876         WifiConfiguration disabledNetwork = new WifiConfiguration();
6877         disabledNetwork.networkId = FRAMEWORK_NETWORK_ID;
6878         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
6879                 .getAllValues()) {
6880             listener.onNetworkTemporarilyDisabled(disabledNetwork,
6881                 WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY);
6882         }
6883         mLooper.dispatchAll();
6884 
6885         assertEquals("L3ConnectedState", getCurrentState().getName());
6886     }
6887 
6888     /**
6889      * Verify that MboOce/WifiDataStall enable/disable methods are called in ClientMode.
6890      */
6891     @Test
verifyMboOceWifiDataStallSetupInClientMode()6892     public void verifyMboOceWifiDataStallSetupInClientMode() throws Exception {
6893         verify(mMboOceController).enable();
6894         mCmi.stop();
6895         mLooper.dispatchAll();
6896         verify(mMboOceController).disable();
6897     }
6898 
6899     @Test
verifyWifiMonitorHandlersDeregisteredOnStop()6900     public void verifyWifiMonitorHandlersDeregisteredOnStop() throws Exception {
6901         verify(mWifiMonitor, atLeastOnce())
6902                 .registerHandler(eq(WIFI_IFACE_NAME), anyInt(), any());
6903         verify(mWifiMetrics).registerForWifiMonitorEvents(WIFI_IFACE_NAME);
6904         verify(mWifiLastResortWatchdog).registerForWifiMonitorEvents(WIFI_IFACE_NAME);
6905 
6906         mCmi.stop();
6907         mLooper.dispatchAll();
6908 
6909         verify(mWifiMonitor, atLeastOnce())
6910                 .deregisterHandler(eq(WIFI_IFACE_NAME), anyInt(), any());
6911         verify(mWifiMetrics).deregisterForWifiMonitorEvents(WIFI_IFACE_NAME);
6912         verify(mWifiLastResortWatchdog).deregisterForWifiMonitorEvents(WIFI_IFACE_NAME);
6913     }
6914 
6915     @Test
onBluetoothConnectionStateChanged()6916     public void onBluetoothConnectionStateChanged() throws Exception {
6917         // reset mWifiNative since initializeCmi() was called in setup()
6918         resetWifiNative();
6919 
6920         when(mWifiGlobals.isBluetoothConnected()).thenReturn(false);
6921         initializeCmi();
6922         verify(mWifiNative).setBluetoothCoexistenceScanMode(any(), eq(false));
6923 
6924         when(mWifiGlobals.isBluetoothConnected()).thenReturn(true);
6925         mCmi.onBluetoothConnectionStateChanged();
6926         mLooper.dispatchAll();
6927         verify(mWifiNative).setBluetoothCoexistenceScanMode(any(), eq(true));
6928 
6929         when(mWifiGlobals.isBluetoothConnected()).thenReturn(false);
6930         mCmi.onBluetoothConnectionStateChanged();
6931         mLooper.dispatchAll();
6932         verify(mWifiNative, times(2)).setBluetoothCoexistenceScanMode(any(), eq(false));
6933     }
6934 
6935     /**
6936      * Test that handleBssTransitionRequest() blocklist the BSS upon
6937      * receiving BTM request frame that contains MBO-OCE IE with an
6938      * association retry delay attribute.
6939      */
6940     @Test
testBtmFrameWithMboAssocretryDelayBlockListTheBssid()6941     public void testBtmFrameWithMboAssocretryDelayBlockListTheBssid() throws Exception {
6942         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
6943         connect();
6944 
6945         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
6946 
6947         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED;
6948         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
6949                 | MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED;
6950         btmFrmData.mBlockListDurationMs = 60000;
6951 
6952         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
6953         mLooper.dispatchAll();
6954 
6955         verify(mWifiMetrics, times(1)).incrementSteeringRequestCountIncludingMboAssocRetryDelay();
6956         verify(mWifiBlocklistMonitor).blockBssidForDurationMs(eq(TEST_BSSID_STR), any(),
6957                 eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt());
6958     }
6959 
6960     /**
6961      * Test that handleBssTransitionRequest() blocklist the BSS upon
6962      * receiving BTM request frame that contains disassociation imminent bit
6963      * set to 1.
6964      */
6965     @Test
testBtmFrameWithDisassocImminentBitBlockListTheBssid()6966     public void testBtmFrameWithDisassocImminentBitBlockListTheBssid() throws Exception {
6967         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
6968         connect();
6969 
6970         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
6971 
6972         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT;
6973         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT;
6974 
6975         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
6976         mLooper.dispatchAll();
6977 
6978         verify(mWifiMetrics, never()).incrementSteeringRequestCountIncludingMboAssocRetryDelay();
6979         verify(mWifiBlocklistMonitor).blockBssidForDurationMs(eq(TEST_BSSID_STR), any(),
6980                 eq(MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS), anyInt(), anyInt());
6981     }
6982 
6983     /**
6984      * Test that handleBssTransitionRequest() trigger force scan for
6985      * network selection when status code is REJECT.
6986      */
6987     @Test
testBTMRequestRejectTriggerNetworkSelction()6988     public void testBTMRequestRejectTriggerNetworkSelction() throws Exception {
6989         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
6990         connect();
6991 
6992         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
6993 
6994         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED;
6995         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
6996                 | MboOceConstants.BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED
6997                 | MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED;
6998         btmFrmData.mBlockListDurationMs = 60000;
6999 
7000         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
7001         mLooper.dispatchAll();
7002 
7003         verify(mWifiBlocklistMonitor, never()).blockBssidForDurationMs(eq(TEST_BSSID_STR),
7004                 any(), eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt());
7005         verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
7006         verify(mWifiMetrics, times(1)).incrementMboCellularSwitchRequestCount();
7007         verify(mWifiMetrics, times(1))
7008                 .incrementForceScanCountDueToSteeringRequest();
7009 
7010     }
7011 
7012     /**
7013      * Test that handleBssTransitionRequest() does not trigger force
7014      * scan when status code is accept.
7015      */
7016     @Test
testBTMRequestAcceptDoNotTriggerNetworkSelction()7017     public void testBTMRequestAcceptDoNotTriggerNetworkSelction() throws Exception {
7018         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
7019         connect();
7020 
7021         MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
7022 
7023         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT;
7024         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT;
7025 
7026         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
7027         mLooper.dispatchAll();
7028 
7029         verify(mWifiConnectivityManager, never())
7030                 .forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
7031     }
7032 
createIE(int id, byte[] bytes)7033     private static ScanResult.InformationElement createIE(int id, byte[] bytes) {
7034         ScanResult.InformationElement ie = new ScanResult.InformationElement();
7035         ie.id = id;
7036         ie.bytes = bytes;
7037         return ie;
7038     }
7039 
7040     /**
7041      * Helper function for setting up fils test.
7042      *
7043      * @param isDriverSupportFils true if driver support fils.
7044      * @return wifi configuration.
7045      */
setupFilsTest(boolean isDriverSupportFils)7046     private WifiConfiguration setupFilsTest(boolean isDriverSupportFils) {
7047         WifiConfiguration config = new WifiConfiguration();
7048         config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
7049         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
7050         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
7051         config.SSID = ScanResultUtil.createQuotedSsid(sFilsSsid);
7052         config.networkId = 1;
7053         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
7054         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
7055 
7056         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config);
7057         if (isDriverSupportFils) {
7058             when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
7059                     createCapabilityBitset(WifiManager.WIFI_FEATURE_FILS_SHA256,
7060                             WifiManager.WIFI_FEATURE_FILS_SHA384));
7061         } else {
7062             when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
7063         }
7064 
7065         return config;
7066     }
7067 
7068     /**
7069      * Helper function for setting up a scan result with FILS supported AP.
7070      *
7071      */
setupFilsEnabledApInScanResult()7072     private void setupFilsEnabledApInScanResult() {
7073         String caps = "[WPA2-EAP/SHA1+EAP/SHA256+EAP-FILS-SHA256-CCMP]"
7074                 + "[RSN-EAP/SHA1+EAP/SHA256+EAP-FILS-SHA256-CCMP][ESS]";
7075         ScanResult scanResult = new ScanResult.Builder(WifiSsid.fromUtf8Text(sFilsSsid),
7076                 TEST_BSSID_STR)
7077                 .setHessid(1245)
7078                 .setCaps(caps)
7079                 .setRssi(-78)
7080                 .setFrequency(2450)
7081                 .setTsf(1025)
7082                 .setDistanceCm(22)
7083                 .setDistanceSdCm(33)
7084                 .setIs80211McRTTResponder(true)
7085                 .build();
7086         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
7087                 sFilsSsid.getBytes(StandardCharsets.UTF_8));
7088         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
7089         when(mScanRequestProxy.getScanResults()).thenReturn(Arrays.asList(scanResult));
7090         when(mScanRequestProxy.getScanResult(eq(TEST_BSSID_STR))).thenReturn(scanResult);
7091     }
7092 
7093 
7094     /**
7095      * Helper function to send CMD_START_FILS_CONNECTION along with HLP IEs.
7096      *
7097      */
prepareFilsHlpPktAndSendStartConnect()7098     private void prepareFilsHlpPktAndSendStartConnect() {
7099         Layer2PacketParcelable l2Packet = new Layer2PacketParcelable();
7100         l2Packet.dstMacAddress = TEST_GLOBAL_MAC_ADDRESS;
7101         l2Packet.payload = new byte[] {0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13,
7102                 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x00, 0x12, 0x13, 0x55, 0x66};
7103         mIpClientCallback.onPreconnectionStart(Collections.singletonList(l2Packet));
7104         mLooper.dispatchAll();
7105         assertEquals("L2ConnectingState", mCmi.getCurrentState().getName());
7106     }
7107 
7108     /**
7109      * Verifies that while connecting to AP, the logic looks into the scan result and
7110      * looks for AP matching the network type and ssid and update the wificonfig with FILS
7111      * AKM if supported.
7112      *
7113      * @throws Exception
7114      */
7115     @Test
testFilsAKMUpdateBeforeConnect()7116     public void testFilsAKMUpdateBeforeConnect() throws Exception {
7117         initializeAndAddNetworkAndVerifySuccess();
7118         WifiConfiguration config = setupFilsTest(true);
7119         setupFilsEnabledApInScanResult();
7120 
7121         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7122         mLooper.dispatchAll();
7123 
7124         assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
7125         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
7126     }
7127 
7128     /**
7129      * Verifies that while connecting to AP, framework updates the wifi config with
7130      * FILS AKM only if underlying driver support FILS feature.
7131      *
7132      * @throws Exception
7133      */
7134     @Test
testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils()7135     public void testFilsAkmIsNotAddedinWifiConfigIfDriverDoesNotSupportFils() throws Exception {
7136         initializeAndAddNetworkAndVerifySuccess();
7137         WifiConfiguration config = setupFilsTest(false);
7138         setupFilsEnabledApInScanResult();
7139 
7140         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7141         mLooper.dispatchAll();
7142 
7143         assertFalse(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.FILS_SHA256));
7144         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
7145     }
7146 
7147 
7148     /**
7149      * Verifies that the HLP (DHCP) packets are send to wpa_supplicant
7150      * prior to Fils connection.
7151      *
7152      * @throws Exception
7153      */
7154     @Test
testFilsHlpUpdateBeforeFilsConnection()7155     public void testFilsHlpUpdateBeforeFilsConnection() throws Exception {
7156         initializeAndAddNetworkAndVerifySuccess();
7157         WifiConfiguration config = setupFilsTest(true);
7158         setupFilsEnabledApInScanResult();
7159 
7160         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7161         mLooper.dispatchAll();
7162 
7163         prepareFilsHlpPktAndSendStartConnect();
7164 
7165         verify(mWifiNative).flushAllHlp(eq(WIFI_IFACE_NAME));
7166         verify(mWifiNative).addHlpReq(eq(WIFI_IFACE_NAME), any(), any());
7167         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
7168     }
7169 
7170     /**
7171      * Verifies that an association rejection in first FILS connect attempt doesn't block
7172      * the second connection attempt.
7173      *
7174      * @throws Exception
7175      */
7176     @Test
testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject()7177     public void testFilsSecondConnectAttemptIsNotBLockedAfterAssocReject() throws Exception {
7178         initializeAndAddNetworkAndVerifySuccess();
7179         WifiConfiguration config = setupFilsTest(true);
7180         setupFilsEnabledApInScanResult();
7181 
7182         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7183         mLooper.dispatchAll();
7184 
7185         prepareFilsHlpPktAndSendStartConnect();
7186 
7187         verify(mWifiNative, times(1)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
7188 
7189         mCmi.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT,
7190                 new AssocRejectEventInfo(TEST_SSID, TEST_BSSID_STR, 2, false));
7191         mLooper.dispatchAll();
7192 
7193         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7194         mLooper.dispatchAll();
7195         prepareFilsHlpPktAndSendStartConnect();
7196 
7197         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
7198     }
7199 
7200     /**
7201      * Verifies Fils connection.
7202      *
7203      * @throws Exception
7204      */
7205     @Test
testFilsConnection()7206     public void testFilsConnection() throws Exception {
7207         initializeAndAddNetworkAndVerifySuccess();
7208         WifiConfiguration config = setupFilsTest(true);
7209         setupFilsEnabledApInScanResult();
7210 
7211         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7212         mLooper.dispatchAll();
7213         assertEquals("L2ConnectingState", mCmi.getCurrentState().getName());
7214 
7215         prepareFilsHlpPktAndSendStartConnect();
7216 
7217         verify(mWifiMetrics, times(1)).incrementConnectRequestWithFilsAkmCount();
7218 
7219         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
7220                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, true, null));
7221         mLooper.dispatchAll();
7222 
7223         verify(mWifiMetrics, times(1)).incrementL2ConnectionThroughFilsAuthCount();
7224 
7225         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
7226                 new StateChangeResult(0, WifiSsid.fromUtf8Text(sFilsSsid),
7227                 TEST_BSSID_STR, sFreq, SupplicantState.COMPLETED));
7228         mLooper.dispatchAll();
7229 
7230         assertEquals("L3ProvisioningState", getCurrentState().getName());
7231 
7232         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
7233         dhcpResults.baseConfiguration = new StaticIpConfiguration();
7234         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
7235         dhcpResults.baseConfiguration.ipAddress =
7236                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
7237         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
7238         dhcpResults.leaseDuration = 3600;
7239 
7240         injectDhcpSuccess(dhcpResults);
7241         mLooper.dispatchAll();
7242 
7243         WifiInfo wifiInfo = mWifiInfo;
7244         assertNotNull(wifiInfo);
7245         assertEquals(TEST_BSSID_STR, wifiInfo.getBSSID());
7246         assertTrue(WifiSsid.fromUtf8Text(sFilsSsid).equals(wifiInfo.getWifiSsid()));
7247         assertEquals("L3ConnectedState", getCurrentState().getName());
7248     }
7249 
7250     /**
7251      * Verifies that while connecting to secondary STA, framework doesn't change the roaming
7252      * configuration.
7253      * @throws Exception
7254      */
7255     @Test
testConnectSecondaryStaNotChangeRoamingConfig()7256     public void testConnectSecondaryStaNotChangeRoamingConfig() throws Exception {
7257         initializeAndAddNetworkAndVerifySuccess();
7258         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED);
7259         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7260         mLooper.dispatchAll();
7261 
7262         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(mTestConfig));
7263         verify(mWifiBlocklistMonitor, never()).setAllowlistSsids(anyString(), any());
7264     }
7265 
7266     /**
7267      * Tests the wifi info is updated correctly for connecting network.
7268      */
7269     @Test
testWifiInfoOnConnectingNextNetwork()7270     public void testWifiInfoOnConnectingNextNetwork() throws Exception {
7271         mConnectedNetwork.ephemeral = true;
7272         mConnectedNetwork.trusted = true;
7273         mConnectedNetwork.oemPaid = true;
7274         mConnectedNetwork.oemPrivate = true;
7275         mConnectedNetwork.carrierMerged = true;
7276         mConnectedNetwork.osu = true;
7277         mConnectedNetwork.subscriptionId = DATA_SUBID;
7278 
7279         triggerConnect();
7280         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
7281                 .thenReturn(mScanDetailCache);
7282 
7283         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
7284                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
7285         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
7286                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
7287 
7288         // before the fist success connection, there is no valid wifi info.
7289         assertEquals(WifiConfiguration.INVALID_NETWORK_ID, mWifiInfo.getNetworkId());
7290 
7291         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
7292                 new StateChangeResult(FRAMEWORK_NETWORK_ID,
7293                     TEST_WIFI_SSID, TEST_BSSID_STR, sFreq, SupplicantState.ASSOCIATED));
7294         mLooper.dispatchAll();
7295 
7296         // retrieve correct wifi info on receiving the supplicant state change event.
7297         assertEquals(FRAMEWORK_NETWORK_ID, mWifiInfo.getNetworkId());
7298         assertEquals(mConnectedNetwork.ephemeral, mWifiInfo.isEphemeral());
7299         assertEquals(mConnectedNetwork.trusted, mWifiInfo.isTrusted());
7300         assertEquals(mConnectedNetwork.osu, mWifiInfo.isOsuAp());
7301         assertEquals(mConnectedNetwork.restricted, mWifiInfo.isRestricted());
7302         if (SdkLevel.isAtLeastS()) {
7303             assertEquals(mConnectedNetwork.oemPaid, mWifiInfo.isOemPaid());
7304             assertEquals(mConnectedNetwork.oemPrivate, mWifiInfo.isOemPrivate());
7305             assertEquals(mConnectedNetwork.carrierMerged, mWifiInfo.isCarrierMerged());
7306             assertEquals(DATA_SUBID, mWifiInfo.getSubscriptionId());
7307         }
7308     }
7309 
7310     /**
7311      * Verify that we disconnect when we mark a previous unmetered network metered.
7312      */
7313     @Test
verifyDisconnectOnMarkingNetworkMetered()7314     public void verifyDisconnectOnMarkingNetworkMetered() throws Exception {
7315         connect();
7316         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7317             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7318         });
7319 
7320         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7321         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
7322 
7323         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7324                 .getAllValues()) {
7325             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7326         }
7327         mLooper.dispatchAll();
7328         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7329         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
7330                 eq(StaEvent.DISCONNECT_NETWORK_METERED));
7331     }
7332 
7333     /**
7334      * Verify that we only update capabilites when we mark a previous unmetered network metered.
7335      */
7336     @Test
verifyUpdateCapabilitiesOnMarkingNetworkUnmetered()7337     public void verifyUpdateCapabilitiesOnMarkingNetworkUnmetered() throws Exception {
7338         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
7339         connect();
7340         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7341             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7342         });
7343         reset(mWifiNetworkAgent);
7344 
7345         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7346         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
7347 
7348         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7349                 .getAllValues()) {
7350             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7351         }
7352         mLooper.dispatchAll();
7353         assertEquals("L3ConnectedState", getCurrentState().getName());
7354 
7355         expectNetworkAgentUpdateCapabilities((cap) -> {
7356             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7357         });
7358     }
7359 
7360 
7361     /**
7362      * Verify that we disconnect when we mark a previous unmetered network metered.
7363      */
7364     @Test
verifyDisconnectOnMarkingNetworkAutoMeteredWithMeteredHint()7365     public void verifyDisconnectOnMarkingNetworkAutoMeteredWithMeteredHint() throws Exception {
7366         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
7367         connect();
7368         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7369             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7370         });
7371         reset(mWifiNetworkAgent);
7372 
7373         // Mark network metered none.
7374         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7375         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
7376 
7377         // Set metered hint in WifiInfo (either via DHCP or ScanResult IE).
7378         WifiInfo wifiInfo = mWifiInfo;
7379         wifiInfo.setMeteredHint(true);
7380 
7381         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7382                 .getAllValues()) {
7383             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7384         }
7385         mLooper.dispatchAll();
7386         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7387     }
7388 
7389     /**
7390      * Verify that we only update capabilites when we mark a previous unmetered network metered.
7391      */
7392     @Test
verifyUpdateCapabilitiesOnMarkingNetworkAutoMeteredWithoutMeteredHint()7393     public void verifyUpdateCapabilitiesOnMarkingNetworkAutoMeteredWithoutMeteredHint()
7394             throws Exception {
7395         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
7396         connect();
7397         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7398             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7399         });
7400         reset(mWifiNetworkAgent);
7401 
7402         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7403         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
7404 
7405         // Reset metered hint in WifiInfo.
7406         WifiInfo wifiInfo = mWifiInfo;
7407         wifiInfo.setMeteredHint(false);
7408 
7409         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7410                 .getAllValues()) {
7411             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7412         }
7413         mLooper.dispatchAll();
7414         assertEquals("L3ConnectedState", getCurrentState().getName());
7415 
7416         expectNetworkAgentUpdateCapabilities((cap) -> {
7417             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7418         });
7419     }
7420 
7421     /**
7422      * Verify that we do nothing on no metered change.
7423      */
7424     @Test
verifyDoNothingMarkingNetworkAutoMeteredWithMeteredHint()7425     public void verifyDoNothingMarkingNetworkAutoMeteredWithMeteredHint() throws Exception {
7426         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_METERED;
7427         connect();
7428         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7429             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7430         });
7431         reset(mWifiNetworkAgent);
7432 
7433         // Mark network metered none.
7434         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7435         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
7436 
7437         // Set metered hint in WifiInfo (either via DHCP or ScanResult IE).
7438         WifiInfo wifiInfo = mWifiInfo;
7439         wifiInfo.setMeteredHint(true);
7440 
7441         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7442                 .getAllValues()) {
7443             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7444         }
7445         mLooper.dispatchAll();
7446         assertEquals("L3ConnectedState", getCurrentState().getName());
7447 
7448         verifyNoMoreInteractions(mWifiNetworkAgent);
7449     }
7450 
7451     /**
7452      * Verify that we do nothing on no metered change.
7453      */
7454     @Test
verifyDoNothingMarkingNetworkAutoMeteredWithoutMeteredHint()7455     public void verifyDoNothingMarkingNetworkAutoMeteredWithoutMeteredHint() throws Exception {
7456         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NOT_METERED;
7457         connect();
7458         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
7459             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
7460         });
7461         reset(mWifiNetworkAgent);
7462 
7463         // Mark network metered none.
7464         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7465         mConnectedNetwork.meteredOverride = METERED_OVERRIDE_NONE;
7466 
7467         // Reset metered hint in WifiInfo.
7468         WifiInfo wifiInfo = mWifiInfo;
7469         wifiInfo.setMeteredHint(false);
7470 
7471         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7472                 .getAllValues()) {
7473             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
7474         }
7475         mLooper.dispatchAll();
7476         assertEquals("L3ConnectedState", getCurrentState().getName());
7477 
7478         verifyNoMoreInteractions(mWifiNetworkAgent);
7479     }
7480 
7481     /*
7482      * Verify that network cached data is cleared correctly in
7483      * disconnected state.
7484      */
7485     @Test
testNetworkCachedDataIsClearedCorrectlyInDisconnectedState()7486     public void testNetworkCachedDataIsClearedCorrectlyInDisconnectedState() throws Exception {
7487         // Setup CONNECT_MODE & a WifiConfiguration
7488         initializeAndAddNetworkAndVerifySuccess();
7489         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7490         mLooper.dispatchAll();
7491 
7492         // got UNSPECIFIED during this connection attempt
7493         DisconnectEventInfo disconnectEventInfo =
7494                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 1, false);
7495         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7496         mLooper.dispatchAll();
7497 
7498         assertEquals("DisconnectedState", getCurrentState().getName());
7499         verify(mWifiNative, never()).removeNetworkCachedData(anyInt());
7500 
7501         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
7502         mLooper.dispatchAll();
7503         // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt
7504         disconnectEventInfo = new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 15, false);
7505         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7506         mLooper.dispatchAll();
7507 
7508         assertEquals("DisconnectedState", getCurrentState().getName());
7509         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
7510     }
7511 
7512     /*
7513      * Verify that network cached data is cleared correctly in
7514      * disconnected state.
7515      */
7516     @Test
testNetworkCachedDataIsClearedCorrectlyInL3ProvisioningState()7517     public void testNetworkCachedDataIsClearedCorrectlyInL3ProvisioningState() throws Exception {
7518         initializeAndAddNetworkAndVerifySuccess();
7519 
7520         verify(mWifiNative).removeAllNetworks(WIFI_IFACE_NAME);
7521 
7522         startConnectSuccess();
7523 
7524         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
7525                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
7526         mLooper.dispatchAll();
7527 
7528         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
7529                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
7530                         SupplicantState.COMPLETED));
7531         mLooper.dispatchAll();
7532 
7533         assertEquals("L3ProvisioningState", getCurrentState().getName());
7534 
7535         // got 4WAY_HANDSHAKE_TIMEOUT during this connection attempt
7536         DisconnectEventInfo disconnectEventInfo =
7537                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 15, false);
7538         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7539         mLooper.dispatchAll();
7540 
7541         verify(mWifiNative).removeNetworkCachedData(FRAMEWORK_NETWORK_ID);
7542     }
7543 
7544     /*
7545      * Verify that network cached data is NOT cleared in L3ConnectedState.
7546      */
7547     @Test
testNetworkCachedDataIsClearedIf4WayHandshakeFailure()7548     public void testNetworkCachedDataIsClearedIf4WayHandshakeFailure() throws Exception {
7549         when(mWifiScoreCard.detectAbnormalDisconnection(any()))
7550                 .thenReturn(WifiHealthMonitor.REASON_SHORT_CONNECTION_NONLOCAL);
7551         InOrder inOrderWifiLockManager = inOrder(mWifiLockManager);
7552         connect();
7553         inOrderWifiLockManager.verify(mWifiLockManager)
7554                 .updateWifiClientConnected(mClientModeManager, true);
7555 
7556         // got 4WAY_HANDSHAKE_TIMEOUT
7557         DisconnectEventInfo disconnectEventInfo =
7558                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 15, false);
7559         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7560         mLooper.dispatchAll();
7561         verify(mWifiNative, never()).removeNetworkCachedData(anyInt());
7562     }
7563 
7564     /**
7565      * Verify that network cached data is cleared on changing the credential.
7566      */
7567     @Test
testNetworkCachedDataIsClearedOnChangingTheCredential()7568     public void testNetworkCachedDataIsClearedOnChangingTheCredential() throws Exception {
7569         mConnectedNetwork = spy(WifiConfigurationTestUtil.createPasspointNetwork());
7570         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
7571         mConnectedNetwork.enterpriseConfig.setPassword("fakePassword");
7572 
7573         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
7574                 .getAllValues()) {
7575             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, true);
7576         }
7577         mLooper.dispatchAll();
7578         verify(mWifiNative).removeNetworkCachedData(eq(oldConfig.networkId));
7579     }
7580 
7581 
7582     @Test
testVerifyWifiInfoStateOnFrameworkDisconnect()7583     public void testVerifyWifiInfoStateOnFrameworkDisconnect() throws Exception {
7584         connect();
7585 
7586         assertEquals(mWifiInfo.getSupplicantState(), SupplicantState.COMPLETED);
7587 
7588         // Now trigger disconnect
7589         mCmi.disconnect();
7590         mLooper.dispatchAll();
7591 
7592         // get disconnect event
7593         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
7594                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
7595                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
7596         mLooper.dispatchAll();
7597 
7598         assertEquals(mWifiInfo.getSupplicantState(), SupplicantState.DISCONNECTED);
7599     }
7600 
7601     @Test
testVerifyWifiInfoStateOnFrameworkDisconnectButMissingDisconnectEvent()7602     public void testVerifyWifiInfoStateOnFrameworkDisconnectButMissingDisconnectEvent()
7603             throws Exception {
7604         connect();
7605 
7606         assertEquals(mWifiInfo.getSupplicantState(), SupplicantState.COMPLETED);
7607 
7608         // Now trigger disconnect
7609         mCmi.disconnect();
7610         mLooper.dispatchAll();
7611 
7612         // missing disconnect event, but got supplicant state change with disconnect state instead.
7613         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
7614                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
7615                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
7616         mLooper.dispatchAll();
7617 
7618         assertEquals(mWifiInfo.getSupplicantState(), SupplicantState.DISCONNECTED);
7619     }
7620 
7621     /**
7622      * Ensures that we only disable the current network & set MAC address only when we exit
7623      * ConnectingState.
7624      * @throws Exception
7625      */
7626     @Test
testDisableNetworkOnExitingConnectingOrConnectedState()7627     public void testDisableNetworkOnExitingConnectingOrConnectedState() throws Exception {
7628         connect();
7629         String oldSsid = mConnectedNetwork.SSID;
7630 
7631         // Trigger connection to a different network
7632         mConnectedNetwork.SSID = "\"" + oldSsid.concat("blah") + "\"";
7633         mConnectedNetwork.networkId++;
7634         mConnectedNetwork.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
7635         setupAndStartConnectSequence(mConnectedNetwork);
7636 
7637         // Send disconnect event for the old network.
7638         DisconnectEventInfo disconnectEventInfo =
7639                 new DisconnectEventInfo(oldSsid, TEST_BSSID_STR, 0, false);
7640         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7641         mLooper.dispatchAll();
7642 
7643         assertEquals("L2ConnectingState", getCurrentState().getName());
7644         // Since we remain in connecting state, we should not disable the network or set random MAC
7645         // address on disconnect.
7646         verify(mWifiNative, never()).disableNetwork(WIFI_IFACE_NAME);
7647         // Set MAC address thrice - once at bootup, twice for the 2 connections.
7648         verify(mWifiNative, times(3)).setStaMacAddress(eq(WIFI_IFACE_NAME), any());
7649 
7650         // Send disconnect event for the new network.
7651         disconnectEventInfo =
7652                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
7653         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
7654         mLooper.dispatchAll();
7655 
7656         verify(mWifiNative).disableNetwork(WIFI_IFACE_NAME);
7657         // Set MAC address thrice - once at bootup, twice for the connections,
7658         // once for the disconnect.
7659         verify(mWifiNative, times(4)).setStaMacAddress(eq(WIFI_IFACE_NAME), any());
7660     }
7661 
7662     @Test
testIpReachabilityFailureConfirmTriggersDisconnection()7663     public void testIpReachabilityFailureConfirmTriggersDisconnection() throws Exception {
7664         assumeTrue(SdkLevel.isAtLeastT());
7665         connect();
7666         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7667         reset(mWifiNetworkAgent);
7668 
7669         // normal behavior w/o overlay
7670         when(mWifiGlobals.disableNudDisconnectsForWapiInSpecificCc()).thenReturn(false);
7671         when(mWifiCountryCode.getCountryCode()).thenReturn("CN");
7672 
7673         // Trigger ip reachability failure and ensure we trigger a disconnect.
7674         ReachabilityLossInfoParcelable lossInfo =
7675                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
7676         mIpClientCallback.onReachabilityFailure(lossInfo);
7677         mLooper.dispatchAll();
7678         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7679     }
7680 
7681     @Test
testIpReachabilityFailureConfirmDoesNotTriggersDisconnectionForWapi()7682     public void testIpReachabilityFailureConfirmDoesNotTriggersDisconnectionForWapi()
7683             throws Exception {
7684         mConnectedNetwork = spy(WifiConfigurationTestUtil.createWapiPskNetwork());
7685 
7686         assumeTrue(SdkLevel.isAtLeastT());
7687         connect();
7688         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7689         reset(mWifiNetworkAgent);
7690 
7691         when(mWifiGlobals.disableNudDisconnectsForWapiInSpecificCc()).thenReturn(true);
7692         when(mWifiCountryCode.getCountryCode()).thenReturn("CN");
7693 
7694         // Trigger ip reachability failure and ensure we trigger a disconnect.
7695         ReachabilityLossInfoParcelable lossInfo =
7696                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.CONFIRM);
7697         mIpClientCallback.onReachabilityFailure(lossInfo);
7698         mLooper.dispatchAll();
7699         if (SdkLevel.isAtLeastV()) {
7700             verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7701         } else {
7702             verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7703         }
7704     }
7705 
7706     @Test
testIpReachabilityMonitorNotStartOnStaticIpConfiguration()7707     public void testIpReachabilityMonitorNotStartOnStaticIpConfiguration() throws Exception {
7708         final List<InetAddress> dnsServers = new ArrayList<>();
7709         dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
7710         dnsServers.add(InetAddresses.parseNumericAddress("4.4.4.4"));
7711         final StaticIpConfiguration staticIpConfig =
7712                 new StaticIpConfiguration.Builder()
7713                         .setIpAddress(new LinkAddress("192.0.2.2/25"))
7714                         .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
7715                         .setDnsServers(dnsServers)
7716                         .build();
7717         final IpConfiguration ipConfig = new IpConfiguration();
7718         ipConfig.setStaticIpConfiguration(staticIpConfig);
7719         ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC);
7720         mConnectedNetwork.setIpConfiguration(ipConfig);
7721 
7722         triggerConnect();
7723         validateConnectionInfo();
7724 
7725         // Simulate L2 connection.
7726         final WifiSsid wifiSsid =
7727                 WifiSsid.fromBytes(
7728                         NativeUtil.byteArrayFromArrayList(
7729                                 NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
7730         mCmi.sendMessage(
7731                 WifiMonitor.NETWORK_CONNECTION_EVENT,
7732                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
7733         mLooper.dispatchAll();
7734 
7735         // Simulate L3 connection.
7736         final DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
7737         dhcpResults.baseConfiguration = staticIpConfig;
7738         injectDhcpSuccess(dhcpResults);
7739         mLooper.dispatchAll();
7740         expectRegisterNetworkAgent((agentConfig) -> {}, (cap) -> {});
7741 
7742         verify(mIpClient).startProvisioning(mProvisioningConfigurationCaptor.capture());
7743         assertFalse(mProvisioningConfigurationCaptor.getValue().usingIpReachabilityMonitor);
7744     }
7745 
doIpReachabilityFailureTest(int lossReason, boolean shouldWifiDisconnect)7746     private void doIpReachabilityFailureTest(int lossReason, boolean shouldWifiDisconnect)
7747             throws Exception {
7748         assumeTrue(SdkLevel.isAtLeastU());
7749         connect();
7750         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7751         reset(mWifiNetworkAgent);
7752 
7753         // Trigger ip reachability failure from cmd_confirm or organic kernel probe and ensure
7754         // wifi never disconnects and eventually state machine transits to L3ProvisioningState
7755         // on U and above, but wifi should still disconnect on previous platforms.
7756         ReachabilityLossInfoParcelable lossInfo =
7757                 new ReachabilityLossInfoParcelable("", lossReason);
7758         mIpClientCallback.onReachabilityFailure(lossInfo);
7759         mLooper.dispatchAll();
7760         if (!shouldWifiDisconnect) {
7761             verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7762             assertEquals("L3ProvisioningState", getCurrentState().getName());
7763         } else {
7764             verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7765         }
7766     }
7767 
7768     @Test
testIpReachabilityFailureConfirm_enableHandleRssiOrganicKernelFailuresFlag()7769     public void testIpReachabilityFailureConfirm_enableHandleRssiOrganicKernelFailuresFlag()
7770             throws Exception {
7771         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
7772 
7773         doIpReachabilityFailureTest(ReachabilityLossReason.CONFIRM,
7774                 false /* shouldWifiDisconnect */);
7775     }
7776 
7777     @Test
testIpReachabilityFailureConfirm_disableHandleRssiOrganicKernelFailuresFlag()7778     public void testIpReachabilityFailureConfirm_disableHandleRssiOrganicKernelFailuresFlag()
7779             throws Exception {
7780         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(false);
7781 
7782         // should still disconnect in following scenario
7783         mConnectedNetwork = spy(WifiConfigurationTestUtil.createPskNetwork());
7784         when(mWifiGlobals.disableNudDisconnectsForWapiInSpecificCc()).thenReturn(true);
7785         when(mWifiCountryCode.getCurrentDriverCountryCode()).thenReturn("CN");
7786 
7787         doIpReachabilityFailureTest(ReachabilityLossReason.CONFIRM,
7788                 true /* shouldWifiDisconnect */);
7789     }
7790 
7791     @Test
testIpReachabilityFailureOrganicTriggersDisconnection()7792     public void testIpReachabilityFailureOrganicTriggersDisconnection() throws Exception {
7793         assumeTrue(SdkLevel.isAtLeastT());
7794         connect();
7795         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7796         reset(mWifiNetworkAgent);
7797 
7798         // Trigger ip reachability failure and ensure we trigger a disconnect.
7799         ReachabilityLossInfoParcelable lossInfo =
7800                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ORGANIC);
7801         mIpClientCallback.onReachabilityFailure(lossInfo);
7802         mLooper.dispatchAll();
7803         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7804     }
7805 
7806     /**
7807      * Verify that when HandleRssiOrganicKernelFailuresEnabled, multiple IP reachability failures
7808      * within a specified time window will lead to disconnect and network disabled.
7809      */
7810     @Test
testRepeatedIpReachabilityFailureDisableNetwork()7811     public void testRepeatedIpReachabilityFailureDisableNetwork() throws Exception {
7812         assumeTrue(SdkLevel.isAtLeastU());
7813         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
7814         int failureThreshold = 5;
7815         int failureWindowMs = 60000;
7816         when(mWifiGlobals.getRepeatedNudFailuresThreshold()).thenReturn(failureThreshold);
7817         when(mWifiGlobals.getRepeatedNudFailuresWindowMs()).thenReturn(failureWindowMs);
7818         when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
7819 
7820         connect();
7821         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7822         reset(mWifiNetworkAgent);
7823 
7824         for (int i = 0; i < failureThreshold; i++) {
7825             // increment time outside the failure window. Failure counter should never add up and
7826             // thus not trigger blocking.
7827             when(mClock.getElapsedSinceBootMillis()).thenReturn(
7828                     (long) (i + 1) * (failureWindowMs + 1));
7829             verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7830             verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
7831                     eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
7832             ReachabilityLossInfoParcelable lossInfo =
7833                     new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ORGANIC);
7834             mIpClientCallback.onReachabilityFailure(lossInfo);
7835             mLooper.dispatchAll();
7836         }
7837 
7838         // Now trigger NUD failure within the failure window and verify the network is blocked.
7839         for (int i = 0; i < failureThreshold - 1; i++) {
7840             when(mClock.getElapsedSinceBootMillis()).thenReturn(
7841                     (long) (i + failureThreshold + 1) * (failureWindowMs));
7842             verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7843             verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
7844                     eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
7845             ReachabilityLossInfoParcelable lossInfo =
7846                     new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ORGANIC);
7847             mIpClientCallback.onReachabilityFailure(lossInfo);
7848             mLooper.dispatchAll();
7849         }
7850 
7851         // Should disconnect and block network after the last iteration.
7852         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
7853                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
7854         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7855     }
7856 
7857     @Test
testIpReachabilityFailureOrganic_enableHandleRssiOrganicKernelFailuresFlag()7858     public void testIpReachabilityFailureOrganic_enableHandleRssiOrganicKernelFailuresFlag()
7859             throws Exception {
7860         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
7861 
7862         doIpReachabilityFailureTest(ReachabilityLossReason.ORGANIC,
7863                 false /* shouldWifiDisconnect */);
7864     }
7865 
7866     @Test
testIpReachabilityFailureOrganic_disableHandleRssiOrganicKernelFailuresFlag()7867     public void testIpReachabilityFailureOrganic_disableHandleRssiOrganicKernelFailuresFlag()
7868             throws Exception {
7869         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(false);
7870 
7871         doIpReachabilityFailureTest(ReachabilityLossReason.ORGANIC,
7872                 true /* shouldWifiDisconnect */);
7873     }
7874 
7875     @Test
testIpReachabilityFailureRoamWithNullConfigDisconnect()7876     public void testIpReachabilityFailureRoamWithNullConfigDisconnect() throws Exception {
7877         assumeTrue(SdkLevel.isAtLeastT());
7878         connect();
7879         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7880         reset(mWifiNetworkAgent);
7881 
7882         // mock the current network as removed
7883         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
7884 
7885         // Trigger ip reachability failure and ensure we disconnect.
7886         ReachabilityLossInfoParcelable lossInfo =
7887                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ROAM);
7888         mIpClientCallback.onReachabilityFailure(lossInfo);
7889         mLooper.dispatchAll();
7890         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7891     }
7892 
7893     @Test
testIpReachabilityFailureRoamL3ProvisioningState()7894     public void testIpReachabilityFailureRoamL3ProvisioningState() throws Exception {
7895         assumeTrue(SdkLevel.isAtLeastT());
7896         connect();
7897         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7898         reset(mWifiNetworkAgent);
7899 
7900         // Trigger ip reachability failure and ensure we do not trigger a disconnect.
7901         ReachabilityLossInfoParcelable lossInfo =
7902                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ROAM);
7903         mIpClientCallback.onReachabilityFailure(lossInfo);
7904         mLooper.dispatchAll();
7905         verify(mWifiNetworkAgent).unregisterAfterReplacement(anyInt());
7906         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7907         assertEquals("L3ProvisioningState", getCurrentState().getName());
7908     }
7909 
7910     @Test
testIpReachabilityFailureRoamL3ProvisioningState_recreateIpClient()7911     public void testIpReachabilityFailureRoamL3ProvisioningState_recreateIpClient()
7912             throws Exception {
7913         assumeTrue(SdkLevel.isAtLeastT());
7914         connect();
7915         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7916         reset(mWifiNetworkAgent);
7917 
7918         // Save current IpClientCallbacks instance and verify the onProvisioningFailure
7919         // from this instance won't trigger wifi disconnection after recreating a new
7920         // IpClient and IpClientCallbacks in WaitBeforeL3ProvisioningState.
7921         final IpClientCallbacks callback = mIpClientCallback;
7922 
7923         // Trigger ip reachability failure and ensure we do not trigger a disconnect.
7924         ReachabilityLossInfoParcelable lossInfo =
7925                 new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ROAM);
7926         callback.onReachabilityFailure(lossInfo);
7927         mLooper.dispatchAll();
7928         verify(mWifiNetworkAgent).unregisterAfterReplacement(anyInt());
7929         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7930         assertEquals("L3ProvisioningState", getCurrentState().getName());
7931 
7932         // Verify that onProvisioningFailure from the legacy IpClientCallbacks instance
7933         // doesn't trigger wifi disconnection.
7934         callback.onProvisioningFailure(new LinkProperties());
7935         mLooper.dispatchAll();
7936         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7937 
7938         // Verify that onProvisioningFailure from the current IpClientCallbacks instance
7939         // triggers wifi disconnection.
7940         mIpClientCallback.onProvisioningFailure(new LinkProperties());
7941         mLooper.dispatchAll();
7942         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7943     }
7944 
runProvisioningFailureCalledAfterReachabilityFailureTest(int lossReason)7945     private void runProvisioningFailureCalledAfterReachabilityFailureTest(int lossReason)
7946             throws Exception {
7947         assumeTrue(SdkLevel.isAtLeastT());
7948         connect();
7949         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
7950         reset(mWifiNetworkAgent);
7951 
7952         // Save current IpClientCallbacks instance and verify an immediate IP provisioning
7953         // failure event from this instance after IP reachability failure still triggers a
7954         // WiFi disconnection due to the race, for example:
7955         // - IpClient sends onReachabilityFailure callback, wifi module receives this callback
7956         //   and post CMD_IP_REACHABILITY_FAILURE, return;
7957         // - IpClient sends onProvisioningFailure callback, wifi module receives this callback
7958         //   and post CMD_IP_CONFIGURATION_LOST, return;
7959         // - state machine processes CMD_IP_REACHABILITY_FAILURE first and eventually transition
7960         //   to WaitBeforeL3ProvisioningState and recreate an IpClient instance there.
7961         // - state machine receives CMD_IP_CONFIGURATION_LOST from the old IpClientCallbacks
7962         //   instanceat at WaitBeforeL3ProvisioningState, but defer the command to its parent state
7963         //   until transition to L3ProvisioningState.
7964         // - CMD_IP_CONFIGURATION_LOST is processed at L2ConnectedState eventually, and trigger
7965         //   WiFi disconnection there.
7966         final IpClientCallbacks callback = mIpClientCallback;
7967         final ReachabilityLossInfoParcelable lossInfo =
7968                 new ReachabilityLossInfoParcelable("", lossReason);
7969         assertNull(mCmi.getConnectingWifiConfiguration());
7970         callback.onReachabilityFailure(lossInfo);
7971         callback.onProvisioningFailure(new LinkProperties());
7972         mLooper.dispatchAll();
7973         verify(mWifiNetworkAgent).unregisterAfterReplacement(anyInt());
7974         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
7975         assertEquals("L3ProvisioningState", getCurrentState().getName());
7976         assertEquals(FRAMEWORK_NETWORK_ID, mCmi.getConnectingWifiConfiguration().networkId);
7977 
7978         // Verify that onProvisioningFailure from the current IpClientCallbacks instance
7979         // triggers wifi disconnection.
7980         mIpClientCallback.onProvisioningFailure(new LinkProperties());
7981         mLooper.dispatchAll();
7982         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
7983     }
7984 
7985     @Test
testProvisioningFailureCalledAfterReachabilityFailure_postRoam()7986     public void testProvisioningFailureCalledAfterReachabilityFailure_postRoam()
7987             throws Exception {
7988         runProvisioningFailureCalledAfterReachabilityFailureTest(ReachabilityLossReason.ROAM);
7989     }
7990 
7991     @Test
testProvisioningFailureCalledAfterReachabilityFailure_rssiConfirm()7992     public void testProvisioningFailureCalledAfterReachabilityFailure_rssiConfirm()
7993             throws Exception {
7994         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
7995 
7996         runProvisioningFailureCalledAfterReachabilityFailureTest(ReachabilityLossReason.CONFIRM);
7997     }
7998 
7999     @Test
testProvisioningFailureCalledAfterReachabilityFailure_organicKernel()8000     public void testProvisioningFailureCalledAfterReachabilityFailure_organicKernel()
8001             throws Exception {
8002         when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
8003 
8004         runProvisioningFailureCalledAfterReachabilityFailureTest(ReachabilityLossReason.ORGANIC);
8005     }
8006 
8007     @Test
testIpReachabilityLostAndRoamEventsRace()8008     public void testIpReachabilityLostAndRoamEventsRace() throws Exception {
8009         connect();
8010         expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
8011         reset(mWifiNetworkAgent);
8012 
8013         // Trigger ip reachability loss and ensure we trigger a disconnect.
8014         mIpClientCallback.onReachabilityLost("CMD_IP_REACHABILITY_LOST");
8015         mLooper.dispatchAll();
8016         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
8017 
8018         // Now send a network connection (indicating a roam) event before we get the disconnect
8019         // event.
8020         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8021                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
8022         mLooper.dispatchAll();
8023         // ensure that we ignored the transient roam while we're disconnecting.
8024         verifyNoMoreInteractions(mWifiNetworkAgent);
8025 
8026         // Now send the disconnect event and ensure that we transition to "DisconnectedState".
8027         DisconnectEventInfo disconnectEventInfo =
8028                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
8029         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
8030         mLooper.dispatchAll();
8031         assertEquals("DisconnectedState", getCurrentState().getName());
8032         verify(mWifiNetworkAgent).unregister();
8033 
8034         verifyNoMoreInteractions(mWifiNetworkAgent);
8035     }
8036 
8037     /**
8038      * Verify that roaming mode is enabled on disconnect for primary.
8039      */
8040     @Test
testRoamingModeOnDisconnectPrimary()8041     public void testRoamingModeOnDisconnectPrimary() throws Exception {
8042         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
8043         connect();
8044         mCmi.disconnect();
8045         mLooper.dispatchAll();
8046         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8047                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
8048                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
8049         mLooper.dispatchAll();
8050         verify(mWifiNative).enableFirmwareRoaming(anyString(),
8051                 eq(WifiNative.ENABLE_FIRMWARE_ROAMING));
8052     }
8053 
8054     /**
8055      * Verify that roaming mode doesn't change on disconnect for secondary.
8056      */
8057     @Test
testRoamingModeOnDisconnectSecondary()8058     public void testRoamingModeOnDisconnectSecondary() throws Exception {
8059         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
8060         connect();
8061         mCmi.disconnect();
8062         mLooper.dispatchAll();
8063         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8064                 new StateChangeResult(0, WifiSsid.fromUtf8Text(mConnectedNetwork.SSID),
8065                         TEST_BSSID_STR, sFreq, SupplicantState.DISCONNECTED));
8066         mLooper.dispatchAll();
8067         verify(mWifiNative, never()).enableFirmwareRoaming(anyString(), anyInt());
8068     }
8069 
8070     @Test
testConnectionWhileDisconnecting()8071     public void testConnectionWhileDisconnecting() throws Exception {
8072         connect();
8073 
8074         // Trigger a disconnect event.
8075         mCmi.disconnect();
8076         mLooper.dispatchAll();
8077         assertEquals("L3ConnectedState", getCurrentState().getName());
8078 
8079         // Trigger a new connection before the NETWORK_DISCONNECTION_EVENT comes in.
8080         WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
8081         config.networkId = FRAMEWORK_NETWORK_ID + 1;
8082         setupAndStartConnectSequence(config);
8083         // Ensure that we triggered the connection attempt.
8084         validateSuccessfulConnectSequence(config);
8085 
8086         // Now trigger the disconnect event for the previous disconnect and ensure we handle it
8087         // correctly and remain in ConnectingState.
8088         DisconnectEventInfo disconnectEventInfo =
8089                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
8090         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
8091         mLooper.dispatchAll();
8092         assertEquals("L2ConnectingState", mCmi.getCurrentState().getName());
8093     }
8094 
8095     @Test
testConnectionWatchdog()8096     public void testConnectionWatchdog() throws Exception {
8097         triggerConnect();
8098         Log.i(TAG, "Triggering Connect done");
8099 
8100         // Simulate watchdog timeout and ensure we retuned to disconnected state.
8101         mLooper.moveTimeForward(ClientModeImpl.CONNECTING_WATCHDOG_TIMEOUT_MS + 5L);
8102         mLooper.dispatchAll();
8103 
8104         verify(mWifiNative).disableNetwork(WIFI_IFACE_NAME);
8105         assertEquals("DisconnectedState", mCmi.getCurrentState().getName());
8106     }
8107 
8108     @Test
testRoamAfterConnectDoesNotChangeNetworkInfoInNetworkStateChangeBroadcast()8109     public void testRoamAfterConnectDoesNotChangeNetworkInfoInNetworkStateChangeBroadcast()
8110             throws Exception {
8111         connect();
8112 
8113         // The last NETWORK_STATE_CHANGED_ACTION should be to mark the network connected.
8114         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
8115 
8116         verifyNetworkStateChangedBroadcast(atLeastOnce(), intentCaptor);
8117         Intent intent = intentCaptor.getValue();
8118         assertNotNull(intent);
8119         assertEquals(WifiManager.NETWORK_STATE_CHANGED_ACTION, intent.getAction());
8120         NetworkInfo networkInfo = (NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO);
8121         assertTrue(networkInfo.isConnected());
8122 
8123         reset(mContext);
8124         when(mContext.getResources()).thenReturn(mResources);
8125         when(mContext.createContextAsUser(UserHandle.ALL, 0)).thenReturn(mUserAllContext);
8126 
8127         // send roam event
8128         mCmi.sendMessage(WifiMonitor.ASSOCIATED_BSSID_EVENT, 0, 0, TEST_BSSID_STR1);
8129         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8130                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
8131                         SupplicantState.COMPLETED));
8132         mLooper.dispatchAll();
8133 
8134         verifyNetworkStateChangedBroadcast(atLeastOnce(), intentCaptor);
8135         intent = intentCaptor.getValue();
8136         assertNotNull(intent);
8137         assertEquals(WifiManager.NETWORK_STATE_CHANGED_ACTION, intent.getAction());
8138         networkInfo = (NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO);
8139         assertTrue(networkInfo.isConnected());
8140     }
8141 
8142 
8143     /**
8144      * Ensure that {@link ClientModeImpl#dump(FileDescriptor, PrintWriter, String[])}
8145      * {@link WifiNative#getWifiLinkLayerStats(String)}, at least once before calling
8146      * {@link WifiScoreReport#dump(FileDescriptor, PrintWriter, String[])}.
8147      *
8148      * This ensures that WifiScoreReport will always get updated RSSI and link layer stats before
8149      * dumping during a bug report, no matter if the screen is on or not.
8150      */
8151     @Test
testWifiScoreReportDump()8152     public void testWifiScoreReportDump() throws Exception {
8153         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
8154                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
8155         InOrder inOrder = inOrder(mWifiNative, mWifiScoreReport);
8156         inOrder.verify(mWifiNative, never()).getWifiLinkLayerStats(any());
8157         connect();
8158 
8159         mCmi.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
8160         mLooper.dispatchAll();
8161 
8162         inOrder.verify(mWifiNative, atLeastOnce()).getWifiLinkLayerStats(any());
8163         inOrder.verify(mWifiScoreReport).dump(any(), any(), any());
8164     }
8165 
8166     @Test
testHandleScreenChangedDontUpdateLinkLayerStatsWhenDisconnected()8167     public void testHandleScreenChangedDontUpdateLinkLayerStatsWhenDisconnected() {
8168         setScreenState(true);
8169         setScreenState(false);
8170         setScreenState(true);
8171         verify(mWifiNative, never()).getWifiLinkLayerStats(any());
8172     }
8173 
8174     @Test
clearRequestingPackageNameInWifiInfoOnConnectionFailure()8175     public void clearRequestingPackageNameInWifiInfoOnConnectionFailure() throws Exception {
8176         mConnectedNetwork.fromWifiNetworkSpecifier = true;
8177         mConnectedNetwork.ephemeral = true;
8178         mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
8179 
8180         triggerConnect();
8181 
8182         // association completed
8183         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8184                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
8185                         SupplicantState.ASSOCIATED));
8186         mLooper.dispatchAll();
8187 
8188         assertTrue(mWifiInfo.isEphemeral());
8189         assertEquals(OP_PACKAGE_NAME, mWifiInfo.getRequestingPackageName());
8190 
8191         // fail the connection.
8192         DisconnectEventInfo disconnectEventInfo =
8193                 new DisconnectEventInfo(mConnectedNetwork.SSID, TEST_BSSID_STR, 0, false);
8194         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
8195         mLooper.dispatchAll();
8196 
8197         assertFalse(mWifiInfo.isEphemeral());
8198         assertNull(mWifiInfo.getRequestingPackageName());
8199     }
8200 
8201     @Test
handleAssociationRejectionWhenRoaming()8202     public void handleAssociationRejectionWhenRoaming() throws Exception {
8203         connect();
8204 
8205         assertTrue(SupplicantState.isConnecting(mWifiInfo.getSupplicantState()));
8206 
8207         when(mWifiNative.roamToNetwork(any(), any())).thenReturn(true);
8208 
8209         // Trigger roam to a BSSID.
8210         mCmi.startRoamToNetwork(FRAMEWORK_NETWORK_ID, TEST_BSSID_STR1);
8211         mLooper.dispatchAll();
8212 
8213 
8214         assertEquals(TEST_BSSID_STR1, mCmi.getConnectingBssid());
8215         assertEquals(FRAMEWORK_NETWORK_ID, mCmi.getConnectingWifiConfiguration().networkId);
8216 
8217         verify(mWifiNative).roamToNetwork(any(), any());
8218         assertEquals("RoamingState", getCurrentState().getName());
8219 
8220         // fail the connection.
8221         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8222                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, 0,
8223                         SupplicantState.DISCONNECTED));
8224         mLooper.dispatchAll();
8225 
8226         // Ensure we reset WifiInfo fields.
8227         assertFalse(SupplicantState.isConnecting(mWifiInfo.getSupplicantState()));
8228     }
8229 
8230     @Test
testOemPaidNetworkCapability()8231     public void testOemPaidNetworkCapability() throws Exception {
8232         // oemPaid introduced in S, not applicable to R
8233         assumeTrue(SdkLevel.isAtLeastS());
8234         mConnectedNetwork.oemPaid = true;
8235         connect();
8236         expectRegisterNetworkAgent((agentConfig) -> { },
8237                 (cap) -> {
8238                     assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID));
8239                     assertFalse(cap.hasCapability(NetworkCapabilities
8240                             .NET_CAPABILITY_NOT_RESTRICTED));
8241                 });
8242     }
8243     @Test
testNotOemPaidNetworkCapability()8244     public void testNotOemPaidNetworkCapability() throws Exception {
8245         // oemPaid introduced in S, not applicable to R
8246         assumeTrue(SdkLevel.isAtLeastS());
8247         mConnectedNetwork.oemPaid = false;
8248         connect();
8249         expectRegisterNetworkAgent((agentConfig) -> { },
8250                 (cap) -> {
8251                     assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID));
8252                     assertTrue(cap.hasCapability(NetworkCapabilities
8253                             .NET_CAPABILITY_NOT_RESTRICTED));
8254                 });
8255     }
8256 
8257     @Test
testRestrictedetworkCapability()8258     public void testRestrictedetworkCapability() throws Exception {
8259         // oemPaid introduced in S, not applicable to R
8260         assumeTrue(SdkLevel.isAtLeastS());
8261         mConnectedNetwork.restricted = true;
8262         connect();
8263         expectRegisterNetworkAgent((agentConfig) -> { },
8264                 (cap) -> {
8265                     assertFalse(cap.hasCapability(NetworkCapabilities
8266                             .NET_CAPABILITY_NOT_RESTRICTED));
8267                 });
8268     }
8269 
8270     @Test
testOemPrivateNetworkCapability()8271     public void testOemPrivateNetworkCapability() throws Exception {
8272         // oemPrivate introduced in S, not applicable to R
8273         assumeTrue(SdkLevel.isAtLeastS());
8274         mConnectedNetwork.oemPrivate = true;
8275         connect();
8276         expectRegisterNetworkAgent((agentConfig) -> { },
8277                 (cap) -> {
8278                     assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE));
8279                     assertFalse(cap.hasCapability(NetworkCapabilities
8280                             .NET_CAPABILITY_NOT_RESTRICTED));
8281                 });
8282     }
8283 
8284     @Test
testNotOemPrivateNetworkCapability()8285     public void testNotOemPrivateNetworkCapability() throws Exception {
8286         // oemPrivate introduced in S, not applicable to R
8287         assumeTrue(SdkLevel.isAtLeastS());
8288         mConnectedNetwork.oemPrivate = false;
8289         connect();
8290         expectRegisterNetworkAgent((agentConfig) -> { },
8291                 (cap) -> {
8292                     assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE));
8293                     assertTrue(cap.hasCapability(NetworkCapabilities
8294                             .NET_CAPABILITY_NOT_RESTRICTED));
8295                 });
8296     }
8297 
8298     @Test
testSendLinkProbeFailure()8299     public void testSendLinkProbeFailure() throws Exception {
8300         mCmi.probeLink(mLinkProbeCallback, -1);
8301 
8302         verify(mLinkProbeCallback).onFailure(LinkProbeCallback.LINK_PROBE_ERROR_NOT_CONNECTED);
8303         verify(mLinkProbeCallback, never()).onAck(anyInt());
8304         verify(mWifiNative, never()).probeLink(any(), any(), any(), anyInt());
8305     }
8306 
8307     @Test
testSendLinkProbeSuccess()8308     public void testSendLinkProbeSuccess() throws Exception {
8309         connect();
8310 
8311         mCmi.probeLink(mLinkProbeCallback, -1);
8312 
8313         verify(mWifiNative).probeLink(any(), any(), eq(mLinkProbeCallback), eq(-1));
8314         verify(mLinkProbeCallback, never()).onFailure(anyInt());
8315         verify(mLinkProbeCallback, never()).onAck(anyInt());
8316     }
8317 
setupPasspointConnection()8318     private void setupPasspointConnection() throws Exception {
8319         mConnectedNetwork = spy(WifiConfigurationTestUtil.createPasspointNetwork());
8320         mConnectedNetwork.carrierId = CARRIER_ID_1;
8321         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class)))
8322                 .thenReturn(DATA_SUBID);
8323         when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true);
8324         mConnectedNetwork.enterpriseConfig.setAnonymousIdentity("");
8325         triggerConnect();
8326 
8327         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(mConnectedNetwork);
8328         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
8329                 .thenReturn(mScanDetailCache);
8330         when(mScanRequestProxy.getScanResult(TEST_BSSID_STR)).thenReturn(
8331                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
8332         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn(
8333                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq));
8334         when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn(
8335                 getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult());
8336 
8337         WifiSsid wifiSsid = WifiSsid.fromBytes(
8338                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
8339         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8340                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null));
8341         mLooper.dispatchAll();
8342         assertEquals("L3ProvisioningState", getCurrentState().getName());
8343     }
8344 
8345     /**
8346      * When connecting to a Passpoint network, verify that the Venue URL ANQP request is sent.
8347      */
8348     @Test
testVenueUrlRequestForPasspointNetworks()8349     public void testVenueUrlRequestForPasspointNetworks() throws Exception {
8350         setupPasspointConnection();
8351         verify(mPasspointManager).requestVenueUrlAnqpElement(any(ScanResult.class));
8352         assertEquals("L3ProvisioningState", getCurrentState().getName());
8353     }
8354 
8355     /**
8356      * Verify that the Venue URL ANQP request is not sent for non-Passpoint EAP networks
8357      */
8358     @Test
testVenueUrlNotRequestedForNonPasspointNetworks()8359     public void testVenueUrlNotRequestedForNonPasspointNetworks() throws Exception {
8360         setupEapSimConnection();
8361         verify(mPasspointManager, never()).requestVenueUrlAnqpElement(any(ScanResult.class));
8362         assertEquals("L3ProvisioningState", getCurrentState().getName());
8363     }
8364 
8365     @Test
testFirmwareRoam()8366     public void testFirmwareRoam() throws Exception {
8367         connect();
8368 
8369         // Now send a network connection (indicating a roam) event
8370         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8371                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null));
8372         mLooper.dispatchAll();
8373 
8374         verifyNetworkStateChangedBroadcast(times(2),
8375                 new NetworkStateChangedIntentMatcher(CONNECTED));
8376     }
8377 
8378     @Test
testFirmwareRoamDisconnectSecondaryInternetOnSameBand()8379     public void testFirmwareRoamDisconnectSecondaryInternetOnSameBand() throws Exception {
8380         connect();
8381         // After connection, the primary should be on 2.4Ghz.
8382         assertTrue(mWifiInfo.is24GHz());
8383 
8384         // Verify no disconnection of secondary if it's on another band.
8385         ConcreteClientModeManager secondaryCmm = mock(ConcreteClientModeManager.class);
8386         WifiInfo secondaryWifiInfo = mock(WifiInfo.class);
8387         when(secondaryWifiInfo.is24GHz()).thenReturn(false);
8388         when(secondaryWifiInfo.is5GHz()).thenReturn(true);
8389         when(secondaryCmm.isConnected()).thenReturn(true);
8390         when(secondaryCmm.isSecondaryInternet()).thenReturn(true);
8391         when(secondaryCmm.getConnectionInfo()).thenReturn(secondaryWifiInfo);
8392         when(mActiveModeWarden.getClientModeManagerInRole(ROLE_CLIENT_SECONDARY_LONG_LIVED))
8393                 .thenReturn(secondaryCmm);
8394 
8395         // Now send a network connection (indicating a roam) event, and verify no disconnection
8396         // of secondary
8397         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8398                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null));
8399         mLooper.dispatchAll();
8400 
8401         assertTrue(mWifiInfo.is24GHz());
8402         verify(secondaryCmm, never()).disconnect();
8403 
8404         // Set the secondary to the same band as primary and then verify a disconnect after the
8405         // primary roams.
8406         when(secondaryWifiInfo.is24GHz()).thenReturn(true);
8407         when(secondaryWifiInfo.is5GHz()).thenReturn(false);
8408         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8409                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR1, false, null));
8410         mLooper.dispatchAll();
8411 
8412         assertTrue(mWifiInfo.is24GHz());
8413         verify(secondaryCmm).disconnect();
8414     }
8415 
8416     @Test
testProvisioningUpdateAfterConnect()8417     public void testProvisioningUpdateAfterConnect() throws Exception {
8418         connect();
8419 
8420         // Trigger a IP params update (maybe a dhcp lease renewal).
8421         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
8422         dhcpResults.baseConfiguration = new StaticIpConfiguration();
8423         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
8424         dhcpResults.baseConfiguration.ipAddress =
8425                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
8426         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
8427         dhcpResults.leaseDuration = 3600;
8428 
8429         injectDhcpSuccess(dhcpResults);
8430         mLooper.dispatchAll();
8431 
8432         verifyNetworkStateChangedBroadcast(times(2),
8433                 new NetworkStateChangedIntentMatcher(CONNECTED));
8434     }
8435 
8436     /**
8437      * Verify that the Deauth-Imminent WNM-Notification is handled by relaying to the Passpoint
8438      * Manager.
8439      */
8440     @Test
testHandlePasspointDeauthImminentWnmNotification()8441     public void testHandlePasspointDeauthImminentWnmNotification() throws Exception {
8442         setupEapSimConnection();
8443         WnmData wnmData = WnmData.createDeauthImminentEvent(TEST_BSSID, "", false,
8444                 TEST_DELAY_IN_SECONDS);
8445         mCmi.sendMessage(WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT, 0, 0, wnmData);
8446         mLooper.dispatchAll();
8447         verify(mPasspointManager).handleDeauthImminentEvent(eq(wnmData),
8448                 any(WifiConfiguration.class));
8449     }
8450 
8451     /**
8452      * Verify that the network selection status will be updated and the function onEapFailure()
8453      * in EapFailureNotifier is called when a EAP Authentication failure is detected
8454      * with carrier erroe code.
8455      */
8456     @Test
testCarrierEapFailure()8457     public void testCarrierEapFailure() throws Exception {
8458         initializeAndAddNetworkAndVerifySuccess();
8459         WifiBlocklistMonitor.CarrierSpecificEapFailureConfig eapFailureConfig =
8460                 new WifiBlocklistMonitor.CarrierSpecificEapFailureConfig(1, -1, true);
8461 
8462         startConnectSuccess();
8463 
8464         WifiConfiguration config = new WifiConfiguration();
8465         config.SSID = TEST_SSID;
8466         config.getNetworkSelectionStatus().setHasEverConnected(true);
8467         config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
8468         when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
8469         when(mEapFailureNotifier.onEapFailure(anyInt(), eq(config), anyBoolean())).thenReturn(
8470                 eapFailureConfig);
8471 
8472         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
8473                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
8474                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, DEFINED_ERROR_CODE)
8475         );
8476         mLooper.dispatchAll();
8477 
8478         verify(mEapFailureNotifier).onEapFailure(DEFINED_ERROR_CODE, config, true);
8479         verify(mWifiBlocklistMonitor).loadCarrierConfigsForDisableReasonInfos(eapFailureConfig);
8480         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
8481                 eq(WifiConfiguration.NetworkSelectionStatus
8482                         .DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR));
8483     }
8484 
8485     /**
8486      * When connected to a Passpoint network, verify that the Venue URL and T&C URL are updated in
8487      * the {@link LinkProperties} object when provisioning complete and when link properties change
8488      * events are received.
8489      */
8490     @Test
testVenueAndTCUrlsUpdateForPasspointNetworks()8491     public void testVenueAndTCUrlsUpdateForPasspointNetworks() throws Exception {
8492         // This tests new S functionality/APIs, not applicable to R.
8493         assumeTrue(SdkLevel.isAtLeastS());
8494         setupPasspointConnection();
8495         when(mPasspointManager.getVenueUrl(any(ScanResult.class))).thenReturn(new URL(VENUE_URL));
8496         WnmData wnmData = WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
8497                 TEST_TERMS_AND_CONDITIONS_URL);
8498         when(mPasspointManager.handleTermsAndConditionsEvent(eq(wnmData),
8499                 any(WifiConfiguration.class))).thenReturn(new URL(TEST_TERMS_AND_CONDITIONS_URL));
8500         mCmi.sendMessage(WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT,
8501                 0, 0, wnmData);
8502         DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable();
8503         dhcpResults.baseConfiguration = new StaticIpConfiguration();
8504         dhcpResults.baseConfiguration.gateway = InetAddresses.parseNumericAddress("1.2.3.4");
8505         dhcpResults.baseConfiguration.ipAddress =
8506                 new LinkAddress(InetAddresses.parseNumericAddress("192.168.1.100"), 0);
8507         dhcpResults.baseConfiguration.dnsServers.add(InetAddresses.parseNumericAddress("8.8.8.8"));
8508         dhcpResults.leaseDuration = 3600;
8509         injectDhcpSuccess(dhcpResults);
8510         mCmi.mNetworkAgent = null;
8511         mLooper.dispatchAll();
8512         LinkProperties linkProperties = mock(LinkProperties.class);
8513         mIpClientCallback.onLinkPropertiesChange(linkProperties);
8514         mLooper.dispatchAll();
8515         verify(mPasspointManager, times(2)).getVenueUrl(any(ScanResult.class));
8516         final ArgumentCaptor<CaptivePortalData> captivePortalDataCaptor =
8517                 ArgumentCaptor.forClass(CaptivePortalData.class);
8518         verify(linkProperties).setCaptivePortalData(captivePortalDataCaptor.capture());
8519         assertEquals(WifiConfigurationTestUtil.TEST_PROVIDER_FRIENDLY_NAME,
8520                 captivePortalDataCaptor.getValue().getVenueFriendlyName());
8521         assertEquals(VENUE_URL, captivePortalDataCaptor.getValue().getVenueInfoUrl().toString());
8522         assertEquals(TEST_TERMS_AND_CONDITIONS_URL, captivePortalDataCaptor.getValue()
8523                 .getUserPortalUrl().toString());
8524     }
8525 
8526     /**
8527      * Verify that the T&C WNM-Notification is handled by relaying to the Passpoint
8528      * Manager.
8529      */
8530     @Test
testHandlePasspointTermsAndConditionsWnmNotification()8531     public void testHandlePasspointTermsAndConditionsWnmNotification() throws Exception {
8532         setupEapSimConnection();
8533         WnmData wnmData = WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
8534                 TEST_TERMS_AND_CONDITIONS_URL);
8535         when(mPasspointManager.handleTermsAndConditionsEvent(eq(wnmData),
8536                 any(WifiConfiguration.class))).thenReturn(new URL(TEST_TERMS_AND_CONDITIONS_URL));
8537         mCmi.sendMessage(WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT,
8538                 0, 0, wnmData);
8539         mLooper.dispatchAll();
8540         verify(mPasspointManager).handleTermsAndConditionsEvent(eq(wnmData),
8541                 any(WifiConfiguration.class));
8542         verify(mWifiNative, never()).disconnect(anyString());
8543     }
8544 
8545     /**
8546      * Verify that when a bad URL is received in the T&C WNM-Notification, the connection is
8547      * disconnected.
8548      */
8549     @Test
testHandlePasspointTermsAndConditionsWnmNotificationWithBadUrl()8550     public void testHandlePasspointTermsAndConditionsWnmNotificationWithBadUrl() throws Exception {
8551         setupEapSimConnection();
8552         WnmData wnmData = WnmData.createTermsAndConditionsAccetanceRequiredEvent(TEST_BSSID,
8553                 TEST_TERMS_AND_CONDITIONS_URL);
8554         when(mPasspointManager.handleTermsAndConditionsEvent(eq(wnmData),
8555                 any(WifiConfiguration.class))).thenReturn(null);
8556         mCmi.sendMessage(WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT,
8557                 0, 0, wnmData);
8558         mLooper.dispatchAll();
8559         verify(mPasspointManager).handleTermsAndConditionsEvent(eq(wnmData),
8560                 any(WifiConfiguration.class));
8561         verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
8562         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
8563                 eq(StaEvent.DISCONNECT_PASSPOINT_TAC));
8564     }
8565 
verifyTransitionDisableEvent(String caps, int indication, boolean shouldUpdate)8566     private void verifyTransitionDisableEvent(String caps, int indication, boolean shouldUpdate)
8567             throws Exception {
8568         final int networkId = FRAMEWORK_NETWORK_ID;
8569         ScanResult scanResult = new ScanResult.Builder(WifiSsid.fromUtf8Text(sFilsSsid),
8570                 TEST_BSSID_STR)
8571                 .setHessid(1245)
8572                 .setCaps(caps)
8573                 .setRssi(-78)
8574                 .setFrequency(2450)
8575                 .setTsf(1025)
8576                 .setDistanceCm(22)
8577                 .setDistanceSdCm(33)
8578                 .setIs80211McRTTResponder(true)
8579                 .build();
8580         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
8581                 sFilsSsid.getBytes(StandardCharsets.UTF_8));
8582         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
8583         when(mScanRequestProxy.getScanResults()).thenReturn(Arrays.asList(scanResult));
8584         when(mScanRequestProxy.getScanResult(eq(TEST_BSSID_STR))).thenReturn(scanResult);
8585 
8586         initializeAndAddNetworkAndVerifySuccess();
8587 
8588         startConnectSuccess();
8589 
8590         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
8591                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
8592         mLooper.dispatchAll();
8593 
8594         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
8595                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
8596                         SupplicantState.COMPLETED));
8597         mLooper.dispatchAll();
8598 
8599         assertEquals("L3ProvisioningState", getCurrentState().getName());
8600 
8601         mCmi.sendMessage(WifiMonitor.TRANSITION_DISABLE_INDICATION,
8602                 networkId, indication);
8603         mLooper.dispatchAll();
8604 
8605         if (shouldUpdate) {
8606             verify(mWifiConfigManager).updateNetworkTransitionDisable(
8607                     eq(networkId), eq(indication));
8608         } else {
8609             verify(mWifiConfigManager, never()).updateNetworkTransitionDisable(
8610                     anyInt(), anyInt());
8611         }
8612     }
8613 
8614     /**
8615      * Verify that the Transition Disable event is routed correctly.
8616      */
8617     @Test
testUpdateSaeOnlyTransitionDisableIndicationFromPskSaeBss()8618     public void testUpdateSaeOnlyTransitionDisableIndicationFromPskSaeBss() throws Exception {
8619         String caps = "[PSK][SAE]";
8620         int indication = WifiMonitor.TDI_USE_WPA3_PERSONAL;
8621         boolean shouldUpdate = true;
8622         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8623     }
8624 
8625     /**
8626      * Verify that the Transition Disable event is routed correctly.
8627      */
8628     @Test
testUpdateSaeOnlyTransitionDisableIndicationFromSaeBss()8629     public void testUpdateSaeOnlyTransitionDisableIndicationFromSaeBss() throws Exception {
8630         String caps = "[SAE]";
8631         int indication = WifiMonitor.TDI_USE_WPA3_PERSONAL;
8632         boolean shouldUpdate = true;
8633         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8634     }
8635 
8636     /**
8637      * Verify that the Transition Disable event is routed correctly.
8638      */
8639     @Test
testDropSaeOnlyTransitionDisableIndicationFromPskBss()8640     public void testDropSaeOnlyTransitionDisableIndicationFromPskBss() throws Exception {
8641         String caps = "[PSK]";
8642         int indication = WifiMonitor.TDI_USE_WPA3_PERSONAL;
8643         boolean shouldUpdate = false;
8644         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8645     }
8646 
8647     /**
8648      * Verify that the Transition Disable event is routed correctly.
8649      */
8650     @Test
testUpdateSaePkTransitionDisableIndicationFromPskSaeBss()8651     public void testUpdateSaePkTransitionDisableIndicationFromPskSaeBss() throws Exception {
8652         String caps = "[PSK][SAE]";
8653         int indication = WifiMonitor.TDI_USE_SAE_PK;
8654         boolean shouldUpdate = true;
8655         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8656     }
8657 
8658     /**
8659      * Verify that the Transition Disable event is routed correctly.
8660      */
8661     @Test
testUpdateSaePkTransitionDisableIndicationFromSaeBss()8662     public void testUpdateSaePkTransitionDisableIndicationFromSaeBss() throws Exception {
8663         String caps = "[SAE]";
8664         int indication = WifiMonitor.TDI_USE_SAE_PK;
8665         boolean shouldUpdate = true;
8666         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8667     }
8668 
8669     /**
8670      * Verify that the Transition Disable event is routed correctly.
8671      */
8672     @Test
testDropSaePkTransitionDisableIndicationFromPskBss()8673     public void testDropSaePkTransitionDisableIndicationFromPskBss() throws Exception {
8674         String caps = "[PSK]";
8675         int indication = WifiMonitor.TDI_USE_SAE_PK;
8676         boolean shouldUpdate = false;
8677         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8678     }
8679 
8680     /**
8681      * Verify that the Transition Disable event is routed correctly.
8682      */
8683     @Test
testUpdateOweOnlyTransitionDisableIndicationFromOpenOweBss()8684     public void testUpdateOweOnlyTransitionDisableIndicationFromOpenOweBss() throws Exception {
8685         String caps = "[OWE_TRANSITION]";
8686         int indication = WifiMonitor.TDI_USE_ENHANCED_OPEN;
8687         boolean shouldUpdate = true;
8688         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8689     }
8690 
8691     /**
8692      * Verify that the Transition Disable event is routed correctly.
8693      */
8694     @Test
testUpdateOweOnlyTransitionDisableIndicationFromOweBss()8695     public void testUpdateOweOnlyTransitionDisableIndicationFromOweBss() throws Exception {
8696         String caps = "[OWE]";
8697         int indication = WifiMonitor.TDI_USE_ENHANCED_OPEN;
8698         boolean shouldUpdate = true;
8699         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8700     }
8701 
8702     /**
8703      * Verify that the Transition Disable event is routed correctly.
8704      */
8705     @Test
testDropOweOnlyTransitionDisableIndicationFromOpenBss()8706     public void testDropOweOnlyTransitionDisableIndicationFromOpenBss() throws Exception {
8707         String caps = "";
8708         int indication = WifiMonitor.TDI_USE_ENHANCED_OPEN;
8709         boolean shouldUpdate = false;
8710         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8711     }
8712 
8713     /**
8714      * Verify that the Transition Disable event is routed correctly.
8715      */
8716     @Test
testUpdateWpa3EnterpriseTransitionDisableIndicationFromTransitionBss()8717     public void testUpdateWpa3EnterpriseTransitionDisableIndicationFromTransitionBss()
8718             throws Exception {
8719         String caps = "[EAP/SHA1-EAP/SHA256][RSN][MFPC]";
8720         int indication = WifiMonitor.TDI_USE_WPA3_ENTERPRISE;
8721         boolean shouldUpdate = true;
8722         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8723     }
8724 
8725     /**
8726      * Verify that the Transition Disable event is routed correctly.
8727      */
8728     @Test
testUpdateWpa3EnterpriseTransitionDisableIndicationFromWpa3EnterpriseBss()8729     public void testUpdateWpa3EnterpriseTransitionDisableIndicationFromWpa3EnterpriseBss()
8730             throws Exception {
8731         String caps = "[EAP/SHA256][RSN][MFPC][MFPR]";
8732         int indication = WifiMonitor.TDI_USE_WPA3_ENTERPRISE;
8733         boolean shouldUpdate = true;
8734         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8735     }
8736 
8737     /**
8738      * Verify that the Transition Disable event is routed correctly.
8739      */
8740     @Test
testDropWpa3EnterpriseTransitionDisableIndicationFromWpa2EnterpriseBss()8741     public void testDropWpa3EnterpriseTransitionDisableIndicationFromWpa2EnterpriseBss()
8742             throws Exception {
8743         String caps = "[EAP/SHA1]";
8744         int indication = WifiMonitor.TDI_USE_WPA3_ENTERPRISE;
8745         boolean shouldUpdate = false;
8746         verifyTransitionDisableEvent(caps, indication, shouldUpdate);
8747     }
8748 
8749     /**
8750      * Verify that the network selection status will be updated with DISABLED_NETWORK_NOT_FOUND
8751      * when number of NETWORK_NOT_FOUND_EVENT event reaches the threshold.
8752      */
8753     @Test
testNetworkNotFoundEventUpdatesAssociationFailureStatus()8754     public void testNetworkNotFoundEventUpdatesAssociationFailureStatus()
8755             throws Exception {
8756         assumeTrue(SdkLevel.isAtLeastS());
8757         initializeAndAddNetworkAndVerifySuccess();
8758         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, 0, 0, TEST_BSSID_STR);
8759         for (int i = 0; i < mWifiGlobals.getNetworkNotFoundEventThreshold(); i++) {
8760             mCmi.sendMessage(WifiMonitor.NETWORK_NOT_FOUND_EVENT, DEFAULT_TEST_SSID);
8761         }
8762         mLooper.dispatchAll();
8763         verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
8764                 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_NETWORK_NOT_FOUND));
8765         verify(mWifiConfigManager).setRecentFailureAssociationStatus(anyInt(),
8766                 eq(WifiConfiguration.RECENT_FAILURE_NETWORK_NOT_FOUND));
8767 
8768         verify(mWifiDiagnostics).reportConnectionEvent(
8769                 eq(WifiDiagnostics.CONNECTION_EVENT_FAILED), any());
8770         verify(mWifiConnectivityManager).handleConnectionAttemptEnded(
8771                 mClientModeManager,
8772                 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_NOT_FOUND,
8773                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, TEST_BSSID_STR,
8774                 mTestConfig);
8775         verify(mWifiNetworkFactory).handleConnectionAttemptEnded(
8776                 eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_NOT_FOUND),
8777                 eq(mTestConfig), eq(TEST_BSSID_STR),
8778                 eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN));
8779         verify(mWifiNetworkSuggestionsManager).handleConnectionAttemptEnded(
8780                 eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_NOT_FOUND),
8781                 eq(mTestConfig), eq(null));
8782         verify(mWifiMetrics, never())
8783                 .incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
8784         verifyConnectionEventTimeoutDoesNotOccur();
8785 
8786         clearInvocations(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
8787                 mWifiNetworkSuggestionsManager);
8788 
8789         // Now trigger a disconnect event from supplicant, this should be ignored since the
8790         // connection tracking should have already ended.
8791         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT,
8792                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false));
8793         mLooper.dispatchAll();
8794 
8795         verifyNoMoreInteractions(mWifiDiagnostics, mWifiConfigManager, mWifiNetworkFactory,
8796                 mWifiNetworkSuggestionsManager);
8797     }
8798 
8799     /**
8800      * Verify that the subscriberId will be filled in NetworkAgentConfig
8801      * after connecting to a merged network. And also VCN policy will be checked.
8802      */
8803     @Test
triggerConnectToMergedNetwork()8804     public void triggerConnectToMergedNetwork() throws Exception {
8805         assumeTrue(SdkLevel.isAtLeastS());
8806         VcnManager vcnManager = mock(VcnManager.class);
8807         VcnNetworkPolicyResult vcnUnderlyingNetworkPolicy = mock(VcnNetworkPolicyResult.class);
8808         when(mContext.getSystemService(VcnManager.class)).thenReturn(vcnManager);
8809         ArgumentCaptor<VcnManager.VcnNetworkPolicyChangeListener> policyChangeListenerCaptor =
8810                 ArgumentCaptor.forClass(VcnManager.VcnNetworkPolicyChangeListener.class);
8811         InOrder inOrder = inOrder(vcnManager, vcnUnderlyingNetworkPolicy);
8812         doAnswer(new AnswerWithArguments() {
8813             public VcnNetworkPolicyResult answer(NetworkCapabilities networkCapabilities,
8814                     LinkProperties linkProperties) throws Exception {
8815                 networkCapabilities.removeCapability(
8816                         NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
8817                 when(vcnUnderlyingNetworkPolicy.getNetworkCapabilities())
8818                         .thenReturn(networkCapabilities);
8819                 return vcnUnderlyingNetworkPolicy;
8820             }
8821         }).when(vcnManager).applyVcnNetworkPolicy(any(), any());
8822         when(vcnUnderlyingNetworkPolicy.isTeardownRequested()).thenReturn(false);
8823 
8824         String testSubscriberId = "TestSubscriberId";
8825         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
8826         when(mDataTelephonyManager.getSubscriberId()).thenReturn(testSubscriberId);
8827         mConnectedNetwork.carrierMerged = true;
8828         mConnectedNetwork.subscriptionId = DATA_SUBID;
8829         connect();
8830         expectRegisterNetworkAgent((agentConfig) -> {
8831             assertEquals(testSubscriberId, agentConfig.subscriberId);
8832         }, (cap) -> {
8833                 assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED));
8834                 assertEquals(Collections.singleton(DATA_SUBID), cap.getSubscriptionIds());
8835             });
8836         // Verify VCN policy listener is registered
8837         inOrder.verify(vcnManager).addVcnNetworkPolicyChangeListener(any(),
8838                     policyChangeListenerCaptor.capture());
8839         assertNotNull(policyChangeListenerCaptor.getValue());
8840 
8841         // Verify getting new capability from VcnManager
8842         inOrder.verify(vcnManager).applyVcnNetworkPolicy(any(NetworkCapabilities.class),
8843                 any(LinkProperties.class));
8844         inOrder.verify(vcnUnderlyingNetworkPolicy).isTeardownRequested();
8845         inOrder.verify(vcnUnderlyingNetworkPolicy).getNetworkCapabilities();
8846 
8847         // Update policy with tear down request.
8848         when(vcnUnderlyingNetworkPolicy.isTeardownRequested()).thenReturn(true);
8849         policyChangeListenerCaptor.getValue().onPolicyChanged();
8850         mLooper.dispatchAll();
8851 
8852         // The merged carrier network should be disconnected.
8853         inOrder.verify(vcnManager).applyVcnNetworkPolicy(any(NetworkCapabilities.class),
8854                 any(LinkProperties.class));
8855         inOrder.verify(vcnUnderlyingNetworkPolicy).isTeardownRequested();
8856         inOrder.verify(vcnUnderlyingNetworkPolicy).getNetworkCapabilities();
8857         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
8858         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
8859                 eq(StaEvent.DISCONNECT_VCN_REQUEST));
8860         DisconnectEventInfo disconnectEventInfo =
8861                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
8862         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
8863         mLooper.dispatchAll();
8864         assertEquals("DisconnectedState", getCurrentState().getName());
8865 
8866         // In DisconnectedState, policy update should result no capability update.
8867         reset(mWifiConfigManager, vcnManager);
8868         policyChangeListenerCaptor.getValue().onPolicyChanged();
8869         verifyNoMoreInteractions(mWifiConfigManager, vcnManager);
8870     }
8871 
8872     /**
8873      * Verify when connect to a unmerged network, will not mark it as a VCN network.
8874      */
8875     @Test
triggerConnectToUnmergedNetwork()8876     public void triggerConnectToUnmergedNetwork() throws Exception {
8877         assumeTrue(SdkLevel.isAtLeastS());
8878         VcnManager vcnManager = mock(VcnManager.class);
8879         when(mContext.getSystemService(VcnManager.class)).thenReturn(vcnManager);
8880         VcnNetworkPolicyResult vcnUnderlyingNetworkPolicy = mock(VcnNetworkPolicyResult.class);
8881         ArgumentCaptor<VcnManager.VcnNetworkPolicyChangeListener> policyChangeListenerCaptor =
8882                 ArgumentCaptor.forClass(VcnManager.VcnNetworkPolicyChangeListener.class);
8883         doAnswer(new AnswerWithArguments() {
8884             public VcnNetworkPolicyResult answer(NetworkCapabilities networkCapabilities,
8885                     LinkProperties linkProperties) throws Exception {
8886                 networkCapabilities.removeCapability(
8887                         NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
8888                 when(vcnUnderlyingNetworkPolicy.getNetworkCapabilities())
8889                         .thenReturn(networkCapabilities);
8890                 return vcnUnderlyingNetworkPolicy;
8891             }
8892         }).when(vcnManager).applyVcnNetworkPolicy(any(), any());
8893         when(vcnUnderlyingNetworkPolicy.isTeardownRequested()).thenReturn(false);
8894 
8895         String testSubscriberId = "TestSubscriberId";
8896         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager);
8897         when(mDataTelephonyManager.getSubscriberId()).thenReturn(testSubscriberId);
8898         connect();
8899         expectRegisterNetworkAgent((agentConfig) -> {
8900             assertEquals(null, agentConfig.subscriberId);
8901         }, (cap) -> {
8902                 assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED));
8903                 assertTrue(cap.getSubscriptionIds().isEmpty());
8904             });
8905 
8906         // Verify VCN policy listener is registered
8907         verify(vcnManager).addVcnNetworkPolicyChangeListener(any(),
8908                 policyChangeListenerCaptor.capture());
8909         assertNotNull(policyChangeListenerCaptor.getValue());
8910 
8911         policyChangeListenerCaptor.getValue().onPolicyChanged();
8912         mLooper.dispatchAll();
8913 
8914         verifyNoMoreInteractions(vcnManager, vcnUnderlyingNetworkPolicy);
8915     }
8916 
8917     /**
8918      * Verifies that we trigger a disconnect when the {@link WifiConfigManager}.
8919      * OnNetworkUpdateListener#onNetworkRemoved(WifiConfiguration)} is invoked.
8920      */
8921     @Test
testOnCarrierOffloadDisabled()8922     public void testOnCarrierOffloadDisabled() throws Exception {
8923         mConnectedNetwork.subscriptionId = DATA_SUBID;
8924         connect();
8925 
8926         mOffloadDisabledListenerArgumentCaptor.getValue()
8927                 .onCarrierOffloadDisabled(DATA_SUBID, false);
8928         mLooper.dispatchAll();
8929 
8930         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
8931         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
8932                 eq(StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED));
8933         verify(mWifiConnectivityManager).clearCachedCandidates();
8934     }
8935 
8936     @Test
testPacketFilter()8937     public void testPacketFilter() throws Exception {
8938         connect();
8939 
8940         verify(mIpClient).startProvisioning(mProvisioningConfigurationCaptor.capture());
8941         assertEquals(APF_CAP, mProvisioningConfigurationCaptor.getValue().apfCapabilities);
8942 
8943         byte[] filter = new byte[20];
8944         new Random().nextBytes(filter);
8945         mIpClientCallback.installPacketFilter(filter);
8946         mLooper.dispatchAll();
8947 
8948         verify(mWifiNative).installPacketFilter(WIFI_IFACE_NAME, filter);
8949 
8950         when(mWifiNative.readPacketFilter(WIFI_IFACE_NAME)).thenReturn(filter);
8951         mIpClientCallback.startReadPacketFilter();
8952         mLooper.dispatchAll();
8953         verify(mIpClient).readPacketFilterComplete(filter);
8954         verify(mWifiNative).readPacketFilter(WIFI_IFACE_NAME);
8955     }
8956 
8957     @Test
testPacketFilterOnSecondarySupported()8958     public void testPacketFilterOnSecondarySupported() throws Exception {
8959         mResources.setBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta, true);
8960         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
8961         connect();
8962 
8963         verify(mIpClient).startProvisioning(mProvisioningConfigurationCaptor.capture());
8964         assertEquals(APF_CAP, mProvisioningConfigurationCaptor.getValue().apfCapabilities);
8965     }
8966 
8967     @Test
testPacketFilterOnSecondaryNotSupported()8968     public void testPacketFilterOnSecondaryNotSupported() throws Exception {
8969         mResources.setBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta, false);
8970         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
8971         connect();
8972 
8973         verify(mIpClient).startProvisioning(mProvisioningConfigurationCaptor.capture());
8974         assertNull(mProvisioningConfigurationCaptor.getValue().apfCapabilities);
8975     }
8976 
8977     @Test
testPacketFilterOnRoleChangeOnSecondaryCmm()8978     public void testPacketFilterOnRoleChangeOnSecondaryCmm() throws Exception {
8979         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
8980         connect();
8981 
8982         verify(mWifiScoreReport).onRoleChanged(ROLE_CLIENT_PRIMARY);
8983 
8984         byte[] filter = new byte[20];
8985         new Random().nextBytes(filter);
8986         mIpClientCallback.installPacketFilter(filter);
8987         mLooper.dispatchAll();
8988 
8989         // packet filter will not be installed if the secondary STA doesn't support APF.
8990         verify(mWifiNative, never()).installPacketFilter(WIFI_IFACE_NAME, filter);
8991 
8992         mIpClientCallback.startReadPacketFilter();
8993         mLooper.dispatchAll();
8994         // Return null as packet filter is not installed.
8995         verify(mIpClient).readPacketFilterComplete(eq(null));
8996         verify(mWifiNative, never()).readPacketFilter(WIFI_IFACE_NAME);
8997 
8998         // Now invoke role change, that should apply the APF
8999         when(mWifiNative.readPacketFilter(WIFI_IFACE_NAME)).thenReturn(filter);
9000         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
9001         mCmi.onRoleChanged();
9002         mIpClientCallback.installPacketFilter(filter);
9003         mLooper.dispatchAll();
9004         verify(mWifiScoreReport, times(2)).onRoleChanged(ROLE_CLIENT_PRIMARY);
9005         // verify that the APF capabilities are updated in IpClient.
9006         verify(mWifiNative, times(1)).getApfCapabilities(WIFI_IFACE_NAME);
9007         verify(mIpClient, times(1)).updateApfCapabilities(eq(APF_CAP));
9008         verify(mWifiNative, times(1)).installPacketFilter(WIFI_IFACE_NAME, filter);
9009     }
9010 
9011     @Test
testPacketFilterOnRoleChangeOnSecondaryCmmWithSupportForNonPrimaryApf()9012     public void testPacketFilterOnRoleChangeOnSecondaryCmmWithSupportForNonPrimaryApf()
9013             throws Exception {
9014         mResources.setBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta, true);
9015         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
9016         connect();
9017 
9018         byte[] filter = new byte[20];
9019         new Random().nextBytes(filter);
9020         mIpClientCallback.installPacketFilter(filter);
9021         mLooper.dispatchAll();
9022 
9023         // apply the data.
9024         verify(mWifiNative).installPacketFilter(WIFI_IFACE_NAME, filter);
9025 
9026         when(mWifiNative.readPacketFilter(WIFI_IFACE_NAME)).thenReturn(filter);
9027         mIpClientCallback.startReadPacketFilter();
9028         mLooper.dispatchAll();
9029         verify(mIpClient).readPacketFilterComplete(filter);
9030         // return the applied data.
9031         verify(mWifiNative).readPacketFilter(WIFI_IFACE_NAME);
9032 
9033         // Now invoke role change, that should not apply the APF
9034         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
9035         mCmi.onRoleChanged();
9036         // ignore (since it was already applied)
9037         verify(mIpClient, never()).updateApfCapabilities(eq(APF_CAP));
9038         verify(mWifiNative, times(1)).installPacketFilter(WIFI_IFACE_NAME, filter);
9039     }
9040 
9041     @Test
testSetMaxDtimMultiplier_IPv4OnlyNetwork()9042     public void testSetMaxDtimMultiplier_IPv4OnlyNetwork() throws Exception {
9043         connect();
9044 
9045         mIpClientCallback.setMaxDtimMultiplier(TEST_IPV4_ONLY_NETWORK_MAX_DTIM_MULTIPLIER);
9046         mLooper.dispatchAll();
9047 
9048         verify(mWifiNative).setDtimMultiplier(WIFI_IFACE_NAME,
9049                 TEST_IPV4_ONLY_NETWORK_MAX_DTIM_MULTIPLIER);
9050     }
9051 
9052     @Test
testSetMaxDtimMultiplier_IPv6OnlyNetwork()9053     public void testSetMaxDtimMultiplier_IPv6OnlyNetwork() throws Exception {
9054         connect();
9055 
9056         mIpClientCallback.setMaxDtimMultiplier(TEST_IPV6_ONLY_NETWORK_MAX_DTIM_MULTIPLIER);
9057         mLooper.dispatchAll();
9058 
9059         verify(mWifiNative).setDtimMultiplier(WIFI_IFACE_NAME,
9060                 TEST_IPV6_ONLY_NETWORK_MAX_DTIM_MULTIPLIER);
9061     }
9062 
runSetMaxDtimMultiplierInDualStackTest()9063     private void runSetMaxDtimMultiplierInDualStackTest() throws Exception {
9064         connect();
9065 
9066         mIpClientCallback.setMaxDtimMultiplier(TEST_DUAL_STACK_NETWORK_MAX_DTIM_MULTIPLIER);
9067         mLooper.dispatchAll();
9068 
9069         verify(mWifiNative).setDtimMultiplier(WIFI_IFACE_NAME,
9070                 TEST_DUAL_STACK_NETWORK_MAX_DTIM_MULTIPLIER);
9071     }
9072 
9073     @Test
testSetMaxDtimMultiplier_DualStackNetwork()9074     public void testSetMaxDtimMultiplier_DualStackNetwork() throws Exception {
9075         runSetMaxDtimMultiplierInDualStackTest();
9076     }
9077 
9078     @Test
testSetMaxDtimMultiplier_EnableMulticastLock()9079     public void testSetMaxDtimMultiplier_EnableMulticastLock() throws Exception {
9080         runSetMaxDtimMultiplierInDualStackTest();
9081         reset(mIpClient);
9082 
9083         // simulate the multicast lock is held.
9084         WifiMulticastLockManager.FilterController filterController =
9085                 mCmi.getMcastLockManagerFilterController();
9086         filterController.startFilteringMulticastPackets();
9087         verify(mIpClient).setMulticastFilter(eq(true));
9088 
9089         reset(mWifiNative);
9090 
9091         mIpClientCallback.setMaxDtimMultiplier(TEST_MULTICAST_LOCK_MAX_DTIM_MULTIPLIER);
9092         mLooper.dispatchAll();
9093 
9094         verify(mWifiNative).setDtimMultiplier(WIFI_IFACE_NAME,
9095                 TEST_MULTICAST_LOCK_MAX_DTIM_MULTIPLIER);
9096     }
9097 
9098     @Test
testWifiInfoUpdateOnRoleChange()9099     public void testWifiInfoUpdateOnRoleChange() throws Exception {
9100         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
9101         connect();
9102         // Should not set WifiInfo.isPrimary
9103         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
9104             if (SdkLevel.isAtLeastS()) {
9105                 WifiInfo wifiInfoFromTi = (WifiInfo) cap.getTransportInfo();
9106                 assertFalse(wifiInfoFromTi.isPrimary());
9107             }
9108         });
9109         reset(mWifiNetworkAgent);
9110 
9111         // Now invoke role change, that should set WifiInfo.isPrimary
9112         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
9113         mCmi.onRoleChanged();
9114         expectNetworkAgentUpdateCapabilities((cap) -> {
9115             if (SdkLevel.isAtLeastS()) {
9116                 WifiInfo wifiInfoFromTi = (WifiInfo) cap.getTransportInfo();
9117                 assertTrue(wifiInfoFromTi.isPrimary());
9118             }
9119         });
9120     }
9121 
9122     /**
9123      * Verify onCellularConnectivityChanged plumbs the information to the right locations.
9124      */
9125     @Test
testOnCellularConnectivityChanged()9126     public void testOnCellularConnectivityChanged() {
9127         mCmi.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_AVAILABLE);
9128         verify(mWifiConfigManager).onCellularConnectivityChanged(
9129                 WifiDataStall.CELLULAR_DATA_AVAILABLE);
9130 
9131         mCmi.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE);
9132         verify(mWifiConfigManager).onCellularConnectivityChanged(
9133                 WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE);
9134     }
9135 
9136     /**
9137      * Verify that when cellular data is lost and wifi is not connected, we force a connectivity
9138      * scan.
9139      */
9140     @Test
testOnCellularConnectivityChangedForceConnectivityScan()9141     public void testOnCellularConnectivityChangedForceConnectivityScan() throws Exception {
9142         mResources.setBoolean(R.bool.config_wifiScanOnCellularDataLossEnabled, true);
9143         // verify a connectivity scan is forced since wifi is not connected
9144         mCmi.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE);
9145         verify(mWifiConnectivityManager).forceConnectivityScan(WIFI_WORK_SOURCE);
9146 
9147         // verify that after wifi is connected, loss of cellular data will not trigger scans.
9148         connect();
9149         mCmi.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE);
9150         verify(mWifiConnectivityManager).forceConnectivityScan(WIFI_WORK_SOURCE);
9151     }
9152 
setScreenState(boolean screenOn)9153     private void setScreenState(boolean screenOn) {
9154         WifiDeviceStateChangeManager.StateChangeCallback callback =
9155                 mStateChangeCallbackArgumentCaptor.getValue();
9156         assertNotNull(callback);
9157         callback.onScreenStateChanged(screenOn);
9158     }
9159 
9160     @Test
verifyRssiPollOnScreenStateChange()9161     public void verifyRssiPollOnScreenStateChange() throws Exception {
9162         setScreenState(true);
9163         connect();
9164         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9165 
9166         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
9167                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
9168         WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
9169         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
9170         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9171         mLooper.dispatchAll();
9172         verify(mWifiNative).getWifiLinkLayerStats(WIFI_IFACE_NAME);
9173         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
9174                 mConnectionCapabilities, null, oldLLStats, mWifiInfo, TEST_TX_BYTES, TEST_RX_BYTES);
9175         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, oldLLStats);
9176 
9177         WifiLinkLayerStats newLLStats = new WifiLinkLayerStats();
9178         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(newLLStats);
9179         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9180         mLooper.dispatchAll();
9181         verify(mWifiNative, times(2)).getWifiLinkLayerStats(WIFI_IFACE_NAME);
9182 
9183         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
9184                 mConnectionCapabilities, oldLLStats, newLLStats, mWifiInfo, TEST_TX_BYTES,
9185                 TEST_RX_BYTES);
9186         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, newLLStats);
9187 
9188         // Now set the screen state to false & move time forward, ensure no more link layer stats
9189         // collection.
9190         setScreenState(false);
9191         mLooper.dispatchAll();
9192         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9193 
9194         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9195         mLooper.dispatchAll();
9196 
9197         verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
9198     }
9199 
9200     @Test
verifyRssiPollOnSecondaryCmm()9201     public void verifyRssiPollOnSecondaryCmm() throws Exception {
9202         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
9203         mCmi.onRoleChanged();
9204         setScreenState(true);
9205         connect();
9206         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9207 
9208         verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
9209 
9210         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
9211                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
9212         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats());
9213 
9214         // No link layer stats collection on secondary CMM.
9215         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9216         mLooper.dispatchAll();
9217 
9218         verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
9219     }
9220 
9221     @Test
verifyRssiPollOnOnRoleChangeToPrimary()9222     public void verifyRssiPollOnOnRoleChangeToPrimary() throws Exception {
9223         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
9224         mCmi.onRoleChanged();
9225         setScreenState(true);
9226         connect();
9227         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9228 
9229         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
9230                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
9231         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats());
9232 
9233         // No link layer stats collection on secondary CMM.
9234         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9235         mLooper.dispatchAll();
9236 
9237         verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
9238 
9239         // Now invoke role change, that should start rssi polling on the new primary.
9240         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY);
9241         mCmi.onRoleChanged();
9242         mLooper.dispatchAll();
9243         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9244 
9245         WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
9246         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
9247         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9248         mLooper.dispatchAll();
9249         verify(mWifiNative).getWifiLinkLayerStats(WIFI_IFACE_NAME);
9250         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
9251                 mConnectionCapabilities, null, oldLLStats, mWifiInfo, TEST_TX_BYTES, TEST_RX_BYTES);
9252         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, oldLLStats);
9253     }
9254 
9255     @Test
verifyRssiPollOnOnRoleChangeToSecondary()9256     public void verifyRssiPollOnOnRoleChangeToSecondary() throws Exception {
9257         setScreenState(true);
9258         connect();
9259         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9260 
9261         // RSSI polling is enabled on primary.
9262         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
9263                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
9264         WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats();
9265         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats);
9266         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9267         mLooper.dispatchAll();
9268         verify(mWifiNative).getWifiLinkLayerStats(WIFI_IFACE_NAME);
9269         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
9270                 mConnectionCapabilities, null, oldLLStats, mWifiInfo, TEST_TX_BYTES, TEST_RX_BYTES);
9271         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, oldLLStats);
9272 
9273         // Now invoke role change, that should stop rssi polling on the secondary.
9274         when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT);
9275         mCmi.onRoleChanged();
9276         mLooper.dispatchAll();
9277         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9278 
9279         // No link layer stats collection on secondary CMM.
9280         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9281         mLooper.dispatchAll();
9282 
9283         verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall);
9284     }
9285 
9286     @Test
verifyRssiPollWhenLinkLayerStatsIsNotSupported()9287     public void verifyRssiPollWhenLinkLayerStatsIsNotSupported() throws Exception {
9288         setScreenState(true);
9289         connect();
9290         clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall);
9291 
9292         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet());
9293         WifiLinkLayerStats stats = new WifiLinkLayerStats();
9294         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats);
9295         mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis());
9296         mLooper.dispatchAll();
9297         verify(mWifiNative, never()).getWifiLinkLayerStats(any());
9298         verify(mWifiDataStall).checkDataStallAndThroughputSufficiency(WIFI_IFACE_NAME,
9299                 mConnectionCapabilities, null, null, mWifiInfo, TEST_TX_BYTES, TEST_RX_BYTES);
9300         verify(mWifiMetrics).incrementWifiLinkLayerUsageStats(WIFI_IFACE_NAME, null);
9301     }
9302 
9303     @Test
testClientModeImplWhenIpClientIsNotReady()9304     public void testClientModeImplWhenIpClientIsNotReady() throws Exception {
9305         WifiConfiguration config = mConnectedNetwork;
9306         config.networkId = FRAMEWORK_NETWORK_ID;
9307         config.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
9308         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
9309         config.getNetworkSelectionStatus().setHasEverConnected(mTestNetworkParams.hasEverConnected);
9310         assertNull(config.getNetworkSelectionStatus().getCandidateSecurityParams());
9311 
9312         mFrameworkFacade = mock(FrameworkFacade.class);
9313         ArgumentCaptor<IpClientCallbacks> captor = ArgumentCaptor.forClass(IpClientCallbacks.class);
9314         // reset mWifiNative since initializeCmi() was called in setup()
9315         resetWifiNative();
9316 
9317         // reinitialize ClientModeImpl with IpClient is not ready.
9318         initializeCmi();
9319         verify(mFrameworkFacade).makeIpClient(any(), anyString(), captor.capture());
9320 
9321         // Manually connect should fail.
9322         IActionListener connectActionListener = mock(IActionListener.class);
9323         mCmi.connectNetwork(
9324                 new NetworkUpdateResult(config.networkId),
9325                 new ActionListenerWrapper(connectActionListener),
9326                 Binder.getCallingUid(), OP_PACKAGE_NAME, null);
9327         mLooper.dispatchAll();
9328         verify(connectActionListener).onFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR);
9329         verify(mWifiConfigManager, never())
9330                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
9331         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
9332 
9333         // Auto connect should also fail
9334         mCmi.startConnectToNetwork(config.networkId, MANAGED_PROFILE_UID, config.BSSID);
9335         mLooper.dispatchAll();
9336         verify(mWifiConfigManager, never())
9337                 .getConfiguredNetworkWithoutMasking(eq(config.networkId));
9338         verify(mWifiNative, never()).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
9339 
9340         // Make IpClient ready connection should succeed.
9341         captor.getValue().onIpClientCreated(mIpClient);
9342         mLooper.dispatchAll();
9343 
9344         triggerConnect();
9345     }
9346 
testNetworkRemovedUpdatesLinkedNetworks(boolean isSecondary)9347     private void testNetworkRemovedUpdatesLinkedNetworks(boolean isSecondary) throws Exception {
9348         if (isSecondary) {
9349             when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED);
9350         }
9351         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9352         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9353         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9354         WifiConfiguration removeConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid2\"");
9355         removeConfig.networkId = FRAMEWORK_NETWORK_ID + 1;
9356         connectedConfig.linkedConfigurations = new HashMap<>();
9357         connectedConfig.linkedConfigurations.put(removeConfig.getProfileKey(), 1);
9358         removeConfig.linkedConfigurations = new HashMap<>();
9359         removeConfig.linkedConfigurations.put(connectedConfig.getProfileKey(), 1);
9360         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9361                 .thenReturn(connectedConfig);
9362         when(mWifiConfigManager.getConfiguredNetwork(removeConfig.networkId))
9363                 .thenReturn(removeConfig);
9364         mConnectedNetwork = connectedConfig;
9365         connect();
9366 
9367         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9368                 SecurityParams.createSecurityParamsBySecurityType(
9369                         WifiConfiguration.SECURITY_TYPE_PSK));
9370         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
9371                 .getAllValues()) {
9372             listener.onNetworkRemoved(removeConfig);
9373         }
9374         mLooper.dispatchAll();
9375 
9376         if (!isSecondary) {
9377             verify(mWifiConfigManager).updateLinkedNetworks(connectedConfig.networkId);
9378         } else {
9379             verify(mWifiConfigManager, never()).updateLinkedNetworks(connectedConfig.networkId);
9380         }
9381     }
9382 
9383     @Test
testNetworkRemovedUpdatesLinkedNetworksPrimary()9384     public void testNetworkRemovedUpdatesLinkedNetworksPrimary() throws Exception {
9385         testNetworkRemovedUpdatesLinkedNetworks(false);
9386     }
9387 
9388     @Test
testNetworkRemovedUpdatesLinkedNetworksSecondary()9389     public void testNetworkRemovedUpdatesLinkedNetworksSecondary() throws Exception {
9390         testNetworkRemovedUpdatesLinkedNetworks(true);
9391     }
9392 
9393     @Test
testConnectClearsAllowlistSsids()9394     public void testConnectClearsAllowlistSsids() throws Exception {
9395         connect();
9396         verify(mWifiBlocklistMonitor)
9397                 .setAllowlistSsids(eq(mConnectedNetwork.SSID), eq(Collections.emptyList()));
9398     }
9399 
9400     @Test
testNetworkUpdatedUpdatesLinkedNetworks()9401     public void testNetworkUpdatedUpdatesLinkedNetworks() throws Exception {
9402         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9403         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9404         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9405         WifiConfiguration updatedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid2\"");
9406         updatedConfig.networkId = FRAMEWORK_NETWORK_ID + 1;
9407         connectedConfig.linkedConfigurations = new HashMap<>();
9408         connectedConfig.linkedConfigurations.put(updatedConfig.getProfileKey(), 1);
9409         updatedConfig.linkedConfigurations = new HashMap<>();
9410         updatedConfig.linkedConfigurations.put(connectedConfig.getProfileKey(), 1);
9411         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9412                 .thenReturn(connectedConfig);
9413         when(mWifiConfigManager.getConfiguredNetwork(updatedConfig.networkId))
9414                 .thenReturn(updatedConfig);
9415         mConnectedNetwork = connectedConfig;
9416         connect();
9417 
9418         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9419                 SecurityParams.createSecurityParamsBySecurityType(
9420                         WifiConfiguration.SECURITY_TYPE_PSK));
9421         IActionListener connectActionListener = mock(IActionListener.class);
9422         mCmi.saveNetwork(
9423                 new NetworkUpdateResult(
9424                         updatedConfig.networkId, STATUS_SUCCESS, false, false, true, false),
9425                 new ActionListenerWrapper(connectActionListener),
9426                 Binder.getCallingUid(), OP_PACKAGE_NAME);
9427         mLooper.dispatchAll();
9428 
9429         verify(mWifiConfigManager).updateLinkedNetworks(connectedConfig.networkId);
9430     }
9431 
9432     @Test
testNetworkValidationUpdatesLinkedNetworks()9433     public void testNetworkValidationUpdatesLinkedNetworks() throws Exception {
9434         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9435         BufferedReader reader = mock(BufferedReader.class);
9436         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9437         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9438         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9439                 .thenReturn(connectedConfig);
9440         mConnectedNetwork = connectedConfig;
9441         connect();
9442         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
9443                 mWifiNetworkAgentCallbackCaptor.capture());
9444         verify(mWifiBlocklistMonitor).setAllowlistSsids(
9445                 eq(connectedConfig.SSID), eq(Collections.emptyList()));
9446         verify(mWifiBlocklistMonitor).updateFirmwareRoamingConfiguration(
9447                 eq(Set.of(connectedConfig.SSID)));
9448 
9449         LinkProperties linkProperties = mock(LinkProperties.class);
9450         RouteInfo routeInfo = mock(RouteInfo.class);
9451         IpPrefix ipPrefix = mock(IpPrefix.class);
9452         Inet4Address destinationAddress = mock(Inet4Address.class);
9453         InetAddress gatewayAddress = mock(InetAddress.class);
9454         String hostAddress = "127.0.0.1";
9455         String gatewayMac = "192.168.0.1";
9456         when(linkProperties.getRoutes()).thenReturn(Arrays.asList(routeInfo));
9457         when(routeInfo.isDefaultRoute()).thenReturn(true);
9458         when(routeInfo.getDestination()).thenReturn(ipPrefix);
9459         when(ipPrefix.getAddress()).thenReturn(destinationAddress);
9460         when(routeInfo.hasGateway()).thenReturn(true);
9461         when(routeInfo.getGateway()).thenReturn(gatewayAddress);
9462         when(gatewayAddress.getHostAddress()).thenReturn(hostAddress);
9463         when(mWifiInjector.createBufferedReader(ARP_TABLE_PATH)).thenReturn(reader);
9464         when(reader.readLine()).thenReturn(new StringJoiner(" ")
9465                 .add(hostAddress)
9466                 .add("HWType")
9467                 .add("Flags")
9468                 .add(gatewayMac)
9469                 .add("Mask")
9470                 .add("Device")
9471                 .toString());
9472 
9473         mIpClientCallback.onLinkPropertiesChange(linkProperties);
9474         mLooper.dispatchAll();
9475         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9476                 SecurityParams.createSecurityParamsBySecurityType(
9477                         WifiConfiguration.SECURITY_TYPE_PSK));
9478         when(mWifiConfigManager.setNetworkDefaultGwMacAddress(anyInt(), any())).thenReturn(true);
9479         when(mWifiConfigManager.saveToStore()).thenReturn(true);
9480         WifiConfiguration linkedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid2\"");
9481         linkedConfig.networkId = connectedConfig.networkId + 1;
9482         Map<String, WifiConfiguration> linkedNetworks = new HashMap<>();
9483         linkedNetworks.put(linkedConfig.getProfileKey(), linkedConfig);
9484         when(mWifiConfigManager.getLinkedNetworksWithoutMasking(connectedConfig.networkId))
9485                 .thenReturn(linkedNetworks);
9486         when(mWifiNative.updateLinkedNetworks(any(), anyInt(), any())).thenReturn(true);
9487         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9488                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9489         mLooper.dispatchAll();
9490 
9491         verify(mWifiConfigManager)
9492                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9493         verify(mWifiConfigManager).updateLinkedNetworks(connectedConfig.networkId);
9494         verify(mWifiNative).updateLinkedNetworks(
9495                 any(), eq(connectedConfig.networkId), eq(linkedNetworks));
9496         List<String> allowlistSsids = new ArrayList<>();
9497         allowlistSsids.add(linkedConfig.SSID);
9498         allowlistSsids.add(connectedConfig.SSID);
9499         verify(mWifiBlocklistMonitor).setAllowlistSsids(
9500                 eq(connectedConfig.SSID), eq(allowlistSsids));
9501         verify(mWifiBlocklistMonitor).updateFirmwareRoamingConfiguration(
9502                 eq(new ArraySet<>(allowlistSsids)));
9503     }
9504 
9505     @Test
testNonPskNetworkDoesNotUpdateLinkedNetworks()9506     public void testNonPskNetworkDoesNotUpdateLinkedNetworks() throws Exception {
9507         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9508         BufferedReader reader = mock(BufferedReader.class);
9509         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9510         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9511         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9512                 .thenReturn(connectedConfig);
9513         mConnectedNetwork = connectedConfig;
9514         connect();
9515         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
9516                 mWifiNetworkAgentCallbackCaptor.capture());
9517 
9518         LinkProperties linkProperties = mock(LinkProperties.class);
9519         RouteInfo routeInfo = mock(RouteInfo.class);
9520         IpPrefix ipPrefix = mock(IpPrefix.class);
9521         Inet4Address destinationAddress = mock(Inet4Address.class);
9522         InetAddress gatewayAddress = mock(InetAddress.class);
9523         String hostAddress = "127.0.0.1";
9524         String gatewayMac = "192.168.0.1";
9525         when(linkProperties.getRoutes()).thenReturn(Arrays.asList(routeInfo));
9526         when(routeInfo.isDefaultRoute()).thenReturn(true);
9527         when(routeInfo.getDestination()).thenReturn(ipPrefix);
9528         when(ipPrefix.getAddress()).thenReturn(destinationAddress);
9529         when(routeInfo.hasGateway()).thenReturn(true);
9530         when(routeInfo.getGateway()).thenReturn(gatewayAddress);
9531         when(gatewayAddress.getHostAddress()).thenReturn(hostAddress);
9532         when(mWifiInjector.createBufferedReader(ARP_TABLE_PATH)).thenReturn(reader);
9533         when(reader.readLine()).thenReturn(new StringJoiner(" ")
9534                 .add(hostAddress)
9535                 .add("HWType")
9536                 .add("Flags")
9537                 .add(gatewayMac)
9538                 .add("Mask")
9539                 .add("Device")
9540                 .toString());
9541 
9542         mIpClientCallback.onLinkPropertiesChange(linkProperties);
9543         mLooper.dispatchAll();
9544         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9545                 SecurityParams.createSecurityParamsBySecurityType(
9546                         WifiConfiguration.SECURITY_TYPE_SAE));
9547         when(mWifiConfigManager.setNetworkDefaultGwMacAddress(anyInt(), any())).thenReturn(true);
9548         when(mWifiConfigManager.saveToStore()).thenReturn(true);
9549         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9550                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9551         mLooper.dispatchAll();
9552 
9553         verify(mWifiConfigManager)
9554                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9555         verify(mWifiConfigManager, never()).updateLinkedNetworks(connectedConfig.networkId);
9556     }
9557 
9558     @Test
testInvalidScanResultDoesNotUpdateLinkedNetworks()9559     public void testInvalidScanResultDoesNotUpdateLinkedNetworks() throws Exception {
9560         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9561         BufferedReader reader = mock(BufferedReader.class);
9562         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9563         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9564         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9565                 .thenReturn(connectedConfig);
9566         mConnectedNetwork = connectedConfig;
9567         connect();
9568         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
9569                 mWifiNetworkAgentCallbackCaptor.capture());
9570 
9571         LinkProperties linkProperties = mock(LinkProperties.class);
9572         RouteInfo routeInfo = mock(RouteInfo.class);
9573         IpPrefix ipPrefix = mock(IpPrefix.class);
9574         Inet4Address destinationAddress = mock(Inet4Address.class);
9575         InetAddress gatewayAddress = mock(InetAddress.class);
9576         String hostAddress = "127.0.0.1";
9577         String gatewayMac = "192.168.0.1";
9578         when(linkProperties.getRoutes()).thenReturn(Arrays.asList(routeInfo));
9579         when(routeInfo.isDefaultRoute()).thenReturn(true);
9580         when(routeInfo.getDestination()).thenReturn(ipPrefix);
9581         when(ipPrefix.getAddress()).thenReturn(destinationAddress);
9582         when(routeInfo.hasGateway()).thenReturn(true);
9583         when(routeInfo.getGateway()).thenReturn(gatewayAddress);
9584         when(gatewayAddress.getHostAddress()).thenReturn(hostAddress);
9585         when(mWifiInjector.createBufferedReader(ARP_TABLE_PATH)).thenReturn(reader);
9586         when(reader.readLine()).thenReturn(new StringJoiner(" ")
9587                 .add(hostAddress)
9588                 .add("HWType")
9589                 .add("Flags")
9590                 .add(gatewayMac)
9591                 .add("Mask")
9592                 .add("Device")
9593                 .toString());
9594 
9595         mIpClientCallback.onLinkPropertiesChange(linkProperties);
9596         mLooper.dispatchAll();
9597         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9598                 SecurityParams.createSecurityParamsBySecurityType(
9599                         WifiConfiguration.SECURITY_TYPE_PSK));
9600         when(mWifiConfigManager.setNetworkDefaultGwMacAddress(anyInt(), any())).thenReturn(true);
9601         when(mWifiConfigManager.saveToStore()).thenReturn(true);
9602 
9603         // FT/PSK scan, do not update linked networks
9604         ScanResult ftPskScan = new ScanResult();
9605         ftPskScan.capabilities = "FT/PSK";
9606         when(mScanDetailCache.getScanResult(any())).thenReturn(ftPskScan);
9607         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9608                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9609         mLooper.dispatchAll();
9610         verify(mWifiConfigManager)
9611                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9612         verify(mWifiConfigManager, never()).updateLinkedNetworks(connectedConfig.networkId);
9613 
9614         // FT/SAE scan, do not update linked networks
9615         ScanResult ftSaeScan = new ScanResult();
9616         ftSaeScan.capabilities = "FT/SAE";
9617         when(mScanRequestProxy.getScanResult(any())).thenReturn(ftSaeScan);
9618         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9619                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9620         mLooper.dispatchAll();
9621         verify(mWifiConfigManager)
9622                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9623         verify(mWifiConfigManager, never()).updateLinkedNetworks(connectedConfig.networkId);
9624 
9625         // Null scan, do not update linked networks
9626         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9627                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9628         mLooper.dispatchAll();
9629         verify(mWifiConfigManager)
9630                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9631         verify(mWifiConfigManager, never()).updateLinkedNetworks(connectedConfig.networkId);
9632     }
9633 
9634     @Test
testLinkedNetworksFiltersOutAutojoinDisabledNetworks()9635     public void testLinkedNetworksFiltersOutAutojoinDisabledNetworks() throws Exception {
9636         mResources.setBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming, true);
9637         BufferedReader reader = mock(BufferedReader.class);
9638         WifiConfiguration connectedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid1\"");
9639         connectedConfig.networkId = FRAMEWORK_NETWORK_ID;
9640         when(mWifiConfigManager.getConfiguredNetwork(connectedConfig.networkId))
9641                 .thenReturn(connectedConfig);
9642         mConnectedNetwork = connectedConfig;
9643         connect();
9644         verify(mWifiInjector).makeWifiNetworkAgent(any(), any(), any(), any(),
9645                 mWifiNetworkAgentCallbackCaptor.capture());
9646         verify(mWifiBlocklistMonitor).setAllowlistSsids(
9647                 eq(connectedConfig.SSID), eq(Collections.emptyList()));
9648         verify(mWifiBlocklistMonitor).updateFirmwareRoamingConfiguration(
9649                 eq(Set.of(connectedConfig.SSID)));
9650 
9651         LinkProperties linkProperties = mock(LinkProperties.class);
9652         RouteInfo routeInfo = mock(RouteInfo.class);
9653         IpPrefix ipPrefix = mock(IpPrefix.class);
9654         Inet4Address destinationAddress = mock(Inet4Address.class);
9655         InetAddress gatewayAddress = mock(InetAddress.class);
9656         String hostAddress = "127.0.0.1";
9657         String gatewayMac = "192.168.0.1";
9658         when(linkProperties.getRoutes()).thenReturn(Arrays.asList(routeInfo));
9659         when(routeInfo.isDefaultRoute()).thenReturn(true);
9660         when(routeInfo.getDestination()).thenReturn(ipPrefix);
9661         when(ipPrefix.getAddress()).thenReturn(destinationAddress);
9662         when(routeInfo.hasGateway()).thenReturn(true);
9663         when(routeInfo.getGateway()).thenReturn(gatewayAddress);
9664         when(gatewayAddress.getHostAddress()).thenReturn(hostAddress);
9665         when(mWifiInjector.createBufferedReader(ARP_TABLE_PATH)).thenReturn(reader);
9666         when(reader.readLine()).thenReturn(new StringJoiner(" ")
9667                 .add(hostAddress)
9668                 .add("HWType")
9669                 .add("Flags")
9670                 .add(gatewayMac)
9671                 .add("Mask")
9672                 .add("Device")
9673                 .toString());
9674 
9675         mIpClientCallback.onLinkPropertiesChange(linkProperties);
9676         mLooper.dispatchAll();
9677         when(mWifiNative.getCurrentNetworkSecurityParams(any())).thenReturn(
9678                 SecurityParams.createSecurityParamsBySecurityType(
9679                         WifiConfiguration.SECURITY_TYPE_PSK));
9680         when(mWifiConfigManager.setNetworkDefaultGwMacAddress(anyInt(), any())).thenReturn(true);
9681         when(mWifiConfigManager.saveToStore()).thenReturn(true);
9682         WifiConfiguration linkedConfig = WifiConfigurationTestUtil.createPskNetwork("\"ssid2\"");
9683         linkedConfig.networkId = connectedConfig.networkId + 1;
9684         linkedConfig.allowAutojoin = false;
9685         Map<String, WifiConfiguration> linkedNetworks = new HashMap<>();
9686         linkedNetworks.put(linkedConfig.getProfileKey(), linkedConfig);
9687         when(mWifiConfigManager.getLinkedNetworksWithoutMasking(connectedConfig.networkId))
9688                 .thenReturn(linkedNetworks);
9689         when(mWifiNative.updateLinkedNetworks(any(), anyInt(), any())).thenReturn(true);
9690         mWifiNetworkAgentCallbackCaptor.getValue().onValidationStatus(
9691                 NetworkAgent.VALIDATION_STATUS_VALID, null /* captivePortalUrl */);
9692         mLooper.dispatchAll();
9693 
9694         verify(mWifiConfigManager)
9695                 .setNetworkDefaultGwMacAddress(mConnectedNetwork.networkId, gatewayMac);
9696         verify(mWifiConfigManager).updateLinkedNetworks(connectedConfig.networkId);
9697         verify(mWifiNative).updateLinkedNetworks(
9698                 any(), eq(connectedConfig.networkId), eq(linkedNetworks));
9699         verify(mWifiBlocklistMonitor, times(2)).setAllowlistSsids(
9700                 eq(connectedConfig.SSID), eq(Collections.emptyList()));
9701         verify(mWifiBlocklistMonitor).updateFirmwareRoamingConfiguration(
9702                 eq(Collections.emptySet()));
9703     }
9704 
9705     /**
9706      * Verify that we disconnect when we mark a previous trusted network untrusted.
9707      */
9708     @Test
verifyDisconnectOnMarkingNetworkUntrusted()9709     public void verifyDisconnectOnMarkingNetworkUntrusted() throws Exception {
9710         assumeTrue(SdkLevel.isAtLeastT());
9711         connect();
9712         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
9713             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED));
9714         });
9715 
9716         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
9717         mConnectedNetwork.trusted = false;
9718 
9719         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
9720                 .getAllValues()) {
9721             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
9722         }
9723         mLooper.dispatchAll();
9724         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
9725         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
9726                 eq(StaEvent.DISCONNECT_NETWORK_UNTRUSTED));
9727     }
9728 
9729     /**
9730      * Verify that we only update capabilities when we mark a previous untrusted network trusted.
9731      */
9732     @Test
verifyUpdateCapabilitiesOnMarkingNetworkTrusted()9733     public void verifyUpdateCapabilitiesOnMarkingNetworkTrusted() throws Exception {
9734         assumeTrue(SdkLevel.isAtLeastT());
9735         mConnectedNetwork.trusted = false;
9736         connect();
9737         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
9738             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED));
9739         });
9740         reset(mWifiNetworkAgent);
9741 
9742         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
9743         mConnectedNetwork.trusted = true;
9744 
9745         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
9746                 .getAllValues()) {
9747             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
9748         }
9749         mLooper.dispatchAll();
9750         assertEquals("L3ConnectedState", getCurrentState().getName());
9751 
9752         expectNetworkAgentUpdateCapabilities((cap) -> {
9753             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED));
9754         });
9755     }
9756 
9757     /**
9758      * Verify on device before T we will not disconnect when we mark a previous trusted network
9759      * untrusted.
9760      */
9761     @Test
verifyNoDisconnectOnMarkingNetworkUntrustedBeforeT()9762     public void verifyNoDisconnectOnMarkingNetworkUntrustedBeforeT() throws Exception {
9763         assumeFalse(SdkLevel.isAtLeastT());
9764         connect();
9765         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
9766             assertTrue(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED));
9767         });
9768 
9769         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
9770         mConnectedNetwork.trusted = false;
9771 
9772         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
9773                 .getAllValues()) {
9774             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
9775         }
9776         mLooper.dispatchAll();
9777         verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
9778         verify(mWifiMetrics, never()).logStaEvent(anyString(), anyInt(), anyInt());
9779     }
9780 
9781     /**
9782      * Verify on a build before T we will not update capabilities or disconnect when we mark a
9783      * previous untrusted network trusted.
9784      */
9785     @Test
verifyNoUpdateCapabilitiesOnMarkingNetworkTrustedBeforeT()9786     public void verifyNoUpdateCapabilitiesOnMarkingNetworkTrustedBeforeT() throws Exception {
9787         assumeFalse(SdkLevel.isAtLeastT());
9788         mConnectedNetwork.trusted = false;
9789         connect();
9790         expectRegisterNetworkAgent((config) -> { }, (cap) -> {
9791             assertFalse(cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED));
9792         });
9793         reset(mWifiNetworkAgent);
9794 
9795         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
9796         mConnectedNetwork.trusted = true;
9797 
9798         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
9799                 .getAllValues()) {
9800             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
9801         }
9802         mLooper.dispatchAll();
9803         assertEquals("L3ConnectedState", getCurrentState().getName());
9804         verifyNoMoreInteractions(mWifiNetworkAgent);
9805     }
9806 
verifyUpdateAutoUpgradeFlagForSaeOnR( boolean isWpa3SaeUpgradeEnabled, boolean isWpa2PersonalOnlyNetworkInRange, boolean isWpa2Wpa3PersonalTransitionNetworkInRange, boolean isWpa3PersonalOnlyNetworkInRange, boolean shouldBeUpdated)9807     private void verifyUpdateAutoUpgradeFlagForSaeOnR(
9808             boolean isWpa3SaeUpgradeEnabled, boolean isWpa2PersonalOnlyNetworkInRange,
9809             boolean isWpa2Wpa3PersonalTransitionNetworkInRange,
9810             boolean isWpa3PersonalOnlyNetworkInRange, boolean shouldBeUpdated)
9811             throws Exception {
9812 
9813         when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(isWpa3SaeUpgradeEnabled);
9814         when(mScanRequestProxy.isWpa2PersonalOnlyNetworkInRange(any()))
9815                 .thenReturn(isWpa2PersonalOnlyNetworkInRange);
9816         when(mScanRequestProxy.isWpa2Wpa3PersonalTransitionNetworkInRange(any()))
9817                 .thenReturn(isWpa2Wpa3PersonalTransitionNetworkInRange);
9818         when(mScanRequestProxy.isWpa3PersonalOnlyNetworkInRange(any()))
9819                 .thenReturn(isWpa3PersonalOnlyNetworkInRange);
9820         initializeAndAddNetworkAndVerifySuccess();
9821 
9822         WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork();
9823         config.networkId = TEST_NETWORK_ID;
9824         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
9825 
9826         IActionListener connectActionListener = mock(IActionListener.class);
9827         mCmi.connectNetwork(
9828                 new NetworkUpdateResult(TEST_NETWORK_ID),
9829                 new ActionListenerWrapper(connectActionListener),
9830                 Process.SYSTEM_UID, OP_PACKAGE_NAME, null);
9831         mLooper.dispatchAll();
9832         verify(connectActionListener).onSuccess();
9833         if (shouldBeUpdated) {
9834             verify(mWifiConfigManager).updateIsAddedByAutoUpgradeFlag(
9835                     eq(TEST_NETWORK_ID), eq(WifiConfiguration.SECURITY_TYPE_SAE),
9836                     eq(false));
9837         } else {
9838             verify(mWifiConfigManager, never()).updateIsAddedByAutoUpgradeFlag(
9839                     anyInt(), anyInt(), anyBoolean());
9840         }
9841     }
9842 
9843     /**
9844      * Tests that manual connection to a network (from settings app) updates
9845      * the auto upgrade flag for SAE on R.
9846      * - SAE auto-upgrade is disabled.
9847      * - No WPA2 PSK network
9848      * - No WPA2/WPA3 network
9849      * - A WPA3-SAE-only network exists.
9850      */
9851     @Test
testManualConnectUpdateAutoUpgradeFlagForSaeOnR()9852     public void testManualConnectUpdateAutoUpgradeFlagForSaeOnR() throws Exception {
9853         assumeFalse(SdkLevel.isAtLeastS());
9854 
9855         verifyUpdateAutoUpgradeFlagForSaeOnR(false, false, false, true, true);
9856     }
9857 
9858     /**
9859      * Tests that manual connection to a network (from settings app) does not update
9860      * the auto upgrade flag for SAE on R if auto-upgrade is enabled.
9861      */
9862     @Test
testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWhenAutoUpgradeEnabled()9863     public void testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWhenAutoUpgradeEnabled()
9864             throws Exception {
9865         assumeFalse(SdkLevel.isAtLeastS());
9866 
9867         verifyUpdateAutoUpgradeFlagForSaeOnR(true, false, false, true, false);
9868     }
9869 
9870     /**
9871      * Tests that manual connection to a network (from settings app) does not update
9872      * the auto upgrade flag for SAE on R if there are psk networks.
9873      */
9874     @Test
testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithPskNetworks()9875     public void testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithPskNetworks()
9876             throws Exception {
9877         assumeFalse(SdkLevel.isAtLeastS());
9878 
9879         verifyUpdateAutoUpgradeFlagForSaeOnR(false, true, false, true, false);
9880     }
9881 
9882     /**
9883      * Tests that manual connection to a network (from settings app) does not update
9884      * the auto upgrade flag for SAE on R if there are psk/ase networks.
9885      */
9886     @Test
testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithPskSaeNetworks()9887     public void testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithPskSaeNetworks()
9888             throws Exception {
9889         assumeFalse(SdkLevel.isAtLeastS());
9890 
9891         verifyUpdateAutoUpgradeFlagForSaeOnR(false, false, true, true, false);
9892     }
9893 
9894     /**
9895      * Tests that manual connection to a network (from settings app) does not update
9896      * the auto upgrade flag for SAE on R if there is no WPA3 SAE only network..
9897      */
9898     @Test
testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithoutSaeOnlyNetworks()9899     public void testManualConnectNotUpdateAutoUpgradeFlagForSaeOnRWithoutSaeOnlyNetworks()
9900             throws Exception {
9901         assumeFalse(SdkLevel.isAtLeastS());
9902 
9903         verifyUpdateAutoUpgradeFlagForSaeOnR(false, false, true, true, false);
9904     }
9905 
setupLegacyEapNetworkTest(boolean isUserSelected)9906     private WifiConfiguration setupLegacyEapNetworkTest(boolean isUserSelected) throws Exception {
9907         return setupTrustOnFirstUse(false, false, isUserSelected);
9908     }
9909 
setupTrustOnFirstUse( boolean isAtLeastT, boolean isTrustOnFirstUseSupported, boolean isUserSelected)9910     private WifiConfiguration setupTrustOnFirstUse(
9911             boolean isAtLeastT, boolean isTrustOnFirstUseSupported, boolean isUserSelected)
9912             throws Exception {
9913         if (isTrustOnFirstUseSupported) {
9914             when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
9915                     createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE));
9916         }
9917         mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler;
9918 
9919         WifiConfiguration eapTlsConfig = spy(WifiConfigurationTestUtil.createEapNetwork(
9920                 WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE));
9921         eapTlsConfig.networkId = FRAMEWORK_NETWORK_ID;
9922         eapTlsConfig.SSID = TEST_SSID;
9923         if (isAtLeastT && isTrustOnFirstUseSupported) {
9924             eapTlsConfig.enterpriseConfig.enableTrustOnFirstUse(true);
9925         }
9926         eapTlsConfig.enterpriseConfig.setCaPath("");
9927         eapTlsConfig.enterpriseConfig.setDomainSuffixMatch("");
9928         eapTlsConfig.setRandomizedMacAddress(TEST_LOCAL_MAC_ADDRESS);
9929         eapTlsConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_AUTO;
9930 
9931         initializeAndAddNetworkAndVerifySuccess(eapTlsConfig);
9932 
9933         if (isUserSelected) {
9934             startConnectSuccess();
9935         } else {
9936             mCmi.startConnectToNetwork(
9937                     eapTlsConfig.networkId,
9938                     Process.SYSTEM_UID,
9939                     ClientModeImpl.SUPPLICANT_BSSID_ANY);
9940             mLooper.dispatchAll();
9941         }
9942         verify(mInsecureEapNetworkHandler).prepareConnection(eq(eapTlsConfig));
9943 
9944         if (isTrustOnFirstUseSupported) {
9945             mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
9946                     new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
9947                             SupplicantState.ASSOCIATED));
9948             mLooper.dispatchAll();
9949 
9950             CertificateEventInfo certificateEventInfo =
9951                     spy(new CertificateEventInfo(FakeKeys.CA_CERT0, "1234"));
9952             mCmi.sendMessage(WifiMonitor.TOFU_CERTIFICATE_EVENT,
9953                     FRAMEWORK_NETWORK_ID, 0, certificateEventInfo);
9954             mLooper.dispatchAll();
9955             verify(mInsecureEapNetworkHandler).addPendingCertificate(
9956                     eq(eapTlsConfig.networkId), eq(0), eq(certificateEventInfo));
9957 
9958             // Adding a certificate in depth 0 will cause a disconnection when TOFU is supported
9959             DisconnectEventInfo disconnectEventInfo =
9960                     new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 3, true);
9961             mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
9962             mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
9963                     new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
9964                             SupplicantState.DISCONNECTED));
9965             mLooper.dispatchAll();
9966         }
9967 
9968         verify(mInsecureEapNetworkHandler).startUserApprovalIfNecessary(eq(isUserSelected));
9969         if (isTrustOnFirstUseSupported) {
9970             assertEquals("DisconnectedState", getCurrentState().getName());
9971         }
9972         return eapTlsConfig;
9973     }
9974 
9975     /**
9976      * Verify Trust On First Use support.
9977      * - This network is selected by a user.
9978      * - Accept the connection.
9979      */
9980     @Test
verifyTrustOnFirstUseAcceptWhenConnectByUser()9981     public void verifyTrustOnFirstUseAcceptWhenConnectByUser() throws Exception {
9982         assumeTrue(SdkLevel.isAtLeastT());
9983         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, true);
9984 
9985         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID,
9986                 testConfig.networkId);
9987         mLooper.dispatchAll();
9988         ArgumentCaptor<WifiConfiguration> wifiConfigurationArgumentCaptor =
9989                 ArgumentCaptor.forClass(WifiConfiguration.class);
9990 
9991         // TOFU will first connect to get the certificates, and then connect once approved
9992         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME),
9993                 wifiConfigurationArgumentCaptor.capture());
9994         assertEquals(testConfig.networkId, wifiConfigurationArgumentCaptor.getValue().networkId);
9995     }
9996 
9997     /**
9998      * Verify Trust On First Use support.
9999      * - This network is selected by a user.
10000      * - Reject the connection.
10001      */
10002     @Test
verifyTrustOnFirstUseRejectWhenConnectByUser()10003     public void verifyTrustOnFirstUseRejectWhenConnectByUser() throws Exception {
10004         assumeTrue(SdkLevel.isAtLeastT());
10005         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, true);
10006 
10007         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID, false);
10008         mLooper.dispatchAll();
10009         verify(mWifiConnectivityManager, never())
10010                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10011         verify(mWifiMetrics).endConnectionEvent(
10012                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
10013                 eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
10014                 eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
10015                 anyInt(), anyInt());
10016         ArgumentCaptor<WifiConfiguration> wifiConfigurationArgumentCaptor =
10017                 ArgumentCaptor.forClass(WifiConfiguration.class);
10018 
10019         // TOFU will connect only once to get the certificates, but will not proceed
10020         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME),
10021                 wifiConfigurationArgumentCaptor.capture());
10022         assertEquals(testConfig.networkId, wifiConfigurationArgumentCaptor.getValue().networkId);
10023 
10024     }
10025 
10026     /**
10027      * Verify Trust On First Use support.
10028      * - This network is selected by a user.
10029      * - Errors occur in InsecureEapNetworkHandler.
10030      */
10031     @Test
verifyTrustOnFirstUseErrorWhenConnectByUser()10032     public void verifyTrustOnFirstUseErrorWhenConnectByUser() throws Exception {
10033         assumeTrue(SdkLevel.isAtLeastT());
10034         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, true);
10035 
10036         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
10037         mLooper.dispatchAll();
10038         verify(mWifiConnectivityManager, never())
10039                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10040         verify(mWifiMetrics).endConnectionEvent(
10041                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
10042                 eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
10043                 eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
10044                 anyInt(), anyInt());
10045     }
10046 
10047     /**
10048      * Verify Trust On First Use support.
10049      * - this network is automatically connected.
10050      * - Tap the notification.
10051      * - Accept the connection.
10052      */
10053     @Test
verifyTrustOnFirstUseAcceptWhenAutoConnect()10054     public void verifyTrustOnFirstUseAcceptWhenAutoConnect() throws Exception {
10055         assumeTrue(SdkLevel.isAtLeastT());
10056         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, false);
10057 
10058         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID,
10059                 testConfig.networkId);
10060         mLooper.dispatchAll();
10061         ArgumentCaptor<WifiConfiguration> wifiConfigurationArgumentCaptor =
10062                 ArgumentCaptor.forClass(WifiConfiguration.class);
10063 
10064         // TOFU will first connect to get the certificates, and then connect once approved
10065         verify(mWifiNative, times(2)).connectToNetwork(eq(WIFI_IFACE_NAME),
10066                 wifiConfigurationArgumentCaptor.capture());
10067         assertEquals(testConfig.networkId, wifiConfigurationArgumentCaptor.getValue().networkId);
10068     }
10069 
10070     /**
10071      * Verify Trust On First Use support.
10072      * - this network is automatically connected.
10073      * - Tap the notification
10074      * - Reject the connection.
10075      */
10076     @Test
verifyTrustOnFirstUseRejectWhenAutoConnect()10077     public void verifyTrustOnFirstUseRejectWhenAutoConnect() throws Exception {
10078         assumeTrue(SdkLevel.isAtLeastT());
10079         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, false);
10080 
10081         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID, false);
10082         mLooper.dispatchAll();
10083         verify(mWifiConnectivityManager, never())
10084                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10085         verify(mWifiMetrics).endConnectionEvent(
10086                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
10087                 eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
10088                 eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
10089                 anyInt(), anyInt());
10090         ArgumentCaptor<WifiConfiguration> wifiConfigurationArgumentCaptor =
10091                 ArgumentCaptor.forClass(WifiConfiguration.class);
10092 
10093         // TOFU will connect only once to get the certificates, but will not proceed
10094         verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME),
10095                 wifiConfigurationArgumentCaptor.capture());
10096         assertEquals(testConfig.networkId, wifiConfigurationArgumentCaptor.getValue().networkId);
10097     }
10098 
10099     /**
10100      * Verify Trust On First Use support.
10101      * - This network is automatically connected.
10102      * - Errors occur in InsecureEapNetworkHandler.
10103      */
10104     @Test
verifyTrustOnFirstUseErrorWhenAutoConnect()10105     public void verifyTrustOnFirstUseErrorWhenAutoConnect() throws Exception {
10106         assumeTrue(SdkLevel.isAtLeastT());
10107         WifiConfiguration testConfig = setupTrustOnFirstUse(true, true, false);
10108 
10109         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onError(testConfig.SSID);
10110         mLooper.dispatchAll();
10111         verify(mWifiConnectivityManager, never())
10112                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10113         verify(mWifiMetrics).endConnectionEvent(
10114                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION),
10115                 eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
10116                 eq(WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN),
10117                 anyInt(), anyInt());
10118     }
10119 
10120     /**
10121      * Verify that InsecureEapNetworkHandler cleanup() is called if wifi is disabled.
10122      */
10123     @Test
verifyInsecureEapNetworkCleanUpWhenDisabled()10124     public void verifyInsecureEapNetworkCleanUpWhenDisabled() throws Exception {
10125         mCmi.stop();
10126         mLooper.dispatchAll();
10127         verify(mInsecureEapNetworkHandler).cleanup();
10128     }
10129 
10130     /**
10131      * Verify legacy EAP network handling.
10132      * - This network is selected by a user.
10133      * - Accept the connection.
10134      */
10135     @Test
verifyLegacyEapNetworkAcceptWhenConnectByUser()10136     public void verifyLegacyEapNetworkAcceptWhenConnectByUser() throws Exception {
10137         assumeFalse(SdkLevel.isAtLeastT());
10138         WifiConfiguration testConfig = setupLegacyEapNetworkTest(true);
10139 
10140         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID,
10141                 testConfig.networkId);
10142         mLooper.dispatchAll();
10143         verify(mWifiMetrics, never()).endConnectionEvent(
10144                 any(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt());
10145     }
10146 
10147     /**
10148      * Verify legacy EAP network handling.
10149      * - This network is selected by a user.
10150      * - Reject the connection.
10151      */
10152     @Test
verifyLegacyEapNetworkRejectWhenConnectByUser()10153     public void verifyLegacyEapNetworkRejectWhenConnectByUser() throws Exception {
10154         assumeFalse(SdkLevel.isAtLeastT());
10155         WifiConfiguration testConfig = setupLegacyEapNetworkTest(true);
10156 
10157         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID, true);
10158         mLooper.dispatchAll();
10159         verify(mWifiConnectivityManager, never())
10160                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10161         verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
10162     }
10163 
10164     /**
10165      * Verify legacy EAP network handling.
10166      * - This network is automatically connected.
10167      * - Tap "connect anyway" on the notification.
10168      */
10169     @Test
verifyLegacyEapNetworkAcceptOnNotificationWhenAutoConnect()10170     public void verifyLegacyEapNetworkAcceptOnNotificationWhenAutoConnect() throws Exception {
10171         assumeFalse(SdkLevel.isAtLeastT());
10172         WifiConfiguration testConfig = setupLegacyEapNetworkTest(false);
10173 
10174         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onAccept(testConfig.SSID,
10175                 testConfig.networkId);
10176         mLooper.dispatchAll();
10177         verify(mWifiMetrics, never()).endConnectionEvent(
10178                 any(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt());
10179     }
10180 
10181     /**
10182      * Verify legacy EAP network handling.
10183      * - This network is automatically connected.
10184      * - Tap "Disconnect now" on the notification
10185      */
10186     @Test
verifyLegacyEapNetworkRejectOnNotificationWhenAutoConnect()10187     public void verifyLegacyEapNetworkRejectOnNotificationWhenAutoConnect() throws Exception {
10188         assumeFalse(SdkLevel.isAtLeastT());
10189         WifiConfiguration testConfig = setupLegacyEapNetworkTest(false);
10190 
10191         mCmi.mInsecureEapNetworkHandlerCallbacksImpl.onReject(testConfig.SSID, true);
10192         mLooper.dispatchAll();
10193         verify(mFrameworkFacade, never()).makeAlertDialogBuilder(any());
10194         verify(mWifiConnectivityManager, never())
10195                 .forceConnectivityScan(eq(ClientModeImpl.WIFI_WORK_SOURCE));
10196         verify(mWifiNative).disconnect(eq(WIFI_IFACE_NAME));
10197     }
10198 
setScanResultWithMloInfo()10199     private void setScanResultWithMloInfo() {
10200         List<MloLink> mloLinks = new ArrayList<>();
10201         MloLink link1 = new MloLink();
10202         link1.setBand(WifiScanner.WIFI_BAND_24_GHZ);
10203         link1.setChannel(TEST_CHANNEL);
10204         link1.setApMacAddress(MacAddress.fromString(TEST_BSSID_STR));
10205         link1.setLinkId(TEST_MLO_LINK_ID);
10206         link1.setRssi(TEST_RSSI);
10207         MloLink link2 = new MloLink();
10208         link2.setBand(WifiScanner.WIFI_BAND_5_GHZ);
10209         link2.setChannel(TEST_CHANNEL_1);
10210         link2.setApMacAddress(MacAddress.fromString(TEST_BSSID_STR1));
10211         link2.setLinkId(TEST_MLO_LINK_ID_1);
10212         link2.setRssi(TEST_RSSI);
10213         mloLinks.add(link1);
10214         mloLinks.add(link2);
10215 
10216         when(mScanResult.getApMldMacAddress()).thenReturn(TEST_AP_MLD_MAC_ADDRESS);
10217         when(mScanResult.getApMloLinkId()).thenReturn(TEST_MLO_LINK_ID);
10218         when(mScanResult.getAffiliatedMloLinks()).thenReturn(mloLinks);
10219         mScanResult.level = TEST_RSSI;
10220 
10221         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
10222                 .thenReturn(mScanDetailCache);
10223         when(mScanDetailCache.getScanResult(any())).thenReturn(mScanResult);
10224     }
10225 
setScanResultWithoutMloInfo()10226     private void setScanResultWithoutMloInfo() {
10227         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11AC;
10228 
10229         when(mScanResult.getApMldMacAddress()).thenReturn(null);
10230         when(mScanResult.getApMloLinkId()).thenReturn(MloLink.INVALID_MLO_LINK_ID);
10231         when(mScanResult.getAffiliatedMloLinks()).thenReturn(Collections.emptyList());
10232 
10233         when(mScanRequestProxy.getScanResults()).thenReturn(Arrays.asList(mScanResult));
10234         when(mScanRequestProxy.getScanResult(any())).thenReturn(mScanResult);
10235     }
10236 
setConnection()10237     private void setConnection() throws Exception {
10238         WifiConfiguration config = createTestNetwork(false);
10239         setupAndStartConnectSequence(config);
10240         validateSuccessfulConnectSequence(config);
10241     }
10242 
setConnectionMloLinksInfo()10243     private void setConnectionMloLinksInfo() {
10244         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE;
10245         WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo();
10246         info.links = new WifiNative.ConnectionMloLink[2];
10247         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
10248                 TEST_AP_MLD_MAC_ADDRESS, Byte.MIN_VALUE, Byte.MAX_VALUE, 5160);
10249         info.links[1] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID_1, TEST_MLO_LINK_ADDR_1,
10250                 TEST_AP_MLD_MAC_ADDRESS, Byte.MAX_VALUE, Byte.MIN_VALUE, 2437);
10251         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
10252     }
10253 
10254     /**
10255      * Verify Affiliated link BSSID matching
10256      */
10257     @Test
testAffiliatedLinkBssidMatch()10258     public  void testAffiliatedLinkBssidMatch() throws Exception {
10259         setConnection();
10260         setScanResultWithMloInfo();
10261         // Associate
10262         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10263                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10264                         SupplicantState.ASSOCIATED));
10265         mLooper.dispatchAll();
10266         // Validate Affiliated BSSID match
10267         assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR)));
10268         assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR1)));
10269         assertFalse(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR2)));
10270         // Check for null BSSID
10271         assertFalse(mCmi.isAffiliatedLinkBssid(null));
10272     }
10273 
10274     @Test
testAffiliatedLinkBssidMatchWithNullLinkMacAddress()10275     public  void testAffiliatedLinkBssidMatchWithNullLinkMacAddress() throws Exception {
10276         setConnection();
10277         List<MloLink> mloLinks = new ArrayList<>();
10278         // Build MLO link with null link mac address
10279         MloLink link1 = new MloLink();
10280         link1.setBand(WifiScanner.WIFI_BAND_24_GHZ);
10281         link1.setChannel(TEST_CHANNEL);
10282         link1.setLinkId(TEST_MLO_LINK_ID);
10283         link1.setRssi(TEST_RSSI);
10284         mloLinks.add(link1);
10285         when(mScanResult.getApMldMacAddress()).thenReturn(TEST_AP_MLD_MAC_ADDRESS);
10286         when(mScanResult.getApMloLinkId()).thenReturn(TEST_MLO_LINK_ID);
10287         when(mScanResult.getAffiliatedMloLinks()).thenReturn(mloLinks);
10288         mScanResult.level = TEST_RSSI;
10289         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
10290                 .thenReturn(mScanDetailCache);
10291         when(mScanDetailCache.getScanResult(any())).thenReturn(mScanResult);
10292         // Associate
10293         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10294                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10295                         SupplicantState.ASSOCIATED));
10296         mLooper.dispatchAll();
10297         // Test isAffiliatedLinkBssid match fails with no NPE
10298         assertFalse(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR)));
10299         // Check for null BSSID
10300         assertFalse(mCmi.isAffiliatedLinkBssid(null));
10301     }
10302 
10303     /**
10304      * Verify MLO parameters update from ScanResult at association
10305      */
10306     @Test
verifyMloParametersUpdateAssoc()10307     public void verifyMloParametersUpdateAssoc() throws Exception {
10308         setConnection();
10309         setScanResultWithMloInfo();
10310         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10311                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10312                         SupplicantState.ASSOCIATED));
10313         mLooper.dispatchAll();
10314 
10315         WifiInfo connectionInfo = mCmi.getConnectionInfo();
10316         assertNotNull(connectionInfo.getApMldMacAddress());
10317         assertEquals(TEST_AP_MLD_MAC_ADDRESS_STR, connectionInfo.getApMldMacAddress().toString());
10318         assertEquals(TEST_MLO_LINK_ID, connectionInfo.getApMloLinkId());
10319         assertEquals(2, connectionInfo.getAffiliatedMloLinks().size());
10320         // None of the links are active or idle.
10321         assertTrue(connectionInfo.getAssociatedMloLinks().isEmpty());
10322     }
10323 
10324     /**
10325      * Verify MLO parameters update when roaming to a MLD ap, and then get cleared when roaming to
10326      * a non MLD supported AP.
10327      */
10328     @Test
verifyMloParametersUpdateRoam()10329     public void verifyMloParametersUpdateRoam() throws Exception {
10330         connect();
10331         setScanResultWithMloInfo();
10332 
10333         // Roam to an MLD AP
10334         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10335                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10336                         SupplicantState.ASSOCIATED));
10337         mLooper.dispatchAll();
10338 
10339         WifiInfo connectionInfo = mCmi.getConnectionInfo();
10340         assertNotNull(connectionInfo.getApMldMacAddress());
10341         assertEquals(TEST_AP_MLD_MAC_ADDRESS_STR, connectionInfo.getApMldMacAddress().toString());
10342         assertEquals(TEST_MLO_LINK_ID, connectionInfo.getApMloLinkId());
10343         assertEquals(2, connectionInfo.getAffiliatedMloLinks().size());
10344 
10345         // Now perform Roaming to a non-MLD AP
10346         setScanResultWithoutMloInfo();
10347         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10348                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10349                         SupplicantState.ASSOCIATED));
10350         mLooper.dispatchAll();
10351 
10352         connectionInfo = mCmi.getConnectionInfo();
10353         assertNull(connectionInfo.getApMldMacAddress());
10354         assertEquals(MloLink.INVALID_MLO_LINK_ID, connectionInfo.getApMloLinkId());
10355         assertTrue(connectionInfo.getAffiliatedMloLinks().isEmpty());
10356         assertTrue(connectionInfo.getAssociatedMloLinks().isEmpty());
10357     }
10358 
10359     /**
10360      * Verify API calls on affiliated BSSIDs during association and disconnect.
10361      */
10362     @Test
verifyAffiliatedBssidsAssocDisconnect()10363     public void verifyAffiliatedBssidsAssocDisconnect() throws Exception {
10364         List<String> affiliatedBssids = Arrays.asList(TEST_BSSID_STR1);
10365 
10366         connect();
10367         setScanResultWithMloInfo();
10368         setConnectionMloLinksInfo();
10369         mLooper.dispatchAll();
10370 
10371         // Association
10372         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10373                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10374                         SupplicantState.ASSOCIATED));
10375         mLooper.dispatchAll();
10376         verify(mWifiBlocklistMonitor).setAffiliatedBssids(eq(TEST_BSSID_STR), eq(affiliatedBssids));
10377 
10378         // Disconnect
10379         DisconnectEventInfo disconnectEventInfo =
10380                 new DisconnectEventInfo(TEST_SSID, TEST_BSSID_STR, 0, false);
10381         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, disconnectEventInfo);
10382         mLooper.dispatchAll();
10383         verify(mWifiBlocklistMonitor).removeAffiliatedBssids(eq(TEST_BSSID_STR));
10384     }
10385 
configureMloLinksInfoWithIdleLinks()10386     private void configureMloLinksInfoWithIdleLinks() {
10387         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE;
10388         WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo();
10389         info.links = new WifiNative.ConnectionMloLink[2];
10390         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
10391                 TEST_AP_MLD_MAC_ADDRESS, (byte) 0xFF, (byte) 0xFF, 2437);
10392         info.links[1] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID_1, TEST_MLO_LINK_ADDR_1,
10393                 TEST_AP_MLD_MAC_ADDRESS, (byte) 0, (byte) 0, 5160);
10394         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
10395     }
10396 
reconfigureMloLinksInfoWithOneLink()10397     private void reconfigureMloLinksInfoWithOneLink() {
10398         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE;
10399         WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo();
10400         info.links = new WifiNative.ConnectionMloLink[1];
10401         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
10402                 TEST_AP_MLD_MAC_ADDRESS, (byte) 0xFF, (byte) 0xFF, 2437);
10403         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
10404     }
10405 
10406     @Test
verifyMloLinkChangeTidToLinkMapping()10407     public void verifyMloLinkChangeTidToLinkMapping() throws Exception {
10408         // Initialize
10409         connect();
10410         setScanResultWithMloInfo();
10411         setConnectionMloLinksInfo();
10412         mLooper.dispatchAll();
10413 
10414         // Association
10415         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10416                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10417                         SupplicantState.ASSOCIATED));
10418         mLooper.dispatchAll();
10419         // Make sure all links are active
10420         for (MloLink link: mWifiInfo.getAffiliatedMloLinks()) {
10421             assertEquals(link.getState(), MloLink.MLO_LINK_STATE_ACTIVE);
10422         }
10423         // All links are associated (ACTIVE)
10424         assertEquals(mWifiInfo.getAssociatedMloLinks().size(),
10425                 mWifiInfo.getAffiliatedMloLinks().size());
10426 
10427         // TID to link mapping. Make sure one link is IDLE.
10428         configureMloLinksInfoWithIdleLinks();
10429         mCmi.sendMessage(WifiMonitor.MLO_LINKS_INFO_CHANGED,
10430                 WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP);
10431         mLooper.dispatchAll();
10432         List<MloLink> links = mWifiInfo.getAffiliatedMloLinks();
10433         assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE);
10434         assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_IDLE);
10435         // All links are associated (ACTIVE & IDLE)
10436         assertEquals(mWifiInfo.getAssociatedMloLinks().size(),
10437                 mWifiInfo.getAffiliatedMloLinks().size());
10438 
10439         // LInk Removal. Make sure removed link is UNASSOCIATED.
10440         reconfigureMloLinksInfoWithOneLink();
10441         mCmi.sendMessage(WifiMonitor.MLO_LINKS_INFO_CHANGED,
10442                 WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL);
10443         mLooper.dispatchAll();
10444         links = mWifiInfo.getAffiliatedMloLinks();
10445         assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE);
10446         assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_UNASSOCIATED);
10447         // One link is unassociated.
10448         assertEquals(2, mWifiInfo.getAffiliatedMloLinks().size());
10449         assertEquals(1, mWifiInfo.getAssociatedMloLinks().size());
10450 
10451     }
10452 
10453     @Test
verifyMloLinkChangeAfterAssociation()10454     public void verifyMloLinkChangeAfterAssociation() throws Exception {
10455         // Initialize
10456         connect();
10457         setScanResultWithMloInfo();
10458         setConnectionMloLinksInfo();
10459         mLooper.dispatchAll();
10460 
10461         // Association
10462         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10463                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10464                         SupplicantState.ASSOCIATED));
10465         mLooper.dispatchAll();
10466         // Verify all links are associated (ACTIVE) after assciation.
10467         assertEquals(mWifiInfo.getAssociatedMloLinks().size(),
10468                 mWifiInfo.getAffiliatedMloLinks().size());
10469 
10470         // verify that affiliated link state the scan results are still in unassociated state.
10471         for (MloLink link : mScanResult.getAffiliatedMloLinks()) {
10472             assertEquals(MloLink.MLO_LINK_STATE_UNASSOCIATED, link.getState());
10473         }
10474         // verify that affiliated link state are active
10475         for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) {
10476             assertEquals(MloLink.MLO_LINK_STATE_ACTIVE, link.getState());
10477         }
10478 
10479         setScanResultWithMloInfo();
10480         // Send FOUR_WAY_HANDSHAKE, GROUP_HANDSHAKE and COMPLETED and verify all links are still
10481         // asscoaited.
10482         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10483                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10484                         SupplicantState.FOUR_WAY_HANDSHAKE));
10485 
10486         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10487                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10488                         SupplicantState.GROUP_HANDSHAKE));
10489 
10490         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
10491                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
10492                         SupplicantState.COMPLETED));
10493         mLooper.dispatchAll();
10494         // Verify all links are still associated (ACTIVE).
10495         assertEquals(mWifiInfo.getAssociatedMloLinks().size(),
10496                 mWifiInfo.getAffiliatedMloLinks().size());
10497     }
10498     /**
10499      * Verify that an event that occurs on a managed network is handled by
10500      * logEventIfManagedNetwork.
10501      */
10502     @Test
verifyEventHandledByLogEventIfManagedNetwork()10503     public void verifyEventHandledByLogEventIfManagedNetwork() throws Exception {
10504         assumeTrue(SdkLevel.isAtLeastT());
10505         MacAddress bssid = MacAddress.fromString(TEST_BSSID_STR);
10506         int numMaskedOctets = 4;
10507 
10508         mResources.setInteger(
10509                 R.integer.config_wifiNumMaskedBssidOctetsInSecurityLog, numMaskedOctets);
10510         when(mWifiPermissionsUtil.isAdmin(anyInt(), any())).thenReturn(true);
10511         MockitoSession scanResultUtilSession = ExtendedMockito.mockitoSession()
10512                 .strictness(Strictness.LENIENT)
10513                 .mockStatic(ScanResultUtil.class, withSettings().lenient())
10514                 .startMocking();
10515         connect();
10516 
10517         // Connect will generate the Associated and Connected events. Confirm the events were
10518         // handled by checking that redactBssid() was called for each one.
10519         ExtendedMockito.verify(() ->
10520                 ScanResultUtil.redactBssid(bssid, numMaskedOctets), times(2));
10521         scanResultUtilSession.finishMocking();
10522     }
10523 
10524     /**
10525      * Verify that QoS policy reset events are handled when mNetworkAgent is non-null.
10526      */
10527     @Test
verifyQosPolicyResetEventWithNonNullNetworkAgent()10528     public void verifyQosPolicyResetEventWithNonNullNetworkAgent() throws Exception {
10529         assumeTrue(SdkLevel.isAtLeastT());
10530         connect();
10531         assertNotNull(mCmi.mNetworkAgent);
10532         mCmi.sendMessage(WifiMonitor.QOS_POLICY_RESET_EVENT, 0, 0, null);
10533         mLooper.dispatchAll();
10534         verify(mWifiNetworkAgent).sendRemoveAllDscpPolicies();
10535     }
10536 
10537     /**
10538      * Verify that QoS policy reset events are not handled when mNetworkAgent is null.
10539      */
10540     @Test
verifyQosPolicyResetEventWithNullNetworkAgent()10541     public void verifyQosPolicyResetEventWithNullNetworkAgent() throws Exception {
10542         assumeTrue(SdkLevel.isAtLeastT());
10543         assertNull(mCmi.mNetworkAgent);
10544         mCmi.sendMessage(WifiMonitor.QOS_POLICY_RESET_EVENT, 0, 0, null);
10545         mLooper.dispatchAll();
10546         verify(mWifiNetworkAgent, never()).sendRemoveAllDscpPolicies();
10547     }
10548 
10549     /**
10550      * Verify that QoS policy reset events are not handled if the QoS policy feature was
10551      * not enabled in WifiNative.
10552      */
10553     @Test
verifyQosPolicyResetEventWhenQosFeatureNotEnabled()10554     public void verifyQosPolicyResetEventWhenQosFeatureNotEnabled() throws Exception {
10555         assumeTrue(SdkLevel.isAtLeastT());
10556         connect();
10557         assertNotNull(mCmi.mNetworkAgent);
10558         when(mWifiNative.isQosPolicyFeatureEnabled()).thenReturn(false);
10559         mCmi.sendMessage(WifiMonitor.QOS_POLICY_RESET_EVENT, 0, 0, null);
10560         mLooper.dispatchAll();
10561         verify(mWifiNetworkAgent, never()).sendRemoveAllDscpPolicies();
10562     }
10563 
10564     /**
10565      * Verify that QoS policy request events are handled when mNetworkAgent is non-null.
10566      */
10567     @Test
verifyQosPolicyRequestEvent()10568     public void verifyQosPolicyRequestEvent() throws Exception {
10569         assumeTrue(SdkLevel.isAtLeastT());
10570         final int dialogToken = 124;
10571 
10572         // Event should be ignored by the QosPolicyRequestHandler if no network is connected,
10573         // since mNetworkAgent is null.
10574         assertNull(mCmi.mNetworkAgent);
10575         mCmi.sendMessage(WifiMonitor.QOS_POLICY_REQUEST_EVENT, dialogToken, 0,
10576                 new ArrayList<SupplicantStaIfaceHal.QosPolicyRequest>());
10577         mLooper.dispatchAll();
10578 
10579         // New events should be processed after connecting to a network,
10580         // since mNetworkAgent is not null.
10581         connect();
10582         assertNotNull(mCmi.mNetworkAgent);
10583         mCmi.sendMessage(WifiMonitor.QOS_POLICY_REQUEST_EVENT, dialogToken + 1, 0,
10584                 new ArrayList<SupplicantStaIfaceHal.QosPolicyRequest>());
10585         mLooper.dispatchAll();
10586 
10587         verify(mWifiNative, never()).sendQosPolicyResponse(
10588                 eq(WIFI_IFACE_NAME), eq(dialogToken), eq(true), any());
10589         verify(mWifiNative).sendQosPolicyResponse(
10590                 eq(WIFI_IFACE_NAME), eq(dialogToken + 1), eq(true), any());
10591     }
10592 
verifyConnectWithDisabledType( WifiConfiguration config, List<ScanResult> results, boolean shouldDropRequest)10593     private void verifyConnectWithDisabledType(
10594             WifiConfiguration config, List<ScanResult> results,
10595             boolean shouldDropRequest) throws Exception {
10596         WifiDialogManager mockWifiDialogManager = mock(WifiDialogManager.class);
10597         WifiDialogManager.DialogHandle mockDialogHandle =
10598                 mock(WifiDialogManager.DialogHandle.class);
10599         when(mockWifiDialogManager.createLegacySimpleDialog(any(), any(), any(), any(), any(),
10600                 any(), any())).thenReturn(mockDialogHandle);
10601         when(mWifiInjector.getWifiDialogManager()).thenReturn(mockWifiDialogManager);
10602         // Add some irrelevant networks to ensure they are filtered.
10603         final String irrelevantSsid = "IrrelevantSsid";
10604         results.add(makeScanResult(irrelevantSsid, "[PSK]"));
10605         results.add(makeScanResult(irrelevantSsid, "[SAE]"));
10606         results.add(makeScanResult(irrelevantSsid, "[PSK][SAE]"));
10607         results.add(makeScanResult(irrelevantSsid, ""));
10608         results.add(makeScanResult(irrelevantSsid, "[OWE_TRANSITION]"));
10609         results.add(makeScanResult(irrelevantSsid, "[OWE]"));
10610         results.add(makeScanResult(irrelevantSsid, "[RSN][EAP/SHA1][MFPC]"));
10611         results.add(makeScanResult(irrelevantSsid, "[RSN][EAP/SHA1][EAP/SHA256][MFPC]"));
10612         results.add(makeScanResult(irrelevantSsid, "[RSN][EAP/SHA256][MFPC][MFPR]"));
10613         when(mScanRequestProxy.getScanResults()).thenReturn(results);
10614 
10615         initializeAndAddNetworkAndVerifySuccess();
10616 
10617         when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(TEST_NETWORK_ID))
10618                 .thenReturn(config);
10619         when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config);
10620 
10621         IActionListener connectActionListener = mock(IActionListener.class);
10622         mCmi.connectNetwork(
10623                 new NetworkUpdateResult(TEST_NETWORK_ID),
10624                 new ActionListenerWrapper(connectActionListener),
10625                 Process.SYSTEM_UID, OP_PACKAGE_NAME, null);
10626         mLooper.dispatchAll();
10627         verify(connectActionListener).onSuccess();
10628         if (shouldDropRequest) {
10629             verify(mockDialogHandle).launchDialog();
10630             verify(mWifiNative, never()).connectToNetwork(any(), any());
10631         } else {
10632             verify(mockDialogHandle, never()).launchDialog();
10633             verify(mWifiNative).connectToNetwork(eq(WIFI_IFACE_NAME), eq(config));
10634         }
10635     }
10636 
makeScanResult(String ssid, String caps)10637     private ScanResult makeScanResult(String ssid, String caps) {
10638         ScanResult scanResult = new ScanResult.Builder(
10639                 WifiSsid.fromUtf8Text(ssid.replace("\"", "")),
10640                 TEST_BSSID_STR)
10641                 .setHessid(1245)
10642                 .setCaps(caps)
10643                 .setRssi(-78)
10644                 .setFrequency(2450)
10645                 .setTsf(1025)
10646                 .setDistanceCm(22)
10647                 .setDistanceSdCm(33)
10648                 .setIs80211McRTTResponder(true)
10649                 .build();
10650         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
10651                 ssid.getBytes(StandardCharsets.UTF_8));
10652         scanResult.informationElements = new ScanResult.InformationElement[]{ie};
10653         return scanResult;
10654     }
10655 
verifyConnectWithDisabledPskType( boolean isWpa2PersonalOnlyNetworkInRange, boolean isWpa2Wpa3PersonalTransitionNetworkInRange, boolean isWpa3PersonalOnlyNetworkInRange, boolean shouldDropRequest)10656     private void verifyConnectWithDisabledPskType(
10657             boolean isWpa2PersonalOnlyNetworkInRange,
10658             boolean isWpa2Wpa3PersonalTransitionNetworkInRange,
10659             boolean isWpa3PersonalOnlyNetworkInRange, boolean shouldDropRequest)
10660             throws Exception {
10661         WifiConfiguration config = WifiConfigurationTestUtil.createPskSaeNetwork();
10662         config.networkId = TEST_NETWORK_ID;
10663         config.setSecurityParamsEnabled(WifiConfiguration.SECURITY_TYPE_PSK, false);
10664         List<ScanResult> results = new ArrayList<>();
10665         if (isWpa2PersonalOnlyNetworkInRange) {
10666             results.add(makeScanResult(config.SSID, "[PSK]"));
10667         }
10668         if (isWpa2Wpa3PersonalTransitionNetworkInRange) {
10669             results.add(makeScanResult(config.SSID, "[PSK][SAE]"));
10670         }
10671         if (isWpa3PersonalOnlyNetworkInRange) {
10672             results.add(makeScanResult(config.SSID, "[SAE]"));
10673         }
10674 
10675         verifyConnectWithDisabledType(config, results, shouldDropRequest);
10676     }
10677 
10678     @Test
testConnectDropWithOnlyDisabledPskNetwork()10679     public void testConnectDropWithOnlyDisabledPskNetwork() throws Exception {
10680         boolean isWpa2PersonalOnlyNetworkInRange = true;
10681         boolean isWpa2Wpa3PersonalTransitionNetworkInRange = false;
10682         boolean isWpa3PersonalOnlyNetworkInRange = false;
10683         boolean shouldDropRequest = true;
10684 
10685         verifyConnectWithDisabledPskType(isWpa2PersonalOnlyNetworkInRange,
10686                 isWpa2Wpa3PersonalTransitionNetworkInRange,
10687                 isWpa3PersonalOnlyNetworkInRange, shouldDropRequest);
10688     }
10689 
10690     @Test
testConnectAllowedWithPskSaeNetwork()10691     public void testConnectAllowedWithPskSaeNetwork() throws Exception {
10692         boolean isWpa2PersonalOnlyNetworkInRange = true;
10693         boolean isWpa2Wpa3PersonalTransitionNetworkInRange = true;
10694         boolean isWpa3PersonalOnlyNetworkInRange = false;
10695         boolean shouldDropRequest = false;
10696 
10697         verifyConnectWithDisabledPskType(isWpa2PersonalOnlyNetworkInRange,
10698                 isWpa2Wpa3PersonalTransitionNetworkInRange,
10699                 isWpa3PersonalOnlyNetworkInRange, shouldDropRequest);
10700     }
10701 
10702     @Test
testConnectAllowedWithSaeNetwork()10703     public void testConnectAllowedWithSaeNetwork() throws Exception {
10704         boolean isWpa2PersonalOnlyNetworkInRange = true;
10705         boolean isWpa2Wpa3PersonalTransitionNetworkInRange = false;
10706         boolean isWpa3PersonalOnlyNetworkInRange = true;
10707         boolean shouldDropRequest = false;
10708 
10709         verifyConnectWithDisabledPskType(isWpa2PersonalOnlyNetworkInRange,
10710                 isWpa2Wpa3PersonalTransitionNetworkInRange,
10711                 isWpa3PersonalOnlyNetworkInRange, shouldDropRequest);
10712     }
10713 
10714     @Test
testConnectAllowedWithoutPskNetwork()10715     public void testConnectAllowedWithoutPskNetwork() throws Exception {
10716         boolean isWpa2PersonalOnlyNetworkInRange = false;
10717         boolean isWpa2Wpa3PersonalTransitionNetworkInRange = true;
10718         boolean isWpa3PersonalOnlyNetworkInRange = false;
10719         boolean shouldDropRequest = false;
10720 
10721         verifyConnectWithDisabledPskType(isWpa2PersonalOnlyNetworkInRange,
10722                 isWpa2Wpa3PersonalTransitionNetworkInRange,
10723                 isWpa3PersonalOnlyNetworkInRange, shouldDropRequest);
10724     }
10725 
10726     @Test
testConnectDisabledPskAllowedForNonUserSelectedNetwork()10727     public void testConnectDisabledPskAllowedForNonUserSelectedNetwork() throws Exception {
10728         boolean isWpa2PersonalOnlyNetworkInRange = true;
10729         boolean isWpa2Wpa3PersonalTransitionNetworkInRange = false;
10730         boolean isWpa3PersonalOnlyNetworkInRange = false;
10731         boolean shouldDropRequest = false;
10732 
10733         // Only a request from settings or setup wizard are considered a user selected network.
10734         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
10735         when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false);
10736 
10737         verifyConnectWithDisabledPskType(isWpa2PersonalOnlyNetworkInRange,
10738                 isWpa2Wpa3PersonalTransitionNetworkInRange,
10739                 isWpa3PersonalOnlyNetworkInRange, shouldDropRequest);
10740     }
10741 
verifyConnectWithDisabledOpenType( boolean isOpenOnlyNetworkInRange, boolean isOpenOweTransitionNetworkInRange, boolean isOweOnlyNetworkInRange, boolean shouldDropRequest)10742     private void verifyConnectWithDisabledOpenType(
10743             boolean isOpenOnlyNetworkInRange,
10744             boolean isOpenOweTransitionNetworkInRange,
10745             boolean isOweOnlyNetworkInRange, boolean shouldDropRequest)
10746             throws Exception {
10747         WifiConfiguration config = WifiConfigurationTestUtil.createOpenOweNetwork();
10748         config.networkId = TEST_NETWORK_ID;
10749         config.setSecurityParamsEnabled(WifiConfiguration.SECURITY_TYPE_OPEN, false);
10750         List<ScanResult> results = new ArrayList<>();
10751         if (isOpenOnlyNetworkInRange) {
10752             results.add(makeScanResult(config.SSID, ""));
10753         }
10754         if (isOpenOweTransitionNetworkInRange) {
10755             results.add(makeScanResult(config.SSID, "[OWE_TRANSITION]"));
10756         }
10757         if (isOweOnlyNetworkInRange) {
10758             results.add(makeScanResult(config.SSID, "[OWE]"));
10759         }
10760 
10761         verifyConnectWithDisabledType(config, results, shouldDropRequest);
10762     }
10763 
10764     @Test
testConnectDropWithOnlyDisabledOpenNetwork()10765     public void testConnectDropWithOnlyDisabledOpenNetwork() throws Exception {
10766         boolean isOpenOnlyNetworkInRange = true;
10767         boolean isOpenOweTransitionNetworkInRange = false;
10768         boolean isOweOnlyNetworkInRange = false;
10769         boolean shouldDropRequest = true;
10770 
10771         verifyConnectWithDisabledOpenType(isOpenOnlyNetworkInRange,
10772                 isOpenOweTransitionNetworkInRange,
10773                 isOweOnlyNetworkInRange, shouldDropRequest);
10774     }
10775 
10776     @Test
testConnectAllowedWithOpenOweNetwork()10777     public void testConnectAllowedWithOpenOweNetwork() throws Exception {
10778         boolean isOpenOnlyNetworkInRange = true;
10779         boolean isOpenOweTransitionNetworkInRange = true;
10780         boolean isOweOnlyNetworkInRange = false;
10781         boolean shouldDropRequest = false;
10782 
10783         verifyConnectWithDisabledOpenType(isOpenOnlyNetworkInRange,
10784                 isOpenOweTransitionNetworkInRange,
10785                 isOweOnlyNetworkInRange, shouldDropRequest);
10786     }
10787 
10788     @Test
testConnectAllowedWithOweNetwork()10789     public void testConnectAllowedWithOweNetwork() throws Exception {
10790         boolean isOpenOnlyNetworkInRange = true;
10791         boolean isOpenOweTransitionNetworkInRange = false;
10792         boolean isOweOnlyNetworkInRange = true;
10793         boolean shouldDropRequest = false;
10794 
10795         verifyConnectWithDisabledOpenType(isOpenOnlyNetworkInRange,
10796                 isOpenOweTransitionNetworkInRange,
10797                 isOweOnlyNetworkInRange, shouldDropRequest);
10798     }
10799 
10800     @Test
testConnectAllowedWithoutOpenNetwork()10801     public void testConnectAllowedWithoutOpenNetwork() throws Exception {
10802         boolean isOpenOnlyNetworkInRange = false;
10803         boolean isOpenOweTransitionNetworkInRange = true;
10804         boolean isOweOnlyNetworkInRange = false;
10805         boolean shouldDropRequest = false;
10806 
10807         verifyConnectWithDisabledOpenType(isOpenOnlyNetworkInRange,
10808                 isOpenOweTransitionNetworkInRange,
10809                 isOweOnlyNetworkInRange, shouldDropRequest);
10810     }
10811 
10812     @Test
testConnectDisabledOpenAllowedForNonUserSelectedNetwork()10813     public void testConnectDisabledOpenAllowedForNonUserSelectedNetwork() throws Exception {
10814         boolean isOpenOnlyNetworkInRange = true;
10815         boolean isOpenOweTransitionNetworkInRange = false;
10816         boolean isOweOnlyNetworkInRange = false;
10817         boolean shouldDropRequest = false;
10818 
10819         // Only a request from settings or setup wizard are considered a user selected network.
10820         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
10821         when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false);
10822 
10823         verifyConnectWithDisabledOpenType(isOpenOnlyNetworkInRange,
10824                 isOpenOweTransitionNetworkInRange,
10825                 isOweOnlyNetworkInRange, shouldDropRequest);
10826     }
10827 
verifyConnectWithDisabledWpa2EnterpriseType( boolean isWpa2EnterpriseOnlyNetworkInRange, boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange, boolean isWpa3EnterpriseOnlyNetworkInRange, boolean shouldDropRequest)10828     private void verifyConnectWithDisabledWpa2EnterpriseType(
10829             boolean isWpa2EnterpriseOnlyNetworkInRange,
10830             boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10831             boolean isWpa3EnterpriseOnlyNetworkInRange, boolean shouldDropRequest)
10832             throws Exception {
10833         WifiConfiguration config = WifiConfigurationTestUtil.createWpa2Wpa3EnterpriseNetwork();
10834         config.networkId = TEST_NETWORK_ID;
10835         config.setSecurityParamsEnabled(WifiConfiguration.SECURITY_TYPE_EAP, false);
10836         List<ScanResult> results = new ArrayList<>();
10837         if (isWpa2EnterpriseOnlyNetworkInRange) {
10838             results.add(makeScanResult(config.SSID, "[RSN][EAP/SHA1][MFPC]"));
10839         }
10840         if (isWpa2Wpa3EnterpriseTransitionNetworkInRange) {
10841             results.add(makeScanResult(config.SSID, "[RSN][EAP/SHA1][EAP/SHA256][MFPC]"));
10842         }
10843         if (isWpa3EnterpriseOnlyNetworkInRange) {
10844             results.add(makeScanResult(config.SSID, "[RSN][EAP/SHA256][MFPC][MFPR]"));
10845         }
10846 
10847         verifyConnectWithDisabledType(config, results, shouldDropRequest);
10848     }
10849 
10850     @Test
testConnectDropWithOnlyDisabledWpa2EnterpriseNetwork()10851     public void testConnectDropWithOnlyDisabledWpa2EnterpriseNetwork() throws Exception {
10852         boolean isWpa2EnterpriseOnlyNetworkInRange = true;
10853         boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange = false;
10854         boolean isWpa3EnterpriseOnlyNetworkInRange = false;
10855         boolean shouldDropRequest = true;
10856 
10857         verifyConnectWithDisabledWpa2EnterpriseType(isWpa2EnterpriseOnlyNetworkInRange,
10858                 isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10859                 isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest);
10860     }
10861 
10862     @Test
testConnectAllowedWithWpa2Wpa3EnterpriseNetwork()10863     public void testConnectAllowedWithWpa2Wpa3EnterpriseNetwork() throws Exception {
10864         boolean isWpa2EnterpriseOnlyNetworkInRange = true;
10865         boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange = true;
10866         boolean isWpa3EnterpriseOnlyNetworkInRange = false;
10867         boolean shouldDropRequest = false;
10868 
10869         verifyConnectWithDisabledWpa2EnterpriseType(isWpa2EnterpriseOnlyNetworkInRange,
10870                 isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10871                 isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest);
10872     }
10873 
10874     @Test
testConnectAllowedWithWpa3EnterpriseNetwork()10875     public void testConnectAllowedWithWpa3EnterpriseNetwork() throws Exception {
10876         boolean isWpa2EnterpriseOnlyNetworkInRange = true;
10877         boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange = false;
10878         boolean isWpa3EnterpriseOnlyNetworkInRange = true;
10879         boolean shouldDropRequest = false;
10880 
10881         verifyConnectWithDisabledWpa2EnterpriseType(isWpa2EnterpriseOnlyNetworkInRange,
10882                 isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10883                 isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest);
10884     }
10885 
10886     @Test
testConnectAllowedWithoutWpa2EnterpriseNetwork()10887     public void testConnectAllowedWithoutWpa2EnterpriseNetwork() throws Exception {
10888         boolean isWpa2EnterpriseOnlyNetworkInRange = false;
10889         boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange = true;
10890         boolean isWpa3EnterpriseOnlyNetworkInRange = false;
10891         boolean shouldDropRequest = false;
10892 
10893         verifyConnectWithDisabledWpa2EnterpriseType(isWpa2EnterpriseOnlyNetworkInRange,
10894                 isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10895                 isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest);
10896     }
10897 
10898     @Test
testConnectDisabledWpa2EnterpriseAllowedForNonUserSelectedNetwork()10899     public void testConnectDisabledWpa2EnterpriseAllowedForNonUserSelectedNetwork()
10900             throws Exception {
10901         boolean isWpa2EnterpriseOnlyNetworkInRange = true;
10902         boolean isWpa2Wpa3EnterpriseTransitionNetworkInRange = false;
10903         boolean isWpa3EnterpriseOnlyNetworkInRange = false;
10904         boolean shouldDropRequest = false;
10905 
10906         // Only a request from settings or setup wizard are considered a user selected network.
10907         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false);
10908         when(mWifiPermissionsUtil.checkNetworkSetupWizardPermission(anyInt())).thenReturn(false);
10909 
10910         verifyConnectWithDisabledWpa2EnterpriseType(isWpa2EnterpriseOnlyNetworkInRange,
10911                 isWpa2Wpa3EnterpriseTransitionNetworkInRange,
10912                 isWpa3EnterpriseOnlyNetworkInRange, shouldDropRequest);
10913     }
10914 
10915     @Test
testUpdateAkmByConnectionInfo()10916     public void testUpdateAkmByConnectionInfo() throws Exception {
10917         mConnectedNetwork = spy(WifiConfigurationTestUtil.createPskSaeNetwork());
10918 
10919         triggerConnect();
10920 
10921         // WifiInfo is not updated yet.
10922         assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, mWifiInfo.getCurrentSecurityType());
10923 
10924         WifiSsid wifiSsid = WifiSsid.fromBytes(
10925                 NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID)));
10926         BitSet akm = new BitSet();
10927         akm.set(WifiConfiguration.KeyMgmt.SAE);
10928         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
10929                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm));
10930         mLooper.dispatchAll();
10931         // WifiInfo is updated to the actual used type.
10932         assertEquals(WifiInfo.SECURITY_TYPE_SAE, mWifiInfo.getCurrentSecurityType());
10933 
10934         // Roam to a PSK BSS.
10935         akm.clear();
10936         akm.set(WifiConfiguration.KeyMgmt.WPA_PSK);
10937         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
10938                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm));
10939         mLooper.dispatchAll();
10940         // WifiInfo is updated to the actual used type.
10941         assertEquals(WifiInfo.SECURITY_TYPE_PSK, mWifiInfo.getCurrentSecurityType());
10942 
10943         // Roam back to a SAE BSS.
10944         akm.clear();
10945         akm.set(WifiConfiguration.KeyMgmt.SAE);
10946         mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT,
10947                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm));
10948         mLooper.dispatchAll();
10949         // WifiInfo is updated to the actual used type.
10950         assertEquals(WifiInfo.SECURITY_TYPE_SAE, mWifiInfo.getCurrentSecurityType());
10951     }
10952 
10953     @Test
testUpdateWpa3EnterpriseSecurityTypeByConnectionInfo()10954     public void testUpdateWpa3EnterpriseSecurityTypeByConnectionInfo() throws Exception {
10955         // Create a WifiConfiguration with WPA2 enterprise and WPA3 enterprise security params
10956         WifiConfiguration config = spy(WifiConfigurationTestUtil.createWpa2Wpa3EnterpriseNetwork());
10957         config.networkId = FRAMEWORK_NETWORK_ID;
10958 
10959         SecurityParams wpa3EnterpriseParams =
10960                 config.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
10961         assertNotNull(wpa3EnterpriseParams);
10962         // Trigger connection with security params as WPA3 enterprise where PMF is mandatory
10963         config.getNetworkSelectionStatus().setLastUsedSecurityParams(wpa3EnterpriseParams);
10964         setupAndStartConnectSequence(config);
10965         validateSuccessfulConnectSequence(config);
10966 
10967         // WifiInfo is not updated yet.
10968         assertEquals(WifiInfo.SECURITY_TYPE_UNKNOWN, mWifiInfo.getCurrentSecurityType());
10969 
10970         WifiSsid wifiSsid =
10971                 WifiSsid.fromBytes(
10972                         NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(config.SSID)));
10973 
10974         BitSet akm = new BitSet();
10975         akm.set(WifiConfiguration.KeyMgmt.WPA_EAP_SHA256);
10976         // Send network connection event with WPA_EAP_SHA256 AKM
10977         mCmi.sendMessage(
10978                 WifiMonitor.NETWORK_CONNECTION_EVENT,
10979                 new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, akm));
10980         mLooper.dispatchAll();
10981         // WifiInfo is updated with WPA3-Enterprise security type derived from the AKM sent in
10982         // network connection event and the PMF settings used in connection.
10983         assertEquals(
10984                 WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, mWifiInfo.getCurrentSecurityType());
10985     }
10986 
10987     @Test
testEnableTdls()10988     public void testEnableTdls() throws Exception {
10989         connect();
10990         when(mWifiNative.getMaxSupportedConcurrentTdlsSessions(WIFI_IFACE_NAME)).thenReturn(1);
10991         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME))
10992                 .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_TDLS));
10993         when(mWifiNative.startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR), anyBoolean()))
10994                 .thenReturn(true);
10995         assertEquals(1, mCmi.getMaxSupportedConcurrentTdlsSessions());
10996         assertTrue(mCmi.isTdlsOperationCurrentlyAvailable());
10997         assertTrue(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, true));
10998         assertEquals(1, mCmi.getNumberOfEnabledTdlsSessions());
10999         verify(mWifiNative).startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR),
11000                 eq(true));
11001         assertFalse(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, true));
11002         assertTrue(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, false));
11003         verify(mWifiNative).startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR),
11004                 eq(false));
11005         assertEquals(0, mCmi.getNumberOfEnabledTdlsSessions());
11006     }
11007 
11008     /**
11009      * Verify that the frequency will be updated on receiving BSS_FREQUENCY_CHANGED_EVENT event.
11010      */
11011     @Test
testBssFrequencyChangedUpdatesFrequency()11012     public void testBssFrequencyChangedUpdatesFrequency() throws Exception {
11013         connect();
11014         assertEquals(sFreq, mWifiInfo.getFrequency());
11015         mCmi.sendMessage(WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT, sFreq1);
11016         mLooper.dispatchAll();
11017         assertEquals(sFreq1, mWifiInfo.getFrequency());
11018     }
11019 
11020     /**
11021      * Verify that the frequency is updated on roaming even when the scan result doesn't have the
11022      * roamed BSS scan entry.
11023      */
11024     @Test
testFrequencyUpdateOnRoamWithoutScanResultEntry()11025     public void testFrequencyUpdateOnRoamWithoutScanResultEntry() throws Exception {
11026         // Connect to network with |TEST_BSSID_STR|, |sFreq|.
11027         connect();
11028 
11029         // Return null scan detail cache for roaming target.
11030         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
11031                 .thenReturn(mScanDetailCache);
11032         when(mScanDetailCache.getScanDetail(TEST_BSSID_STR1)).thenReturn(null);
11033 
11034         // This simulates the behavior of roaming to network with |TEST_BSSID_STR1|, |sFreq1|.
11035         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated with new frequency.
11036         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
11037                 new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR1, sFreq1,
11038                         SupplicantState.COMPLETED));
11039         mLooper.dispatchAll();
11040 
11041         WifiInfo wifiInfo = mWifiInfo;
11042         assertEquals(sFreq1, wifiInfo.getFrequency());
11043     }
11044 
11045     /**
11046      * Verify that static attributes (channel, state, link id and band) of the affiliated MLO links
11047      * are not changed after signal poll.
11048      */
11049     @Test
testMloLinkAttributesAfterSignalPoll()11050     public void testMloLinkAttributesAfterSignalPoll() throws Exception {
11051         connect();
11052         setScanResultWithMloInfo();
11053 
11054         // Associate to one link only
11055         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE;
11056         WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo();
11057         info.links = new WifiNative.ConnectionMloLink[1];
11058         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
11059                 TEST_AP_MLD_MAC_ADDRESS, Byte.MAX_VALUE, Byte.MAX_VALUE, 2437);
11060         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
11061 
11062         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
11063                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
11064                         SupplicantState.ASSOCIATED));
11065         mLooper.dispatchAll();
11066 
11067         // Verify the link attributes
11068         List<MloLink> links = mWifiInfo.getAffiliatedMloLinks();
11069         assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE);
11070         assertEquals(links.get(0).getBand(), WifiScanner.WIFI_BAND_24_GHZ);
11071         assertEquals(links.get(0).getChannel(), TEST_CHANNEL);
11072         assertEquals(links.get(0).getLinkId(), TEST_MLO_LINK_ID);
11073         assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_UNASSOCIATED);
11074         assertEquals(links.get(1).getBand(), WifiScanner.WIFI_BAND_5_GHZ);
11075         assertEquals(links.get(1).getChannel(), TEST_CHANNEL_1);
11076         assertEquals(links.get(1).getLinkId(), TEST_MLO_LINK_ID_1);
11077 
11078         // Signal poll for associated link only
11079         final long startMillis = 1_500_000_000_100L;
11080         WifiLinkLayerStats llStats = new WifiLinkLayerStats();
11081         llStats.txmpdu_be = 1000;
11082         llStats.rxmpdu_bk = 2000;
11083         WifiSignalPollResults signalPollResults = new WifiSignalPollResults();
11084         signalPollResults.addEntry(TEST_MLO_LINK_ID, -42, 65, 54, sFreq);
11085         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
11086                 createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS));
11087         when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats);
11088         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
11089         when(mClock.getWallClockMillis()).thenReturn(startMillis + 0);
11090         mCmi.enableRssiPolling(true);
11091         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
11092         mLooper.dispatchAll();
11093 
11094         // Make sure static link attributes has not changed
11095         links = mWifiInfo.getAffiliatedMloLinks();
11096         assertEquals(links.get(0).getState(), MloLink.MLO_LINK_STATE_ACTIVE);
11097         assertEquals(links.get(0).getBand(), WifiScanner.WIFI_BAND_24_GHZ);
11098         assertEquals(links.get(0).getChannel(), TEST_CHANNEL);
11099         assertEquals(links.get(0).getLinkId(), TEST_MLO_LINK_ID);
11100         assertEquals(links.get(1).getState(), MloLink.MLO_LINK_STATE_UNASSOCIATED);
11101         assertEquals(links.get(1).getBand(), WifiScanner.WIFI_BAND_5_GHZ);
11102         assertEquals(links.get(1).getChannel(), TEST_CHANNEL_1);
11103         assertEquals(links.get(1).getLinkId(), TEST_MLO_LINK_ID_1);
11104 
11105         // Make sure the dynamic attributes (Tx link speed, Rx link speed and RSSI) are matching
11106         // with poll results for associated links.
11107         assertEquals(65, links.get(0).getTxLinkSpeedMbps());
11108         assertEquals(54, links.get(0).getRxLinkSpeedMbps());
11109         assertEquals(-42, links.get(0).getRssi());
11110 
11111         // Make sure the RSSI is matching with scan cache for un-associated links
11112         assertEquals(TEST_RSSI, links.get(1).getRssi());
11113 
11114         // Send signal poll for un-associated link
11115         signalPollResults = new WifiSignalPollResults();
11116         signalPollResults.addEntry(TEST_MLO_LINK_ID_1, -42, 65, 54, sFreq);
11117         when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults);
11118         mCmi.enableRssiPolling(true);
11119         mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1);
11120         mLooper.dispatchAll();
11121         links = mWifiInfo.getAffiliatedMloLinks();
11122 
11123         // Make sure the RSSI is matching with scan result for associated link
11124         assertEquals(TEST_RSSI, links.get(0).getRssi());
11125 
11126     }
11127 
11128     /**
11129      * Verify that during DHCP process, 1. If P2P is in disabled state, clientModeImpl doesn't send
11130      * a message to block P2P discovery. 2. If P2P is not in disabled state, clientModeImpl sends a
11131      * message to block P2P discovery. 3. On DHCP completion, clientModeImpl sends a message to
11132      * unblock P2P discovery.
11133      */
11134     @Test
testP2pBlockDiscoveryDuringDhcp()11135     public void testP2pBlockDiscoveryDuringDhcp() throws Exception {
11136         initializeAndAddNetworkAndVerifySuccess();
11137 
11138         startConnectSuccess();
11139 
11140         mCmi.sendMessage(
11141                 WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
11142                 0,
11143                 0,
11144                 new StateChangeResult(
11145                         0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq, SupplicantState.ASSOCIATED));
11146         mLooper.dispatchAll();
11147 
11148         mCmi.sendMessage(
11149                 WifiMonitor.NETWORK_CONNECTION_EVENT,
11150                 new NetworkConnectionEventInfo(0, TEST_WIFI_SSID, TEST_BSSID_STR, false, null));
11151         mLooper.dispatchAll();
11152         verify(mWifiBlocklistMonitor).handleBssidConnectionSuccess(TEST_BSSID_STR, TEST_SSID);
11153 
11154         mCmi.sendMessage(
11155                 WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
11156                 0,
11157                 0,
11158                 new StateChangeResult(
11159                         0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq, SupplicantState.COMPLETED));
11160         mLooper.dispatchAll();
11161 
11162         assertEquals("L3ProvisioningState", getCurrentState().getName());
11163 
11164         when(mWifiP2pConnection.isConnected()).thenReturn(true);
11165         when(mWifiP2pConnection.isP2pInDisabledState()).thenReturn(true);
11166 
11167         mIpClientCallback.onPreDhcpAction();
11168         mLooper.dispatchAll();
11169         verify(mWifiP2pConnection, never()).sendMessage(anyInt(), anyInt(), anyInt());
11170         verify(mIpClient).completedPreDhcpAction();
11171 
11172         when(mWifiP2pConnection.isConnected()).thenReturn(true);
11173         when(mWifiP2pConnection.isP2pInDisabledState()).thenReturn(false);
11174 
11175         mIpClientCallback.onPreDhcpAction();
11176         mLooper.dispatchAll();
11177         verify(mWifiP2pConnection)
11178                 .sendMessage(
11179                         eq(WifiP2pServiceImpl.BLOCK_DISCOVERY),
11180                         eq(WifiP2pServiceImpl.ENABLED),
11181                         eq(CMD_PRE_DHCP_ACTION_COMPLETE));
11182         verify(mIpClient).completedPreDhcpAction();
11183 
11184         mIpClientCallback.onPostDhcpAction();
11185         mLooper.dispatchAll();
11186         verify(mWifiP2pConnection)
11187                 .sendMessage(
11188                         eq(WifiP2pServiceImpl.BLOCK_DISCOVERY), eq(WifiP2pServiceImpl.DISABLED));
11189     }
11190 
11191     /**
11192      * Verify that MLO link will be updated on receiving BSS_FREQUENCY_CHANGED_EVENT event.
11193      */
11194     @Test
testBssFrequencyChangedUpdatesMloLink()11195     public void testBssFrequencyChangedUpdatesMloLink() throws Exception {
11196         connect();
11197         mLooper.dispatchAll();
11198 
11199         mConnectionCapabilities.wifiStandard = ScanResult.WIFI_STANDARD_11BE;
11200         WifiNative.ConnectionMloLinksInfo info = new WifiNative.ConnectionMloLinksInfo();
11201         info.links = new WifiNative.ConnectionMloLink[2];
11202         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
11203                 TEST_AP_MLD_MAC_ADDRESS, Byte.MIN_VALUE, Byte.MAX_VALUE, TEST_MLO_LINK_FREQ);
11204         info.links[1] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID_1, TEST_MLO_LINK_ADDR_1,
11205                 TEST_AP_MLD_MAC_ADDRESS, Byte.MAX_VALUE, Byte.MIN_VALUE, TEST_MLO_LINK_FREQ_1);
11206         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
11207         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
11208                 new StateChangeResult(FRAMEWORK_NETWORK_ID, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq,
11209                         SupplicantState.ASSOCIATED));
11210         mLooper.dispatchAll();
11211         assertEquals(mWifiInfo.getAssociatedMloLinks().size(),
11212                 mWifiInfo.getAffiliatedMloLinks().size());
11213 
11214         info.links[0] = new WifiNative.ConnectionMloLink(TEST_MLO_LINK_ID, TEST_MLO_LINK_ADDR,
11215                 TEST_AP_MLD_MAC_ADDRESS, Byte.MIN_VALUE, Byte.MAX_VALUE, 6215);
11216         when(mWifiNative.getConnectionMloLinksInfo(WIFI_IFACE_NAME)).thenReturn(info);
11217         mCmi.sendMessage(WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT, 6215);
11218         mLooper.dispatchAll();
11219         List<MloLink> links = mWifiInfo.getAffiliatedMloLinks();
11220         assertEquals(53, links.get(0).getChannel());
11221         assertEquals(WifiScanner.WIFI_BAND_6_GHZ, links.get(0).getBand());
11222     }
11223 
11224     /**
11225      * Verify that we disconnect Wi-Fi 7 is toggled.
11226      */
11227     @Test
verifyDisconnectOnTogglingWifi7()11228     public void verifyDisconnectOnTogglingWifi7() throws Exception {
11229         connect();
11230 
11231         WifiConfiguration oldConfig = new WifiConfiguration(mConnectedNetwork);
11232         mConnectedNetwork.setWifi7Enabled(false);
11233 
11234         for (WifiConfigManager.OnNetworkUpdateListener listener : mConfigUpdateListenerCaptor
11235                 .getAllValues()) {
11236             listener.onNetworkUpdated(mConnectedNetwork, oldConfig, false);
11237         }
11238         mLooper.dispatchAll();
11239         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
11240         verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT),
11241                 eq(StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED));
11242     }
11243 
testDhcpHostnameSetting( boolean configEnabled, @WifiManager.SendDhcpHostnameRestriction int restriction, int security, int expectedHostnameSetting)11244     private void testDhcpHostnameSetting(
11245             boolean configEnabled,
11246             @WifiManager.SendDhcpHostnameRestriction int restriction,
11247             int security,
11248             int expectedHostnameSetting) throws Exception {
11249         if (!SdkLevel.isAtLeastV()) {
11250             expectedHostnameSetting = IIpClient.HOSTNAME_SETTING_UNSET;
11251         }
11252         when(mWifiGlobals.getSendDhcpHostnameRestriction()).thenReturn(restriction);
11253         mConnectedNetwork.setSecurityParams(security);
11254         mConnectedNetwork.setSendDhcpHostnameEnabled(configEnabled);
11255         connect();
11256 
11257         verify(mIpClient).startProvisioning(mProvisioningConfigurationCaptor.capture());
11258         assertEquals(expectedHostnameSetting,
11259                 mProvisioningConfigurationCaptor.getValue().hostnameSetting);
11260     }
11261 
11262     @Test
testSendDhcpHostnameEnabled()11263     public void testSendDhcpHostnameEnabled() throws Exception {
11264         testDhcpHostnameSetting(true, 0, SECURITY_TYPE_OPEN, IIpClient.HOSTNAME_SETTING_SEND);
11265     }
11266 
11267     @Test
testSendDhcpHostnameDisabled()11268     public void testSendDhcpHostnameDisabled() throws Exception {
11269         testDhcpHostnameSetting(false, 0,
11270                 SECURITY_TYPE_OPEN, IIpClient.HOSTNAME_SETTING_DO_NOT_SEND);
11271     }
11272 
11273     @Test
testSendDhcpHostnameEnabledWithOpenRestriction()11274     public void testSendDhcpHostnameEnabledWithOpenRestriction() throws Exception {
11275         testDhcpHostnameSetting(true, WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN,
11276                 SECURITY_TYPE_OPEN, IIpClient.HOSTNAME_SETTING_DO_NOT_SEND);
11277     }
11278 
11279     @Test
testSendDhcpHostnameEnabledWithOpenRestrictionOwe()11280     public void testSendDhcpHostnameEnabledWithOpenRestrictionOwe() throws Exception {
11281         testDhcpHostnameSetting(true, WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_OPEN,
11282                 SECURITY_TYPE_OWE, IIpClient.HOSTNAME_SETTING_DO_NOT_SEND);
11283     }
11284 
11285     @Test
testSendDhcpHostnameEnabledWithSecureRestriction()11286     public void testSendDhcpHostnameEnabledWithSecureRestriction() throws Exception {
11287         testDhcpHostnameSetting(true, WifiManager.FLAG_SEND_DHCP_HOSTNAME_RESTRICTION_SECURE,
11288                 SECURITY_TYPE_PSK, IIpClient.HOSTNAME_SETTING_DO_NOT_SEND);
11289     }
11290 
11291     /**
11292      * Verify that the connection failure due to expired certificate status code is captured in the
11293      * connection result metrics failure specific status code.
11294      */
11295     @Test
testConnectionFailureDueToExpiredCertificateStatusCode()11296     public void testConnectionFailureDueToExpiredCertificateStatusCode() throws Exception {
11297         initializeAndAddNetworkAndVerifySuccess();
11298 
11299         startConnectSuccess();
11300 
11301         mCmi.sendMessage(WifiMonitor.AUXILIARY_SUPPLICANT_EVENT,
11302                 new SupplicantEventInfo(7,  MacAddress.fromString(TEST_BSSID_STR),
11303                         "TLS: Certificate verification failed"
11304                                 + ClientModeImpl.X509_CERTIFICATE_EXPIRED_ERROR_STRING));
11305 
11306         mCmi.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
11307                 new AuthenticationFailureEventInfo(TEST_SSID, MacAddress.fromString(TEST_BSSID_STR),
11308                         WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1));
11309         mLooper.dispatchAll();
11310 
11311         verify(mWifiMetrics).endConnectionEvent(
11312                 any(), eq(WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE),
11313                 eq(WifiMetricsProto.ConnectionEvent.HLF_NONE),
11314                 eq(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE),
11315                 anyInt(), eq(ClientModeImpl.EAP_FAILURE_CODE_CERTIFICATE_EXPIRED));
11316     }
11317 
11318     /**
11319      * Verify that the Sae H2E Feature is set even though config_wifiSaeH2eSupported
11320      * is not enabled through overlay.
11321      */
11322     @Test
testSaeH2eSetEvenThoughConfigForSaeH2eIsNotTrue()11323     public void testSaeH2eSetEvenThoughConfigForSaeH2eIsNotTrue() throws Exception {
11324         when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(3)).thenReturn(true);
11325         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(
11326                 createCapabilityBitset(WifiManager.WIFI_FEATURE_WPA3_SAE));
11327         initializeCmi();
11328         if (SdkLevel.isAtLeastV()) {
11329             verify(mWifiGlobals).enableWpa3SaeH2eSupport();
11330         } else {
11331             verify(mWifiGlobals, never()).enableWpa3SaeH2eSupport();
11332         }
11333     }
11334 
11335     @Test
testBlockNetwork()11336     public void testBlockNetwork() throws Exception {
11337         connect();
11338         BlockingOption option = new BlockingOption.Builder(100)
11339                 .setBlockingBssidOnly(true).build();
11340         mCmi.blockNetwork(option);
11341         verify(mWifiBlocklistMonitor).blockBssidForDurationMs(eq(TEST_BSSID_STR), any(),
11342                 eq(100 * 1000L), eq(REASON_APP_DISALLOW), eq(0));
11343         verify(mWifiBlocklistMonitor).updateAndGetBssidBlocklistForSsids(any());
11344     }
11345 }
11346