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