• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi;
18 
19 import static android.net.util.KeepalivePacketDataUtil.parseTcpKeepalivePacketData;
20 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE;
21 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT;
22 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
23 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_UNWANTED_LOW_RSSI;
24 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA256;
25 import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384;
26 import static android.net.wifi.WifiManager.WIFI_FEATURE_TDLS;
27 import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
28 
29 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY;
30 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
31 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
32 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED;
33 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
34 import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS;
35 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS;
36 import static com.android.server.wifi.proto.WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED;
37 
38 import android.annotation.IntDef;
39 import android.annotation.NonNull;
40 import android.annotation.Nullable;
41 import android.annotation.SuppressLint;
42 import android.app.ActivityManager;
43 import android.app.BroadcastOptions;
44 import android.app.admin.SecurityLog;
45 import android.content.BroadcastReceiver;
46 import android.content.Context;
47 import android.content.Intent;
48 import android.content.IntentFilter;
49 import android.net.CaptivePortalData;
50 import android.net.ConnectivityManager;
51 import android.net.DhcpResultsParcelable;
52 import android.net.InvalidPacketException;
53 import android.net.IpConfiguration;
54 import android.net.KeepalivePacketData;
55 import android.net.Layer2PacketParcelable;
56 import android.net.LinkProperties;
57 import android.net.MacAddress;
58 import android.net.NattKeepalivePacketData;
59 import android.net.Network;
60 import android.net.NetworkAgent;
61 import android.net.NetworkAgentConfig;
62 import android.net.NetworkCapabilities;
63 import android.net.NetworkInfo;
64 import android.net.NetworkInfo.DetailedState;
65 import android.net.RouteInfo;
66 import android.net.SocketKeepalive;
67 import android.net.StaticIpConfiguration;
68 import android.net.TcpKeepalivePacketData;
69 import android.net.TcpKeepalivePacketDataParcelable;
70 import android.net.Uri;
71 import android.net.ip.IIpClient;
72 import android.net.ip.IpClientCallbacks;
73 import android.net.ip.IpClientManager;
74 import android.net.networkstack.aidl.dhcp.DhcpOption;
75 import android.net.networkstack.aidl.ip.ReachabilityLossInfoParcelable;
76 import android.net.networkstack.aidl.ip.ReachabilityLossReason;
77 import android.net.shared.Layer2Information;
78 import android.net.shared.ProvisioningConfiguration;
79 import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
80 import android.net.vcn.VcnManager;
81 import android.net.vcn.VcnNetworkPolicyResult;
82 import android.net.wifi.IWifiConnectedNetworkScorer;
83 import android.net.wifi.MloLink;
84 import android.net.wifi.ScanResult;
85 import android.net.wifi.SecurityParams;
86 import android.net.wifi.SupplicantState;
87 import android.net.wifi.WifiAnnotations.WifiStandard;
88 import android.net.wifi.WifiConfiguration;
89 import android.net.wifi.WifiContext;
90 import android.net.wifi.WifiEnterpriseConfig;
91 import android.net.wifi.WifiInfo;
92 import android.net.wifi.WifiManager;
93 import android.net.wifi.WifiManager.DeviceMobilityState;
94 import android.net.wifi.WifiNetworkAgentSpecifier;
95 import android.net.wifi.WifiNetworkSpecifier;
96 import android.net.wifi.WifiSsid;
97 import android.net.wifi.hotspot2.IProvisioningCallback;
98 import android.net.wifi.hotspot2.OsuProvider;
99 import android.net.wifi.nl80211.DeviceWiphyCapabilities;
100 import android.net.wifi.util.ScanResultUtil;
101 import android.os.BatteryStatsManager;
102 import android.os.Build;
103 import android.os.Bundle;
104 import android.os.ConditionVariable;
105 import android.os.IBinder;
106 import android.os.Looper;
107 import android.os.Message;
108 import android.os.Messenger;
109 import android.os.PowerManager;
110 import android.os.Process;
111 import android.os.UserHandle;
112 import android.os.WorkSource;
113 import android.provider.Settings;
114 import android.system.OsConstants;
115 import android.telephony.SubscriptionManager;
116 import android.telephony.TelephonyManager;
117 import android.text.TextUtils;
118 import android.util.ArraySet;
119 import android.util.Log;
120 import android.util.Pair;
121 import android.util.Range;
122 
123 import androidx.annotation.RequiresApi;
124 
125 import com.android.internal.annotations.VisibleForTesting;
126 import com.android.internal.util.IState;
127 import com.android.internal.util.Protocol;
128 import com.android.internal.util.State;
129 import com.android.internal.util.StateMachine;
130 import com.android.modules.utils.HandlerExecutor;
131 import com.android.modules.utils.build.SdkLevel;
132 import com.android.net.module.util.Inet4AddressUtils;
133 import com.android.net.module.util.MacAddressUtils;
134 import com.android.net.module.util.NetUtils;
135 import com.android.server.wifi.ActiveModeManager.ClientRole;
136 import com.android.server.wifi.MboOceController.BtmFrameData;
137 import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyRequest;
138 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceReasonCode;
139 import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceStatusCode;
140 import com.android.server.wifi.SupplicantStaIfaceHal.SupplicantEventCode;
141 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthRequestData;
142 import com.android.server.wifi.WifiCarrierInfoManager.SimAuthResponseData;
143 import com.android.server.wifi.WifiNative.RxFateReport;
144 import com.android.server.wifi.WifiNative.TxFateReport;
145 import com.android.server.wifi.hotspot2.AnqpEvent;
146 import com.android.server.wifi.hotspot2.IconEvent;
147 import com.android.server.wifi.hotspot2.NetworkDetail;
148 import com.android.server.wifi.hotspot2.PasspointManager;
149 import com.android.server.wifi.hotspot2.WnmData;
150 import com.android.server.wifi.p2p.WifiP2pServiceImpl;
151 import com.android.server.wifi.proto.WifiStatsLog;
152 import com.android.server.wifi.proto.nano.WifiMetricsProto;
153 import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent;
154 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent;
155 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
156 import com.android.server.wifi.util.ActionListenerWrapper;
157 import com.android.server.wifi.util.InformationElementUtil;
158 import com.android.server.wifi.util.NativeUtil;
159 import com.android.server.wifi.util.RssiUtil;
160 import com.android.server.wifi.util.StateMachineObituary;
161 import com.android.server.wifi.util.WifiPermissionsUtil;
162 import com.android.wifi.resources.R;
163 
164 import java.io.BufferedReader;
165 import java.io.FileDescriptor;
166 import java.io.FileNotFoundException;
167 import java.io.IOException;
168 import java.io.PrintWriter;
169 import java.lang.annotation.Retention;
170 import java.lang.annotation.RetentionPolicy;
171 import java.net.Inet4Address;
172 import java.net.Inet6Address;
173 import java.net.InetAddress;
174 import java.net.URL;
175 import java.time.Duration;
176 import java.util.ArrayList;
177 import java.util.Arrays;
178 import java.util.Collections;
179 import java.util.List;
180 import java.util.Map;
181 import java.util.Objects;
182 import java.util.Set;
183 import java.util.stream.Collectors;
184 
185 /**
186  * Implementation of ClientMode.  Event handling for Client mode logic is done here,
187  * and all changes in connectivity state are initiated here.
188  *
189  * Note: No external modules should be calling into {@link ClientModeImpl}. Please plumb it via
190  * {@link ClientModeManager} until b/160014176 is fixed.
191  */
192 public class ClientModeImpl extends StateMachine implements ClientMode {
193     private static final String NETWORKTYPE = "WIFI";
194     @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE_LOW_MEMORY = 200;
195     @VisibleForTesting public static final short NUM_LOG_RECS_VERBOSE = 3000;
196 
197     private static final String TAG = "WifiClientModeImpl";
198 
199     private static final int IPCLIENT_STARTUP_TIMEOUT_MS = 2_000;
200     private static final int IPCLIENT_SHUTDOWN_TIMEOUT_MS = 60_000; // 60 seconds
201     private static final int NETWORK_AGENT_TEARDOWN_DELAY_MS = 5_000; // Max teardown delay.
202     @VisibleForTesting public static final long CONNECTING_WATCHDOG_TIMEOUT_MS = 30_000; // 30 secs.
203     @VisibleForTesting
204     public static final String ARP_TABLE_PATH = "/proc/net/arp";
205 
206     private boolean mVerboseLoggingEnabled = false;
207 
208     /**
209      * Log with error attribute
210      *
211      * @param s is string log
212      */
213     @Override
loge(String s)214     protected void loge(String s) {
215         Log.e(getTag(), s);
216     }
217     @Override
logd(String s)218     protected void logd(String s) {
219         Log.d(getTag(), s);
220     }
221     @Override
log(String s)222     protected void log(String s) {
223         Log.d(getTag(), s);
224     }
225     private final WifiContext mContext;
226     private final WifiMetrics mWifiMetrics;
227     private final WifiMonitor mWifiMonitor;
228     private final WifiNative mWifiNative;
229     private final WifiPermissionsUtil mWifiPermissionsUtil;
230     private final WifiConfigManager mWifiConfigManager;
231     private final WifiConnectivityManager mWifiConnectivityManager;
232     private final WifiBlocklistMonitor mWifiBlocklistMonitor;
233     private final WifiDiagnostics mWifiDiagnostics;
234     private final Clock mClock;
235     private final WifiScoreCard mWifiScoreCard;
236     private final WifiHealthMonitor mWifiHealthMonitor;
237     private final WifiScoreReport mWifiScoreReport;
238     private final WifiTrafficPoller mWifiTrafficPoller;
239     private final PasspointManager mPasspointManager;
240     private final WifiDataStall mWifiDataStall;
241     private final RssiMonitor mRssiMonitor;
242     private final LinkProbeManager mLinkProbeManager;
243     private final MboOceController mMboOceController;
244     private final McastLockManagerFilterController mMcastLockManagerFilterController;
245     private final ActivityManager mActivityManager;
246     private final FrameworkFacade mFacade;
247     private final WifiStateTracker mWifiStateTracker;
248     private final WrongPasswordNotifier mWrongPasswordNotifier;
249     private final EapFailureNotifier mEapFailureNotifier;
250     private final SimRequiredNotifier mSimRequiredNotifier;
251     private final ConnectionFailureNotifier mConnectionFailureNotifier;
252     private final WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
253     private final ThroughputPredictor mThroughputPredictor;
254     private final DeviceConfigFacade mDeviceConfigFacade;
255     private final ScoringParams mScoringParams;
256     private final WifiThreadRunner mWifiThreadRunner;
257     private final ScanRequestProxy mScanRequestProxy;
258     private final WifiLastResortWatchdog mWifiLastResortWatchdog;
259     private final WakeupController mWakeupController;
260     private final WifiLockManager mWifiLockManager;
261     private final WifiP2pConnection mWifiP2pConnection;
262     private final WifiGlobals mWifiGlobals;
263     private final ClientModeManagerBroadcastQueue mBroadcastQueue;
264     private final TelephonyManager mTelephonyManager;
265     private final WifiSettingsConfigStore mSettingsConfigStore;
266     private final long mId;
267 
268     private boolean mScreenOn = false;
269 
270     private final String mInterfaceName;
271     private final ConcreteClientModeManager mClientModeManager;
272 
273     private final WifiNotificationManager mNotificationManager;
274     private final QosPolicyRequestHandler mQosPolicyRequestHandler;
275 
276     private boolean mFailedToResetMacAddress = false;
277     private int mLastSignalLevel = -1;
278     private int mLastTxKbps = -1;
279     private int mLastRxKbps = -1;
280     private int mLastScanRssi = WifiInfo.INVALID_RSSI;
281     private String mLastBssid;
282     // TODO (b/162942761): Ensure this is reset when mTargetNetworkId is set.
283     private int mLastNetworkId; // The network Id we successfully joined
284     // The subId used by WifiConfiguration with SIM credential which was connected successfully
285     private int mLastSubId;
286     private String mLastSimBasedConnectionCarrierName;
287     private URL mTermsAndConditionsUrl; // Indicates that the Passpoint network is captive
288     @Nullable
289     private WifiNative.ConnectionCapabilities mLastConnectionCapabilities;
290     private int mPowerSaveDisableRequests = 0; // mask based on @PowerSaveClientType
291     private boolean mIsUserSelected = false;
292     private boolean mCurrentConnectionDetectedCaptivePortal;
293 
getTag()294     private String getTag() {
295         return TAG + "[" + mId + ":" + (mInterfaceName == null ? "unknown" : mInterfaceName) + "]";
296     }
297 
298     private boolean mEnableRssiPolling = false;
299     private int mRssiPollToken = 0;
300 
301     private PowerManager.WakeLock mSuspendWakeLock;
302 
303     /**
304      * Value to set in wpa_supplicant "bssid" field when we don't want to restrict connection to
305      * a specific AP.
306      */
307     public static final String SUPPLICANT_BSSID_ANY = "any";
308 
309     /**
310      * The link properties of the wifi interface.
311      * Do not modify this directly; use updateLinkProperties instead.
312      */
313     private LinkProperties mLinkProperties;
314 
315     private final Object mDhcpResultsParcelableLock = new Object();
316     @NonNull
317     private DhcpResultsParcelable mDhcpResultsParcelable = new DhcpResultsParcelable();
318 
319     // NOTE: Do not return to clients - see getConnectionInfo()
320     private final ExtendedWifiInfo mWifiInfo;
321     // TODO : remove this member. It should be possible to only call sendNetworkChangeBroadcast when
322     // the state actually changed, and to deduce the state of the agent from the state of the
323     // machine when generating the NetworkInfo for the broadcast.
324     private DetailedState mNetworkAgentState;
325     private final SupplicantStateTracker mSupplicantStateTracker;
326 
327     // Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when
328     // wifi connects or fails to connect
329     private boolean mIsAutoRoaming = false;
330 
331     // Indicates that driver is attempting to allowlist roaming, set true on allowlist roam BSSID
332     // associated, set false when wifi connects or fails to connect
333     private boolean mIsLinkedNetworkRoaming = false;
334 
335     // Roaming failure count
336     private int mRoamFailCount = 0;
337 
338     // This is the BSSID we are trying to associate to, it can be set to SUPPLICANT_BSSID_ANY
339     // if we havent selected a BSSID for joining.
340     private String mTargetBssid = SUPPLICANT_BSSID_ANY;
341     private int mTargetBand = ScanResult.UNSPECIFIED;
342     // This one is used to track the current target network ID. This is used for error
343     // handling during connection setup since many error message from supplicant does not report
344     // SSID. Once connected, it will be set to invalid
345     // TODO (b/162942761): Ensure this is reset when mLastNetworkId is set.
346     private int mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
347     private WifiConfiguration mTargetWifiConfiguration = null;
348     @Nullable private VcnManager mVcnManager = null;
349 
350     // This is is used to track the number of TDLS peers enabled in driver via enableTdls()
351     private Set<String> mEnabledTdlsPeers = new ArraySet<>();
352 
353     /**
354      * Method to clear {@link #mTargetBssid} and reset the current connected network's
355      * bssid in wpa_supplicant after a roam/connect attempt.
356      */
clearTargetBssid(String dbg)357     public boolean clearTargetBssid(String dbg) {
358         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
359         if (config == null) {
360             return false;
361         }
362         String bssid = SUPPLICANT_BSSID_ANY;
363         if (config.BSSID != null) {
364             bssid = config.BSSID;
365             if (mVerboseLoggingEnabled) {
366                 Log.d(getTag(), "force BSSID to " + bssid + "due to config");
367             }
368         }
369         if (mVerboseLoggingEnabled) {
370             logd(dbg + " clearTargetBssid " + bssid + " key=" + config.getProfileKey());
371         }
372         mTargetBssid = bssid;
373         return mWifiNative.setNetworkBSSID(mInterfaceName, bssid);
374     }
375 
376     /**
377      * Set Config's default BSSID (for association purpose) and {@link #mTargetBssid}
378      * @param config config need set BSSID
379      * @param bssid  default BSSID to assocaite with when connect to this network
380      * @return false -- does not change the current default BSSID of the configure
381      *         true -- change the  current default BSSID of the configur
382      */
setTargetBssid(WifiConfiguration config, String bssid)383     private boolean setTargetBssid(WifiConfiguration config, String bssid) {
384         if (config == null || bssid == null) {
385             return false;
386         }
387         if (config.BSSID != null) {
388             bssid = config.BSSID;
389             if (mVerboseLoggingEnabled) {
390                 Log.d(getTag(), "force BSSID to " + bssid + "due to config");
391             }
392         }
393         if (mVerboseLoggingEnabled) {
394             Log.d(getTag(), "setTargetBssid set to " + bssid + " key="
395                     + config.getProfileKey());
396         }
397         mTargetBssid = bssid;
398         config.getNetworkSelectionStatus().setNetworkSelectionBSSID(bssid);
399         return true;
400     }
401 
402     private volatile IpClientManager mIpClient;
403     private IpClientCallbacksImpl mIpClientCallbacks;
404 
405     private final WifiNetworkFactory mNetworkFactory;
406     private final UntrustedWifiNetworkFactory mUntrustedNetworkFactory;
407     private final OemWifiNetworkFactory mOemWifiNetworkFactory;
408     private final RestrictedWifiNetworkFactory mRestrictedWifiNetworkFactory;
409     @VisibleForTesting
410     InsecureEapNetworkHandler mInsecureEapNetworkHandler;
411     boolean mLeafCertSent;
412     @VisibleForTesting
413     InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks
414             mInsecureEapNetworkHandlerCallbacksImpl;
415     private final MultiInternetManager mMultiInternetManager;
416 
417     @VisibleForTesting
418     @Nullable
419     WifiNetworkAgent mNetworkAgent;
420 
421 
422     // Used to filter out requests we couldn't possibly satisfy.
423     private final NetworkCapabilities mNetworkCapabilitiesFilter;
424 
425     /* The base for wifi message types */
426     static final int BASE = Protocol.BASE_WIFI;
427 
428     /* BT connection state changed, e.g., connected/disconnected */
429     static final int CMD_BLUETOOTH_CONNECTION_STATE_CHANGE              = BASE + 31;
430 
431     /* Supplicant commands after driver start*/
432     /* Disconnect from a network */
433     static final int CMD_DISCONNECT                                     = BASE + 73;
434     /* Reconnect to a network */
435     static final int CMD_RECONNECT                                      = BASE + 74;
436     /* Reassociate to a network */
437     static final int CMD_REASSOCIATE                                    = BASE + 75;
438 
439     /* Enables RSSI poll */
440     static final int CMD_ENABLE_RSSI_POLL                               = BASE + 82;
441     /* RSSI poll */
442     static final int CMD_RSSI_POLL                                      = BASE + 83;
443     /** Runs RSSI poll once */
444     static final int CMD_ONESHOT_RSSI_POLL                              = BASE + 84;
445     /* Enable suspend mode optimizations in the driver */
446     static final int CMD_SET_SUSPEND_OPT_ENABLED                        = BASE + 86;
447 
448     /**
449      * Watchdog for protecting against b/16823537
450      * Leave time for 4-way handshake to succeed
451      */
452     static final int ROAM_GUARD_TIMER_MSEC = 15000;
453 
454     int mRoamWatchdogCount = 0;
455     /* Roam state watchdog */
456     static final int CMD_ROAM_WATCHDOG_TIMER                            = BASE + 94;
457     /* Screen change intent handling */
458     static final int CMD_SCREEN_STATE_CHANGED                           = BASE + 95;
459 
460     /* Disconnecting state watchdog */
461     static final int CMD_CONNECTING_WATCHDOG_TIMER                      = BASE + 96;
462 
463     /* SIM is removed; reset any cached data for it */
464     static final int CMD_RESET_SIM_NETWORKS                             = BASE + 101;
465 
466     /**
467      * Update the OOB Pseudonym which is retrieved from the carrier's entitlement server for
468      * EAP-SIM/AKA/AKA' into supplicant.
469      */
470     static final int CMD_UPDATE_OOB_PSEUDONYM                               = BASE + 102;
471 
472     @Retention(RetentionPolicy.SOURCE)
473     @IntDef(prefix = {"RESET_SIM_REASON_"},
474             value = {
475                     RESET_SIM_REASON_SIM_REMOVED,
476                     RESET_SIM_REASON_SIM_INSERTED,
477                     RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED})
478     @interface ResetSimReason {}
479     static final int RESET_SIM_REASON_SIM_REMOVED              = 0;
480     static final int RESET_SIM_REASON_SIM_INSERTED             = 1;
481     static final int RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED = 2;
482 
483     /** Connecting watchdog timeout counter */
484     private int mConnectingWatchdogCount = 0;
485 
486     /* We now have a valid IP configuration. */
487     static final int CMD_IP_CONFIGURATION_SUCCESSFUL                    = BASE + 138;
488     /* We no longer have a valid IP configuration. */
489     static final int CMD_IP_CONFIGURATION_LOST                          = BASE + 139;
490     /* Link configuration (IP address, DNS, ...) changes notified via netlink */
491     static final int CMD_UPDATE_LINKPROPERTIES                          = BASE + 140;
492 
493     static final int CMD_START_CONNECT                                  = BASE + 143;
494 
495     @VisibleForTesting
496     public static final int NETWORK_STATUS_UNWANTED_DISCONNECT         = 0;
497     private static final int NETWORK_STATUS_UNWANTED_VALIDATION_FAILED  = 1;
498     @VisibleForTesting
499     public static final int NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN   = 2;
500 
501     static final int CMD_UNWANTED_NETWORK                               = BASE + 144;
502 
503     static final int CMD_START_ROAM                                     = BASE + 145;
504 
505     static final int CMD_NETWORK_STATUS                                 = BASE + 148;
506 
507     /* A layer 3 neighbor on the Wi-Fi link became unreachable. */
508     static final int CMD_IP_REACHABILITY_LOST                           = BASE + 149;
509 
510     static final int CMD_IP_REACHABILITY_FAILURE                        = BASE + 150;
511 
512     static final int CMD_ACCEPT_UNVALIDATED                             = BASE + 153;
513 
514     /* used to offload sending IP packet */
515     static final int CMD_START_IP_PACKET_OFFLOAD                        = BASE + 160;
516 
517     /* used to stop offload sending IP packet */
518     static final int CMD_STOP_IP_PACKET_OFFLOAD                         = BASE + 161;
519 
520     /* Used to time out the creation of an IpClient instance. */
521     static final int CMD_IPCLIENT_STARTUP_TIMEOUT                       = BASE + 165;
522 
523     /**
524      * Used to handle messages bounced between ClientModeImpl and IpClient.
525      */
526     static final int CMD_IPV4_PROVISIONING_SUCCESS                      = BASE + 200;
527     static final int CMD_IPV4_PROVISIONING_FAILURE                      = BASE + 201;
528 
529     /* Push a new APF program to the HAL */
530     static final int CMD_INSTALL_PACKET_FILTER                          = BASE + 202;
531 
532     /* Enable/disable fallback packet filtering */
533     static final int CMD_SET_FALLBACK_PACKET_FILTERING                  = BASE + 203;
534 
535     /* Enable/disable Neighbor Discovery offload functionality. */
536     static final int CMD_CONFIG_ND_OFFLOAD                              = BASE + 204;
537 
538     /* Read the APF program & data buffer */
539     static final int CMD_READ_PACKET_FILTER                             = BASE + 208;
540 
541     /** Used to add packet filter to apf. */
542     static final int CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF = BASE + 209;
543 
544     /** Used to remove packet filter from apf. */
545     static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF = BASE + 210;
546 
547     /**
548      * Set maximum acceptable DTIM multiplier to hardware driver. Any multiplier larger than the
549      * maximum value must not be accepted, it will cause packet loss higher than what the system
550      * can accept, which will cause unexpected behavior for apps, and may interrupt the network
551      * connection.
552      */
553     static final int CMD_SET_MAX_DTIM_MULTIPLIER = BASE + 211;
554 
555     @VisibleForTesting
556     static final int CMD_PRE_DHCP_ACTION                                = BASE + 255;
557     private static final int CMD_PRE_DHCP_ACTION_COMPLETE               = BASE + 256;
558     private static final int CMD_POST_DHCP_ACTION                       = BASE + 257;
559 
560     private static final int CMD_CONNECT_NETWORK                        = BASE + 258;
561     private static final int CMD_SAVE_NETWORK                           = BASE + 259;
562 
563     /* Start connection to FILS AP*/
564     static final int CMD_START_FILS_CONNECTION                          = BASE + 262;
565 
566     static final int CMD_IPCLIENT_CREATED                               = BASE + 300;
567 
568     @VisibleForTesting
569     static final int CMD_ACCEPT_EAP_SERVER_CERTIFICATE                  = BASE + 301;
570 
571     @VisibleForTesting
572     static final int CMD_REJECT_EAP_INSECURE_CONNECTION                 = BASE + 302;
573 
574     /* Tracks if suspend optimizations need to be disabled by DHCP,
575      * screen or due to high perf mode.
576      * When any of them needs to disable it, we keep the suspend optimizations
577      * disabled
578      */
579     private int mSuspendOptNeedsDisabled = 0;
580 
581     private static final int SUSPEND_DUE_TO_DHCP = 1;
582     private static final int SUSPEND_DUE_TO_HIGH_PERF = 1 << 1;
583     private static final int SUSPEND_DUE_TO_SCREEN = 1 << 2;
584 
585     /** @see #isRecentlySelectedByTheUser */
586     @VisibleForTesting
587     public static final int LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS = 30 * 1000;
588 
589     /* Tracks if user has enabled Connected Mac Randomization through settings */
590 
591     int mRunningBeaconCount = 0;
592 
593     /* Parent state where connections are allowed */
594     private State mConnectableState;
595     /* Connecting/Connected to an access point */
596     private State mConnectingOrConnectedState;
597     /* Connecting to an access point */
598     private State mL2ConnectingState;
599     /* Connected at 802.11 (L2) level */
600     private State mL2ConnectedState;
601     /* Waiting for IpClient recreation completes */
602     private State mWaitBeforeL3ProvisioningState;
603     /* fetching IP after connection to access point (assoc+auth complete) */
604     private State mL3ProvisioningState;
605     /* Connected with IP addr */
606     private State mL3ConnectedState;
607     /* Roaming */
608     private State mRoamingState;
609     /* Network is not connected, supplicant assoc+auth is not complete */
610     private State mDisconnectedState;
611 
612     /*
613      * FILS connection related variables.
614      */
615     /* To indicate to IpClient whether HLP IEs were included or not in assoc request */
616     private boolean mSentHLPs = false;
617     /* Tracks IpClient start state until (FILS_)NETWORK_CONNECTION_EVENT event */
618     private boolean mIpClientWithPreConnection = false;
619 
620     /**
621      * Work source to use to blame usage on the WiFi service
622      */
623     public static final WorkSource WIFI_WORK_SOURCE = new WorkSource(Process.WIFI_UID);
624 
625     private final BatteryStatsManager mBatteryStatsManager;
626 
627     private final WifiCarrierInfoManager mWifiCarrierInfoManager;
628 
629     private final WifiPseudonymManager mWifiPseudonymManager;
630 
631     private final OnNetworkUpdateListener mOnNetworkUpdateListener;
632 
633     private final OnCarrierOffloadDisabledListener mOnCarrierOffloadDisabledListener;
634 
635     private final ClientModeImplMonitor mCmiMonitor;
636 
637     private final WifiNetworkSelector mWifiNetworkSelector;
638 
639     private final WifiInjector mWifiInjector;
640 
641     // Permanently disable a network due to no internet if the estimated probability of having
642     // internet is less than this value.
643     @VisibleForTesting
644     public static final int PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK = 60;
645     // Disable a network permanently due to wrong password even if the network had successfully
646     // connected before wrong password failure on this network reached this threshold.
647     public static final int THRESHOLD_TO_PERM_WRONG_PASSWORD = 3;
648 
649     // Maximum duration to continue to log Wifi usability stats after a data stall is triggered.
650     @VisibleForTesting
651     public static final long DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS = 30 * 1000;
652     private long mDataStallTriggerTimeMs = -1;
653     private int mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN;
654 
655     @Nullable
656     private StateMachineObituary mObituary = null;
657 
658     @Nullable
659     private WifiVcnNetworkPolicyChangeListener mVcnPolicyChangeListener;
660 
661     /** NETWORK_NOT_FOUND_EVENT event counter */
662     private int mNetworkNotFoundEventCount = 0;
663 
664     private final WifiPseudonymManager.PseudonymUpdatingListener mPseudonymUpdatingListener;
665 
666     private final ApplicationQosPolicyRequestHandler mApplicationQosPolicyRequestHandler;
667 
668 
669     /** Note that this constructor will also start() the StateMachine. */
ClientModeImpl( @onNull WifiContext context, @NonNull WifiMetrics wifiMetrics, @NonNull Clock clock, @NonNull WifiScoreCard wifiScoreCard, @NonNull WifiStateTracker wifiStateTracker, @NonNull WifiPermissionsUtil wifiPermissionsUtil, @NonNull WifiConfigManager wifiConfigManager, @NonNull PasspointManager passpointManager, @NonNull WifiMonitor wifiMonitor, @NonNull WifiDiagnostics wifiDiagnostics, @NonNull WifiDataStall wifiDataStall, @NonNull ScoringParams scoringParams, @NonNull WifiThreadRunner wifiThreadRunner, @NonNull WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager, @NonNull WifiHealthMonitor wifiHealthMonitor, @NonNull ThroughputPredictor throughputPredictor, @NonNull DeviceConfigFacade deviceConfigFacade, @NonNull ScanRequestProxy scanRequestProxy, @NonNull ExtendedWifiInfo wifiInfo, @NonNull WifiConnectivityManager wifiConnectivityManager, @NonNull WifiBlocklistMonitor wifiBlocklistMonitor, @NonNull ConnectionFailureNotifier connectionFailureNotifier, @NonNull NetworkCapabilities networkCapabilitiesFilter, @NonNull WifiNetworkFactory networkFactory, @NonNull UntrustedWifiNetworkFactory untrustedWifiNetworkFactory, @NonNull OemWifiNetworkFactory oemPaidWifiNetworkFactory, @NonNull RestrictedWifiNetworkFactory restrictedWifiNetworkFactory, @NonNull MultiInternetManager multiInternetManager, @NonNull WifiLastResortWatchdog wifiLastResortWatchdog, @NonNull WakeupController wakeupController, @NonNull WifiLockManager wifiLockManager, @NonNull FrameworkFacade facade, @NonNull Looper looper, @NonNull WifiNative wifiNative, @NonNull WrongPasswordNotifier wrongPasswordNotifier, @NonNull WifiTrafficPoller wifiTrafficPoller, @NonNull LinkProbeManager linkProbeManager, long id, @NonNull BatteryStatsManager batteryStatsManager, @NonNull SupplicantStateTracker supplicantStateTracker, @NonNull MboOceController mboOceController, @NonNull WifiCarrierInfoManager wifiCarrierInfoManager, @NonNull WifiPseudonymManager wifiPseudonymManager, @NonNull EapFailureNotifier eapFailureNotifier, @NonNull SimRequiredNotifier simRequiredNotifier, @NonNull WifiScoreReport wifiScoreReport, @NonNull WifiP2pConnection wifiP2pConnection, @NonNull WifiGlobals wifiGlobals, @NonNull String ifaceName, @NonNull ConcreteClientModeManager clientModeManager, @NonNull ClientModeImplMonitor cmiMonitor, @NonNull ClientModeManagerBroadcastQueue broadcastQueue, @NonNull WifiNetworkSelector wifiNetworkSelector, @NonNull TelephonyManager telephonyManager, @NonNull WifiInjector wifiInjector, @NonNull WifiSettingsConfigStore settingsConfigStore, boolean verboseLoggingEnabled, @NonNull WifiNotificationManager wifiNotificationManager)670     public ClientModeImpl(
671             @NonNull WifiContext context,
672             @NonNull WifiMetrics wifiMetrics,
673             @NonNull Clock clock,
674             @NonNull WifiScoreCard wifiScoreCard,
675             @NonNull WifiStateTracker wifiStateTracker,
676             @NonNull WifiPermissionsUtil wifiPermissionsUtil,
677             @NonNull WifiConfigManager wifiConfigManager,
678             @NonNull PasspointManager passpointManager,
679             @NonNull WifiMonitor wifiMonitor,
680             @NonNull WifiDiagnostics wifiDiagnostics,
681             @NonNull WifiDataStall wifiDataStall,
682             @NonNull ScoringParams scoringParams,
683             @NonNull WifiThreadRunner wifiThreadRunner,
684             @NonNull WifiNetworkSuggestionsManager wifiNetworkSuggestionsManager,
685             @NonNull WifiHealthMonitor wifiHealthMonitor,
686             @NonNull ThroughputPredictor throughputPredictor,
687             @NonNull DeviceConfigFacade deviceConfigFacade,
688             @NonNull ScanRequestProxy scanRequestProxy,
689             @NonNull ExtendedWifiInfo wifiInfo,
690             @NonNull WifiConnectivityManager wifiConnectivityManager,
691             @NonNull WifiBlocklistMonitor wifiBlocklistMonitor,
692             @NonNull ConnectionFailureNotifier connectionFailureNotifier,
693             @NonNull NetworkCapabilities networkCapabilitiesFilter,
694             @NonNull WifiNetworkFactory networkFactory,
695             @NonNull UntrustedWifiNetworkFactory untrustedWifiNetworkFactory,
696             @NonNull OemWifiNetworkFactory oemPaidWifiNetworkFactory,
697             @NonNull RestrictedWifiNetworkFactory restrictedWifiNetworkFactory,
698             @NonNull MultiInternetManager multiInternetManager,
699             @NonNull WifiLastResortWatchdog wifiLastResortWatchdog,
700             @NonNull WakeupController wakeupController,
701             @NonNull WifiLockManager wifiLockManager,
702             @NonNull FrameworkFacade facade,
703             @NonNull Looper looper,
704             @NonNull WifiNative wifiNative,
705             @NonNull WrongPasswordNotifier wrongPasswordNotifier,
706             @NonNull WifiTrafficPoller wifiTrafficPoller,
707             @NonNull LinkProbeManager linkProbeManager,
708             long id,
709             @NonNull BatteryStatsManager batteryStatsManager,
710             @NonNull SupplicantStateTracker supplicantStateTracker,
711             @NonNull MboOceController mboOceController,
712             @NonNull WifiCarrierInfoManager wifiCarrierInfoManager,
713             @NonNull WifiPseudonymManager wifiPseudonymManager,
714             @NonNull EapFailureNotifier eapFailureNotifier,
715             @NonNull SimRequiredNotifier simRequiredNotifier,
716             @NonNull WifiScoreReport wifiScoreReport,
717             @NonNull WifiP2pConnection wifiP2pConnection,
718             @NonNull WifiGlobals wifiGlobals,
719             @NonNull String ifaceName,
720             @NonNull ConcreteClientModeManager clientModeManager,
721             @NonNull ClientModeImplMonitor cmiMonitor,
722             @NonNull ClientModeManagerBroadcastQueue broadcastQueue,
723             @NonNull WifiNetworkSelector wifiNetworkSelector,
724             @NonNull TelephonyManager telephonyManager,
725             @NonNull WifiInjector wifiInjector,
726             @NonNull WifiSettingsConfigStore settingsConfigStore,
727             boolean verboseLoggingEnabled,
728             @NonNull WifiNotificationManager wifiNotificationManager) {
729         super(TAG, looper);
730         mWifiMetrics = wifiMetrics;
731         mClock = clock;
732         mWifiScoreCard = wifiScoreCard;
733         mContext = context;
734         mFacade = facade;
735         mWifiNative = wifiNative;
736         mWrongPasswordNotifier = wrongPasswordNotifier;
737         mId = id;
738         mEapFailureNotifier = eapFailureNotifier;
739         mSimRequiredNotifier = simRequiredNotifier;
740         mWifiTrafficPoller = wifiTrafficPoller;
741         mLinkProbeManager = linkProbeManager;
742         mMboOceController = mboOceController;
743         mWifiCarrierInfoManager = wifiCarrierInfoManager;
744         mWifiPseudonymManager = wifiPseudonymManager;
745         mBroadcastQueue = broadcastQueue;
746         mNetworkAgentState = DetailedState.DISCONNECTED;
747 
748         mBatteryStatsManager = batteryStatsManager;
749         mWifiStateTracker = wifiStateTracker;
750 
751         mWifiPermissionsUtil = wifiPermissionsUtil;
752         mWifiConfigManager = wifiConfigManager;
753 
754         mPasspointManager = passpointManager;
755 
756         mWifiMonitor = wifiMonitor;
757         mWifiDiagnostics = wifiDiagnostics;
758         mWifiDataStall = wifiDataStall;
759         mThroughputPredictor = throughputPredictor;
760         mDeviceConfigFacade = deviceConfigFacade;
761 
762         mWifiInfo = wifiInfo;
763         mSupplicantStateTracker = supplicantStateTracker;
764         mWifiConnectivityManager = wifiConnectivityManager;
765         mWifiBlocklistMonitor = wifiBlocklistMonitor;
766         mConnectionFailureNotifier = connectionFailureNotifier;
767 
768         mLinkProperties = new LinkProperties();
769         mMcastLockManagerFilterController = new McastLockManagerFilterController();
770         mActivityManager = context.getSystemService(ActivityManager.class);
771 
772         mLastBssid = null;
773         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
774         mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
775         mLastSimBasedConnectionCarrierName = null;
776         mLastSignalLevel = -1;
777 
778         mScoringParams = scoringParams;
779         mWifiThreadRunner = wifiThreadRunner;
780         mScanRequestProxy = scanRequestProxy;
781         mWifiScoreReport = wifiScoreReport;
782 
783         mNetworkCapabilitiesFilter = networkCapabilitiesFilter;
784         mNetworkFactory = networkFactory;
785 
786         mUntrustedNetworkFactory = untrustedWifiNetworkFactory;
787         mOemWifiNetworkFactory = oemPaidWifiNetworkFactory;
788         mRestrictedWifiNetworkFactory = restrictedWifiNetworkFactory;
789         mMultiInternetManager = multiInternetManager;
790 
791         mWifiLastResortWatchdog = wifiLastResortWatchdog;
792         mWakeupController = wakeupController;
793         mWifiLockManager = wifiLockManager;
794 
795         mWifiNetworkSuggestionsManager = wifiNetworkSuggestionsManager;
796         mWifiHealthMonitor = wifiHealthMonitor;
797         mWifiP2pConnection = wifiP2pConnection;
798         mWifiGlobals = wifiGlobals;
799 
800         mInterfaceName = ifaceName;
801         mClientModeManager = clientModeManager;
802         mCmiMonitor = cmiMonitor;
803         mTelephonyManager = telephonyManager;
804         mSettingsConfigStore = settingsConfigStore;
805         updateInterfaceCapabilities();
806 
807         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
808 
809         mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
810         mSuspendWakeLock.setReferenceCounted(false);
811 
812         mOnNetworkUpdateListener = new OnNetworkUpdateListener();
813         mWifiConfigManager.addOnNetworkUpdateListener(mOnNetworkUpdateListener);
814 
815         mOnCarrierOffloadDisabledListener = new OnCarrierOffloadDisabledListener();
816         mWifiCarrierInfoManager.addOnCarrierOffloadDisabledListener(
817                 mOnCarrierOffloadDisabledListener);
818 
819         mWifiNetworkSelector = wifiNetworkSelector;
820         mWifiInjector = wifiInjector;
821         mQosPolicyRequestHandler = new QosPolicyRequestHandler(mInterfaceName, mWifiNative, this,
822                 mWifiInjector.getWifiHandlerThread());
823 
824         mRssiMonitor = new RssiMonitor(mWifiGlobals, mWifiThreadRunner, mWifiInfo, mWifiNative,
825                 mInterfaceName,
826                 () -> {
827                     updateCapabilities();
828                     updateCurrentConnectionInfo();
829                 },
830                 mDeviceConfigFacade);
831 
832         enableVerboseLogging(verboseLoggingEnabled);
833 
834         mNotificationManager = wifiNotificationManager;
835         mInsecureEapNetworkHandlerCallbacksImpl =
836                 new InsecureEapNetworkHandler.InsecureEapNetworkHandlerCallbacks() {
837                 @Override
838                 public void onAccept(String ssid, int networkId) {
839                     log("Accept Root CA cert for " + ssid);
840                     sendMessage(CMD_ACCEPT_EAP_SERVER_CERTIFICATE, networkId);
841                 }
842 
843                 @Override
844                 public void onReject(String ssid, boolean disconnectRequired) {
845                     log("Reject Root CA cert for " + ssid);
846                     sendMessage(CMD_REJECT_EAP_INSECURE_CONNECTION,
847                             WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_REJECTED_BY_USER,
848                             disconnectRequired ? 1 : 0, ssid);
849                 }
850 
851                 @Override
852                 public void onError(String ssid) {
853                     log("Insecure EAP network error for " + ssid);
854                     sendMessage(CMD_REJECT_EAP_INSECURE_CONNECTION,
855                             WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE,
856                             0, ssid);
857                 }};
858         mInsecureEapNetworkHandler = new InsecureEapNetworkHandler(
859                 mContext,
860                 mWifiConfigManager,
861                 mWifiNative,
862                 mFacade,
863                 mNotificationManager,
864                 mWifiInjector.getWifiDialogManager(),
865                 isTrustOnFirstUseSupported(),
866                 mWifiGlobals.isInsecureEnterpriseConfigurationAllowed(),
867                 mInsecureEapNetworkHandlerCallbacksImpl,
868                 mInterfaceName,
869                 getHandler());
870 
871         mPseudonymUpdatingListener = this::updatePseudonymFromOob;
872         mApplicationQosPolicyRequestHandler = mWifiInjector.getApplicationQosPolicyRequestHandler();
873 
874         final int threshold =  mContext.getResources().getInteger(
875                 R.integer.config_wifiConfigurationWifiRunnerThresholdInMs);
876         mConnectableState = new ConnectableState(threshold);
877         mConnectingOrConnectedState = new ConnectingOrConnectedState(threshold);
878         mL2ConnectingState = new L2ConnectingState(threshold);
879         mL2ConnectedState = new L2ConnectedState(threshold);
880         mWaitBeforeL3ProvisioningState = new WaitBeforeL3ProvisioningState(threshold);
881         mL3ProvisioningState = new L3ProvisioningState(threshold);
882         mL3ConnectedState = new L3ConnectedState(threshold);
883         mRoamingState = new RoamingState(threshold);
884         mDisconnectedState = new DisconnectedState(threshold);
885 
886         addState(mConnectableState); {
887             addState(mConnectingOrConnectedState, mConnectableState); {
888                 addState(mL2ConnectingState, mConnectingOrConnectedState);
889                 addState(mL2ConnectedState, mConnectingOrConnectedState); {
890                     addState(mWaitBeforeL3ProvisioningState, mL2ConnectedState);
891                     addState(mL3ProvisioningState, mL2ConnectedState);
892                     addState(mL3ConnectedState, mL2ConnectedState);
893                     addState(mRoamingState, mL2ConnectedState);
894                 }
895             }
896             addState(mDisconnectedState, mConnectableState);
897         }
898 
899         setInitialState(mDisconnectedState);
900 
901         setLogOnlyTransitions(false);
902 
903         // Start the StateMachine
904         start();
905 
906         // update with initial role for ConcreteClientModeManager
907         onRoleChanged();
908         // Update current connection wifiInfo
909         updateCurrentConnectionInfo();
910     }
911 
912     private static final int[] WIFI_MONITOR_EVENTS = {
913             WifiMonitor.TARGET_BSSID_EVENT,
914             WifiMonitor.ASSOCIATED_BSSID_EVENT,
915             WifiMonitor.ANQP_DONE_EVENT,
916             WifiMonitor.ASSOCIATION_REJECTION_EVENT,
917             WifiMonitor.AUTHENTICATION_FAILURE_EVENT,
918             WifiMonitor.GAS_QUERY_DONE_EVENT,
919             WifiMonitor.GAS_QUERY_START_EVENT,
920             WifiMonitor.HS20_REMEDIATION_EVENT,
921             WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT,
922             WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT,
923             WifiMonitor.NETWORK_CONNECTION_EVENT,
924             WifiMonitor.NETWORK_DISCONNECTION_EVENT,
925             WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
926             WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT,
927             WifiMonitor.SUP_REQUEST_IDENTITY,
928             WifiMonitor.SUP_REQUEST_SIM_AUTH,
929             WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE,
930             WifiMonitor.TRANSITION_DISABLE_INDICATION,
931             WifiMonitor.NETWORK_NOT_FOUND_EVENT,
932             WifiMonitor.TOFU_CERTIFICATE_EVENT,
933             WifiMonitor.AUXILIARY_SUPPLICANT_EVENT,
934             WifiMonitor.QOS_POLICY_RESET_EVENT,
935             WifiMonitor.QOS_POLICY_REQUEST_EVENT,
936             WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT,
937     };
938 
registerForWifiMonitorEvents()939     private void registerForWifiMonitorEvents()  {
940         for (int event : WIFI_MONITOR_EVENTS) {
941             mWifiMonitor.registerHandler(mInterfaceName, event, getHandler());
942         }
943 
944         mWifiMetrics.registerForWifiMonitorEvents(mInterfaceName);
945         mWifiLastResortWatchdog.registerForWifiMonitorEvents(mInterfaceName);
946     }
947 
deregisterForWifiMonitorEvents()948     private void deregisterForWifiMonitorEvents()  {
949         for (int event : WIFI_MONITOR_EVENTS) {
950             mWifiMonitor.deregisterHandler(mInterfaceName, event, getHandler());
951         }
952 
953         mWifiMetrics.deregisterForWifiMonitorEvents(mInterfaceName);
954         mWifiLastResortWatchdog.deregisterForWifiMonitorEvents(mInterfaceName);
955     }
956 
isValidBssid(String bssidStr)957     private static boolean isValidBssid(String bssidStr) {
958         try {
959             MacAddress bssid = MacAddress.fromString(bssidStr);
960             return !Objects.equals(bssid, WifiManager.ALL_ZEROS_MAC_ADDRESS);
961         } catch (IllegalArgumentException e) {
962             return false;
963         }
964     }
965 
setMulticastFilter(boolean enabled)966     private void setMulticastFilter(boolean enabled) {
967         if (mIpClient != null) {
968             mIpClient.setMulticastFilter(enabled);
969         }
970     }
971 
972     /*
973      * Log wifi event to SecurityLog if the event occurred on a managed network.
974      */
logEventIfManagedNetwork(@ullable WifiConfiguration config, @SupplicantEventCode int eventCode, MacAddress bssid, String reasonString)975     private void logEventIfManagedNetwork(@Nullable WifiConfiguration config,
976             @SupplicantEventCode int eventCode, MacAddress bssid, String reasonString) {
977         if (config == null || !mWifiPermissionsUtil
978                 .isAdmin(config.creatorUid, config.creatorName)) {
979             return;
980         }
981 
982         if (SdkLevel.isAtLeastT()) {
983             int numRedactedOctets = mContext.getResources()
984                     .getInteger(R.integer.config_wifiNumMaskedBssidOctetsInSecurityLog);
985             String redactedBssid = ScanResultUtil.redactBssid(bssid, numRedactedOctets);
986             if (eventCode == SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED) {
987                 SecurityLog.writeEvent(SecurityLog.TAG_WIFI_DISCONNECTION, redactedBssid,
988                         reasonString);
989             } else {
990                 SecurityLog.writeEvent(SecurityLog.TAG_WIFI_CONNECTION, redactedBssid,
991                         SupplicantStaIfaceHal.supplicantEventCodeToString(eventCode), reasonString);
992             }
993         }
994     }
995 
clearQueuedQosMessages()996     protected void clearQueuedQosMessages() {
997         removeMessages(WifiMonitor.QOS_POLICY_RESET_EVENT);
998         removeMessages(WifiMonitor.QOS_POLICY_REQUEST_EVENT);
999     }
1000 
1001     /**
1002      * Class to implement the MulticastLockManager.FilterController callback.
1003      */
1004     class McastLockManagerFilterController implements WifiMulticastLockManager.FilterController {
1005         /**
1006          * Start filtering Multicast v4 packets
1007          */
startFilteringMulticastPackets()1008         public void startFilteringMulticastPackets() {
1009             setMulticastFilter(true);
1010         }
1011 
1012         /**
1013          * Stop filtering Multicast v4 packets
1014          */
stopFilteringMulticastPackets()1015         public void stopFilteringMulticastPackets() {
1016             setMulticastFilter(false);
1017         }
1018     }
1019 
1020     class IpClientCallbacksImpl extends IpClientCallbacks {
1021         private final ConditionVariable mWaitForCreationCv = new ConditionVariable(false);
1022         private final ConditionVariable mWaitForStopCv = new ConditionVariable(false);
1023 
1024         @Override
onIpClientCreated(IIpClient ipClient)1025         public void onIpClientCreated(IIpClient ipClient) {
1026             if (mIpClientCallbacks != this) return;
1027             // IpClient may take a very long time (many minutes) to start at boot time. But after
1028             // that IpClient should start pretty quickly (a few seconds).
1029             // Blocking wait for 5 seconds first (for when the wait is short)
1030             // If IpClient is still not ready after blocking wait, async wait (for when wait is
1031             // long). Will drop all connection requests until IpClient is ready. Other requests
1032             // will still be processed.
1033             sendMessageAtFrontOfQueue(CMD_IPCLIENT_CREATED,
1034                     new IpClientManager(ipClient, getName()));
1035             mWaitForCreationCv.open();
1036         }
1037 
1038         @Override
onPreDhcpAction()1039         public void onPreDhcpAction() {
1040             if (mIpClientCallbacks != this) return;
1041             sendMessage(CMD_PRE_DHCP_ACTION);
1042         }
1043 
1044         @Override
onPostDhcpAction()1045         public void onPostDhcpAction() {
1046             if (mIpClientCallbacks != this) return;
1047             sendMessage(CMD_POST_DHCP_ACTION);
1048         }
1049 
1050         @Override
onNewDhcpResults(DhcpResultsParcelable dhcpResults)1051         public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
1052             if (mIpClientCallbacks != this) return;
1053             if (dhcpResults != null) {
1054                 sendMessage(CMD_IPV4_PROVISIONING_SUCCESS, dhcpResults);
1055             } else {
1056                 sendMessage(CMD_IPV4_PROVISIONING_FAILURE);
1057             }
1058         }
1059 
1060         @Override
onProvisioningSuccess(LinkProperties newLp)1061         public void onProvisioningSuccess(LinkProperties newLp) {
1062             if (mIpClientCallbacks != this) return;
1063             addPasspointInfoToLinkProperties(newLp);
1064             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL);
1065             sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
1066             sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);
1067         }
1068 
1069         @Override
onProvisioningFailure(LinkProperties newLp)1070         public void onProvisioningFailure(LinkProperties newLp) {
1071             if (mIpClientCallbacks != this) return;
1072             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_CONFIGURATION_LOST);
1073             sendMessage(CMD_IP_CONFIGURATION_LOST);
1074         }
1075 
1076         @Override
onLinkPropertiesChange(LinkProperties newLp)1077         public void onLinkPropertiesChange(LinkProperties newLp) {
1078             if (mIpClientCallbacks != this) return;
1079             addPasspointInfoToLinkProperties(newLp);
1080             sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
1081         }
1082 
1083         @Override
onReachabilityLost(String logMsg)1084         public void onReachabilityLost(String logMsg) {
1085             if (mIpClientCallbacks != this) return;
1086             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST);
1087             sendMessage(CMD_IP_REACHABILITY_LOST, logMsg);
1088         }
1089 
1090         @Override
onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo)1091         public void onReachabilityFailure(ReachabilityLossInfoParcelable lossInfo) {
1092             if (mIpClientCallbacks != this) return;
1093             sendMessage(CMD_IP_REACHABILITY_FAILURE, lossInfo);
1094         }
1095 
1096         @Override
installPacketFilter(byte[] filter)1097         public void installPacketFilter(byte[] filter) {
1098             if (mIpClientCallbacks != this) return;
1099             sendMessage(CMD_INSTALL_PACKET_FILTER, filter);
1100         }
1101 
1102         @Override
startReadPacketFilter()1103         public void startReadPacketFilter() {
1104             if (mIpClientCallbacks != this) return;
1105             sendMessage(CMD_READ_PACKET_FILTER);
1106         }
1107 
1108         @Override
setFallbackMulticastFilter(boolean enabled)1109         public void setFallbackMulticastFilter(boolean enabled) {
1110             if (mIpClientCallbacks != this) return;
1111             sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled);
1112         }
1113 
1114         @Override
setNeighborDiscoveryOffload(boolean enabled)1115         public void setNeighborDiscoveryOffload(boolean enabled) {
1116             if (mIpClientCallbacks != this) return;
1117             sendMessage(CMD_CONFIG_ND_OFFLOAD, (enabled ? 1 : 0));
1118         }
1119 
1120         @Override
onPreconnectionStart(List<Layer2PacketParcelable> packets)1121         public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
1122             if (mIpClientCallbacks != this) return;
1123             sendMessage(CMD_START_FILS_CONNECTION, 0, 0, packets);
1124         }
1125 
1126         @Override
setMaxDtimMultiplier(int multiplier)1127         public void setMaxDtimMultiplier(int multiplier) {
1128             if (mIpClientCallbacks != this) return;
1129             sendMessage(CMD_SET_MAX_DTIM_MULTIPLIER, multiplier);
1130         }
1131 
1132         @Override
onQuit()1133         public void onQuit() {
1134             if (mIpClientCallbacks != this) return;
1135             mWaitForStopCv.open();
1136         }
1137 
awaitCreation()1138         boolean awaitCreation() {
1139             return mWaitForCreationCv.block(IPCLIENT_STARTUP_TIMEOUT_MS);
1140         }
1141 
awaitShutdown()1142         boolean awaitShutdown() {
1143             return mWaitForStopCv.block(IPCLIENT_SHUTDOWN_TIMEOUT_MS);
1144         }
1145     }
1146 
stopIpClient()1147     private void stopIpClient() {
1148         if (mVerboseLoggingEnabled) {
1149             Log.v(getTag(), "stopIpClient IpClientWithPreConnection: "
1150                     + mIpClientWithPreConnection);
1151         }
1152         if (mIpClient != null) {
1153             if (mIpClientWithPreConnection) {
1154                 mIpClient.notifyPreconnectionComplete(false);
1155             }
1156             mIpClient.stop();
1157         }
1158         mIpClientWithPreConnection = false;
1159         mSentHLPs = false;
1160     }
1161 
stopDhcpSetup()1162     private void stopDhcpSetup() {
1163         /* Restore power save and suspend optimizations */
1164         handlePostDhcpSetup();
1165         stopIpClient();
1166     }
1167 
convertToInternalDhcpOptions(List<android.net.DhcpOption> options)1168     private List<DhcpOption> convertToInternalDhcpOptions(List<android.net.DhcpOption> options) {
1169         List<DhcpOption> internalOptions = new ArrayList<DhcpOption>();
1170         for (android.net.DhcpOption option : options) {
1171             DhcpOption internalOption = new DhcpOption();
1172             internalOption.type = option.getType();
1173             if (option.getValue() != null) {
1174                 byte[] value = option.getValue();
1175                 internalOption.value = Arrays.copyOf(value, value.length);
1176             }
1177             internalOptions.add(internalOption);
1178         }
1179         return internalOptions;
1180     }
1181 
1182     /**
1183      * Listener for config manager network config related events.
1184      * TODO (b/117601161) : Move some of the existing handling in WifiConnectivityManager's listener
1185      * for the same events.
1186      */
1187     private class OnNetworkUpdateListener implements
1188             WifiConfigManager.OnNetworkUpdateListener {
1189         @Override
onNetworkRemoved(WifiConfiguration config)1190         public void onNetworkRemoved(WifiConfiguration config) {
1191             // The current connected or connecting network has been removed, trigger a disconnect.
1192             if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
1193                 // Disconnect and let autojoin reselect a new network
1194                 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED);
1195                 // Log disconnection here, since the network config won't exist when the
1196                 // disconnection event is received.
1197                 String bssid = getConnectedBssidInternal();
1198                 logEventIfManagedNetwork(config,
1199                         SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED,
1200                         bssid != null ? MacAddress.fromString(bssid) : null,
1201                         "Network was removed");
1202             } else {
1203                 WifiConfiguration currentConfig = getConnectedWifiConfiguration();
1204                 if (currentConfig != null && currentConfig.isLinked(config)) {
1205                     logi("current network linked config removed, update allowlist networks");
1206                     updateLinkedNetworks(currentConfig);
1207                 }
1208             }
1209             mWifiNative.removeNetworkCachedData(config.networkId);
1210         }
1211 
1212         @Override
onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig)1213         public void onNetworkUpdated(WifiConfiguration newConfig, WifiConfiguration oldConfig) {
1214 
1215             if (WifiConfigurationUtil.hasCredentialChanged(oldConfig, newConfig)) {
1216                 // Clear invalid cached data.
1217                 mWifiNative.removeNetworkCachedData(oldConfig.networkId);
1218                 mWifiBlocklistMonitor.handleNetworkRemoved(newConfig.SSID);
1219             }
1220 
1221             if (newConfig.networkId != mLastNetworkId)  {
1222                 // nothing to do.
1223                 return;
1224             }
1225             boolean isMetered = WifiConfiguration.isMetered(newConfig, mWifiInfo);
1226             boolean wasMetered = WifiConfiguration.isMetered(oldConfig, mWifiInfo);
1227             // Check if user/app change meteredOverride or trusted for connected network.
1228             if (isMetered == wasMetered
1229                     && (!SdkLevel.isAtLeastT() || newConfig.trusted == oldConfig.trusted)) {
1230                 return;
1231             }
1232 
1233             if (SdkLevel.isAtLeastT()) {
1234                 mWifiInfo.setTrusted(newConfig.trusted);
1235                 if (!newConfig.trusted) {
1236                     Log.w(getTag(), "Network marked untrusted, triggering disconnect");
1237                     sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
1238                     return;
1239                 }
1240             }
1241 
1242             if (isMetered) {
1243                 Log.w(getTag(), "Network marked metered, triggering disconnect");
1244                 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED);
1245                 return;
1246             }
1247 
1248             Log.i(getTag(), "Network marked metered=" + isMetered
1249                     + " trusted=" + newConfig.trusted + ", triggering capabilities update");
1250             updateCapabilities(newConfig);
1251             updateCurrentConnectionInfo();
1252         }
1253 
1254         @Override
onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason)1255         public void onNetworkTemporarilyDisabled(WifiConfiguration config, int disableReason) {
1256             if (disableReason == DISABLED_NO_INTERNET_TEMPORARY) return;
1257             if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
1258                 // Disconnect and let autojoin reselect a new network
1259                 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED);
1260             }
1261 
1262         }
1263 
1264         @Override
onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason)1265         public void onNetworkPermanentlyDisabled(WifiConfiguration config, int disableReason) {
1266             // For DISABLED_NO_INTERNET_PERMANENT we do not need to remove the network
1267             // because supplicant won't be trying to reconnect. If this is due to a
1268             // preventAutomaticReconnect request from ConnectivityService, that service
1269             // will disconnect as appropriate.
1270             if (disableReason == DISABLED_NO_INTERNET_PERMANENT) return;
1271             if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) {
1272                 // Disconnect and let autojoin reselect a new network
1273                 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED);
1274             }
1275         }
1276     }
1277 
1278     private class OnCarrierOffloadDisabledListener implements
1279             WifiCarrierInfoManager.OnCarrierOffloadDisabledListener {
1280 
1281         @Override
onCarrierOffloadDisabled(int subscriptionId, boolean merged)1282         public void onCarrierOffloadDisabled(int subscriptionId, boolean merged) {
1283             int networkId = mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID
1284                     ? mLastNetworkId : mTargetNetworkId;
1285             if (networkId == WifiConfiguration.INVALID_NETWORK_ID) {
1286                 return;
1287             }
1288             WifiConfiguration configuration = mWifiConfigManager.getConfiguredNetwork(networkId);
1289             if (configuration != null && configuration.subscriptionId == subscriptionId
1290                     && configuration.carrierMerged == merged) {
1291                 Log.i(getTag(), "Carrier network offload disabled, triggering disconnect");
1292                 sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED);
1293             }
1294             mWifiConnectivityManager.clearCachedCandidates();
1295         }
1296     }
1297 
1298     /**
1299      * Method to update logging level in wifi service related classes.
1300      *
1301      * @param verbose int logging level to use
1302      */
enableVerboseLogging(boolean verbose)1303     public void enableVerboseLogging(boolean verbose) {
1304         if (verbose) {
1305             mVerboseLoggingEnabled = true;
1306             setLogRecSize(mActivityManager.isLowRamDevice()
1307                     ? NUM_LOG_RECS_VERBOSE_LOW_MEMORY : NUM_LOG_RECS_VERBOSE);
1308         } else {
1309             mVerboseLoggingEnabled = false;
1310             setLogRecSize(mWifiGlobals.getClientModeImplNumLogRecs());
1311         }
1312 
1313         mWifiScoreReport.enableVerboseLogging(mVerboseLoggingEnabled);
1314         mSupplicantStateTracker.enableVerboseLogging(mVerboseLoggingEnabled);
1315         mWifiNative.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseLoggingEnabled);
1316         mQosPolicyRequestHandler.enableVerboseLogging(mVerboseLoggingEnabled);
1317         mRssiMonitor.enableVerboseLogging(mVerboseLoggingEnabled);
1318     }
1319 
1320     /**
1321      * If there is only SAE-only networks with this auto-upgrade type,
1322      * this auto-upgrade SAE type is considered to be added explicitly.
1323      *
1324      * For R, Settings/WifiTrackerLib maps WPA3 SAE to WPA2, so there is
1325      * no chance to add or update a WPA3 SAE configuration to update
1326      * the auto-upgrade flag.
1327      */
updateSaeAutoUpgradeFlagForUserSelectNetwork(int networkId)1328     private void updateSaeAutoUpgradeFlagForUserSelectNetwork(int networkId) {
1329         if (SdkLevel.isAtLeastS()) return;
1330         if (mWifiGlobals.isWpa3SaeUpgradeEnabled()) return;
1331 
1332         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkId);
1333         if (null == config) return;
1334         SecurityParams params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
1335         if (null == params || !params.isAddedByAutoUpgrade()) return;
1336 
1337         if (!mScanRequestProxy.isWpa3PersonalOnlyNetworkInRange(config.SSID)) return;
1338         if (mScanRequestProxy.isWpa2PersonalOnlyNetworkInRange(config.SSID)) return;
1339         if (mScanRequestProxy.isWpa2Wpa3PersonalTransitionNetworkInRange(config.SSID)) return;
1340 
1341         logd("update auto-upgrade flag for SAE");
1342         mWifiConfigManager.updateIsAddedByAutoUpgradeFlag(
1343                 config.networkId, WifiConfiguration.SECURITY_TYPE_SAE, false);
1344     }
1345 
1346     /**
1347      * Given a network ID for connection, check the security parameters for a
1348      * disabled security type.
1349      *
1350      * Allow the connection only when there are APs with the better security
1351      * type (or transition mode), or no APs with the disabled security type.
1352      *
1353      * @param networkIdForConnection indicates the network id for the desired connection.
1354      * @return {@code true} if this connection request should be dropped; {@code false} otherwise.
1355      */
shouldDropConnectionRequest(int networkIdForConnection)1356     private boolean shouldDropConnectionRequest(int networkIdForConnection) {
1357         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(networkIdForConnection);
1358         if (null == config) return false;
1359 
1360         List<ScanResult> scanResults = mScanRequestProxy.getScanResults().stream()
1361                 .filter(r -> TextUtils.equals(config.SSID, r.getWifiSsid().toString()))
1362                 .collect(Collectors.toList());
1363         if (0 == scanResults.size()) return false;
1364 
1365         SecurityParams params;
1366         // Check disabled PSK network.
1367         params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
1368         if (null != params && !params.isEnabled()) {
1369             if (scanResults.stream().anyMatch(r ->
1370                     ScanResultUtil.isScanResultForSaeNetwork(r))) {
1371                 return false;
1372             }
1373             if (!scanResults.stream().anyMatch(r ->
1374                     ScanResultUtil.isScanResultForPskOnlyNetwork(r))) {
1375                 return false;
1376             }
1377             return true;
1378         }
1379         // Check disabled OPEN network.
1380         params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
1381         if (null != params && !params.isEnabled()) {
1382             if (scanResults.stream().anyMatch(r ->
1383                     ScanResultUtil.isScanResultForOweNetwork(r))) {
1384                 return false;
1385             }
1386             if (!scanResults.stream().anyMatch(r ->
1387                     ScanResultUtil.isScanResultForOpenOnlyNetwork(r))) {
1388                 return false;
1389             }
1390             return true;
1391         }
1392         // Check disabled WPA2 Enterprise network.
1393         params = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
1394         if (null != params && !params.isEnabled()) {
1395             if (scanResults.stream().anyMatch(r ->
1396                     ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(r))) {
1397                 return false;
1398             }
1399             if (scanResults.stream().anyMatch(r ->
1400                     ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(r))) {
1401                 return false;
1402             }
1403             if (!scanResults.stream().anyMatch(r ->
1404                     ScanResultUtil.isScanResultForWpa2EnterpriseOnlyNetwork(r))) {
1405                 return false;
1406             }
1407             return true;
1408         }
1409         return false;
1410     }
1411 
1412     /**
1413      * Initiates connection to a network specified by the user/app. This method checks if the
1414      * requesting app holds the NETWORK_SETTINGS permission.
1415      *
1416      * @param netId Id network to initiate connection.
1417      * @param uid UID of the app requesting the connection.
1418      * @param forceReconnect Whether to force a connection even if we're connected to the same
1419      *                       network currently.
1420      * @param packageName package name of the app requesting the connection.
1421      */
connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect, @NonNull String packageName)1422     private void connectToUserSelectNetwork(int netId, int uid, boolean forceReconnect,
1423             @NonNull String packageName) {
1424         if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)
1425                 || mWifiPermissionsUtil.checkNetworkSetupWizardPermission(uid)) {
1426             mIsUserSelected = true;
1427         }
1428         logd("connectToUserSelectNetwork netId " + netId + ", uid " + uid + ", package "
1429                 + packageName + ", forceReconnect = " + forceReconnect + ", isUserSelected = "
1430                 + mIsUserSelected);
1431         updateSaeAutoUpgradeFlagForUserSelectNetwork(netId);
1432         if (!forceReconnect && (mLastNetworkId == netId || mTargetNetworkId == netId)) {
1433             // We're already connecting/connected to the user specified network, don't trigger a
1434             // reconnection unless it was forced.
1435             logi("connectToUserSelectNetwork already connecting/connected=" + netId);
1436         } else if (mIsUserSelected && shouldDropConnectionRequest(netId)) {
1437             logi("connectToUserSelectNetwork this network is disabled by admin.");
1438             WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(netId);
1439             String title = mContext.getString(R.string.wifi_network_disabled_by_admin_title);
1440             String message = mContext.getString(R.string.wifi_network_disabled_by_admin_message,
1441                     config.SSID);
1442             String buttonText = mContext.getString(R.string.wifi_network_disabled_by_admin_button);
1443             mWifiInjector.getWifiDialogManager().createLegacySimpleDialog(
1444                     title, message,
1445                     null /* positiveButtonText */,
1446                     null /* negativeButtonText */,
1447                     buttonText,
1448                     new WifiDialogManager.SimpleDialogCallback() {
1449                         @Override
1450                         public void onPositiveButtonClicked() {
1451                             // Not used.
1452                         }
1453                         @Override
1454                         public void onNegativeButtonClicked() {
1455                             // Not used.
1456                         }
1457                         @Override
1458                         public void onNeutralButtonClicked() {
1459                             // Not used.
1460                         }
1461                         @Override
1462                         public void onCancelled() {
1463                             // Not used.
1464                         }
1465                     }, mWifiThreadRunner).launchDialog();
1466         } else {
1467             mWifiConnectivityManager.prepareForForcedConnection(netId);
1468             if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
1469                 mWifiMetrics.setNominatorForNetwork(netId,
1470                         WifiMetricsProto.ConnectionEvent.NOMINATOR_MANUAL);
1471             }
1472             startConnectToNetwork(netId, uid, SUPPLICANT_BSSID_ANY);
1473         }
1474     }
1475 
1476     /**
1477      * ******************************************************
1478      * Methods exposed for public use
1479      * ******************************************************
1480      */
1481 
1482     /**
1483      * Retrieve a Messenger for the ClientModeImpl Handler
1484      *
1485      * @return Messenger
1486      */
getMessenger()1487     public Messenger getMessenger() {
1488         return new Messenger(getHandler());
1489     }
1490 
1491     // For debugging, keep track of last message status handling
1492     // TODO, find an equivalent mechanism as part of parent class
1493     private static final int MESSAGE_HANDLING_STATUS_PROCESSED = 2;
1494     private static final int MESSAGE_HANDLING_STATUS_OK = 1;
1495     private static final int MESSAGE_HANDLING_STATUS_UNKNOWN = 0;
1496     private static final int MESSAGE_HANDLING_STATUS_REFUSED = -1;
1497     private static final int MESSAGE_HANDLING_STATUS_FAIL = -2;
1498     private static final int MESSAGE_HANDLING_STATUS_OBSOLETE = -3;
1499     private static final int MESSAGE_HANDLING_STATUS_DEFERRED = -4;
1500     private static final int MESSAGE_HANDLING_STATUS_DISCARD = -5;
1501     private static final int MESSAGE_HANDLING_STATUS_LOOPED = -6;
1502     private static final int MESSAGE_HANDLING_STATUS_HANDLING_ERROR = -7;
1503 
1504     private int mMessageHandlingStatus = 0;
1505 
1506     private int mOnTime = 0;
1507     private int mTxTime = 0;
1508     private int mRxTime = 0;
1509 
1510     private int mOnTimeScreenStateChange = 0;
1511     private long mLastOntimeReportTimeStamp = 0;
1512     private long mLastScreenStateChangeTimeStamp = 0;
1513     private int mOnTimeLastReport = 0;
1514     private int mTxTimeLastReport = 0;
1515     private int mRxTimeLastReport = 0;
1516 
1517     private WifiLinkLayerStats mLastLinkLayerStats;
1518     private long mLastLinkLayerStatsUpdate = 0;
1519 
reportOnTime()1520     String reportOnTime() {
1521         long now = mClock.getWallClockMillis();
1522         StringBuilder sb = new StringBuilder();
1523         // Report stats since last report
1524         int on = mOnTime - mOnTimeLastReport;
1525         mOnTimeLastReport = mOnTime;
1526         int tx = mTxTime - mTxTimeLastReport;
1527         mTxTimeLastReport = mTxTime;
1528         int rx = mRxTime - mRxTimeLastReport;
1529         mRxTimeLastReport = mRxTime;
1530         int period = (int) (now - mLastOntimeReportTimeStamp);
1531         mLastOntimeReportTimeStamp = now;
1532         sb.append("[on:" + on + " tx:" + tx + " rx:" + rx + " period:" + period + "]");
1533         // Report stats since Screen State Changed
1534         on = mOnTime - mOnTimeScreenStateChange;
1535         period = (int) (now - mLastScreenStateChangeTimeStamp);
1536         sb.append(" from screen [on:" + on + " period:" + period + "]");
1537         return sb.toString();
1538     }
1539 
1540     /**
1541      * receives changes in the interface up/down events for the interface associated with this
1542      * ClientModeImpl. This is expected to be called from the ClientModeManager running on the
1543      * wifi handler thread.
1544      */
onUpChanged(boolean isUp)1545     public void onUpChanged(boolean isUp) {
1546         if (isUp && mFailedToResetMacAddress) {
1547             // When the firmware does a subsystem restart, wifi will disconnect but we may fail to
1548             // re-randomize the MAC address of the interface since it's undergoing recovery. Thus,
1549             // check every time the interface goes up and re-randomize if the failure was detected.
1550             if (mWifiGlobals.isConnectedMacRandomizationEnabled()) {
1551                 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress(
1552                         mInterfaceName, MacAddressUtils.createRandomUnicastAddress());
1553                 if (mFailedToResetMacAddress) {
1554                     Log.e(getTag(), "Failed to set random MAC address on interface up");
1555                 }
1556             }
1557         }
1558         // No need to handle interface down since it's already handled in the ClientModeManager.
1559     }
1560 
getWifiLinkLayerStats()1561     public WifiLinkLayerStats getWifiLinkLayerStats() {
1562         if (mInterfaceName == null) {
1563             loge("getWifiLinkLayerStats called without an interface");
1564             return null;
1565         }
1566         mLastLinkLayerStatsUpdate = mClock.getWallClockMillis();
1567         WifiLinkLayerStats stats = null;
1568         if (isPrimary()) {
1569             stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName);
1570         } else {
1571             if (mVerboseLoggingEnabled) {
1572                 Log.w(getTag(), "Can't getWifiLinkLayerStats on secondary iface");
1573             }
1574         }
1575         if (stats != null) {
1576             mOnTime = stats.on_time;
1577             mTxTime = stats.tx_time;
1578             mRxTime = stats.rx_time;
1579             mRunningBeaconCount = stats.beacon_rx;
1580             mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate);
1581         } else {
1582             long mTxPkts = mFacade.getTxPackets(mInterfaceName);
1583             long mRxPkts = mFacade.getRxPackets(mInterfaceName);
1584             mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate);
1585         }
1586         mWifiMetrics.incrementWifiLinkLayerUsageStats(mInterfaceName, stats);
1587         updateCurrentConnectionInfo();
1588         return stats;
1589     }
1590 
1591     /**
1592      * Update interface capabilities
1593      * This method is used to update some of interface capabilities defined in overlay
1594      */
updateInterfaceCapabilities()1595     private void updateInterfaceCapabilities() {
1596         DeviceWiphyCapabilities cap = getDeviceWiphyCapabilities();
1597         if (cap != null) {
1598             // Some devices don't have support of 11ax/be indicated by the chip,
1599             // so an override config value is used
1600             if (mContext.getResources().getBoolean(R.bool.config_wifi11beSupportOverride)) {
1601                 cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11BE, true);
1602             }
1603             if (mContext.getResources().getBoolean(R.bool.config_wifi11axSupportOverride)) {
1604                 cap.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, true);
1605             }
1606 
1607             mWifiNative.setDeviceWiphyCapabilities(mInterfaceName, cap);
1608         }
1609     }
1610 
1611     @Override
getDeviceWiphyCapabilities()1612     public DeviceWiphyCapabilities getDeviceWiphyCapabilities() {
1613         return mWifiNative.getDeviceWiphyCapabilities(mInterfaceName);
1614     }
1615 
1616     /**
1617      * Check if a Wi-Fi standard is supported
1618      *
1619      * @param standard A value from {@link ScanResult}'s {@code WIFI_STANDARD_}
1620      * @return {@code true} if standard is supported, {@code false} otherwise.
1621      */
isWifiStandardSupported(@ifiStandard int standard)1622     public boolean isWifiStandardSupported(@WifiStandard int standard) {
1623         return mWifiNative.isWifiStandardSupported(mInterfaceName, standard);
1624     }
1625 
getDstMacForKeepalive(KeepalivePacketData packetData)1626     private byte[] getDstMacForKeepalive(KeepalivePacketData packetData)
1627             throws InvalidPacketException {
1628         try {
1629             InetAddress gateway = NetUtils.selectBestRoute(
1630                     mLinkProperties.getRoutes(), packetData.getDstAddress()).getGateway();
1631             String dstMacStr = macAddressFromRoute(gateway.getHostAddress());
1632             return NativeUtil.macAddressToByteArray(dstMacStr);
1633         } catch (NullPointerException | IllegalArgumentException e) {
1634             throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS);
1635         }
1636     }
1637 
getEtherProtoForKeepalive(KeepalivePacketData packetData)1638     private static int getEtherProtoForKeepalive(KeepalivePacketData packetData)
1639             throws InvalidPacketException {
1640         if (packetData.getDstAddress() instanceof Inet4Address) {
1641             return OsConstants.ETH_P_IP;
1642         } else if (packetData.getDstAddress() instanceof Inet6Address) {
1643             return OsConstants.ETH_P_IPV6;
1644         } else {
1645             throw new InvalidPacketException(InvalidPacketException.ERROR_INVALID_IP_ADDRESS);
1646         }
1647     }
1648 
startWifiIPPacketOffload(int slot, KeepalivePacketData packetData, int intervalSeconds)1649     private int startWifiIPPacketOffload(int slot, KeepalivePacketData packetData,
1650             int intervalSeconds) {
1651         byte[] packet = null;
1652         byte[] dstMac = null;
1653         int proto = 0;
1654 
1655         try {
1656             packet = packetData.getPacket();
1657             dstMac = getDstMacForKeepalive(packetData);
1658             proto = getEtherProtoForKeepalive(packetData);
1659         } catch (InvalidPacketException e) {
1660             return e.getError();
1661         }
1662 
1663         int ret = mWifiNative.startSendingOffloadedPacket(
1664                 mInterfaceName, slot, dstMac, packet, proto, intervalSeconds * 1000);
1665         if (ret != 0) {
1666             loge("startWifiIPPacketOffload(" + slot + ", " + intervalSeconds
1667                     + "): hardware error " + ret);
1668             return SocketKeepalive.ERROR_HARDWARE_ERROR;
1669         } else {
1670             return SocketKeepalive.SUCCESS;
1671         }
1672     }
1673 
stopWifiIPPacketOffload(int slot)1674     private int stopWifiIPPacketOffload(int slot) {
1675         int ret = mWifiNative.stopSendingOffloadedPacket(mInterfaceName, slot);
1676         if (ret != 0) {
1677             loge("stopWifiIPPacketOffload(" + slot + "): hardware error " + ret);
1678             return SocketKeepalive.ERROR_HARDWARE_ERROR;
1679         } else {
1680             return SocketKeepalive.SUCCESS;
1681         }
1682     }
1683 
1684     @Override
isConnected()1685     public boolean isConnected() {
1686         return getCurrentState() == mL3ConnectedState;
1687     }
1688 
1689     @Override
isConnecting()1690     public boolean isConnecting() {
1691         IState state = getCurrentState();
1692         return state == mL2ConnectingState || state == mL2ConnectedState
1693                 || state == mWaitBeforeL3ProvisioningState || state == mL3ProvisioningState;
1694     }
1695 
1696     @Override
isRoaming()1697     public boolean isRoaming() {
1698         return getCurrentState() == mRoamingState;
1699     }
1700 
1701     @Override
isDisconnected()1702     public boolean isDisconnected() {
1703         return getCurrentState() == mDisconnectedState;
1704     }
1705 
1706     /**
1707      * Method checking if supplicant is in a transient state
1708      *
1709      * @return boolean true if in transient state
1710      */
isSupplicantTransientState()1711     public boolean isSupplicantTransientState() {
1712         SupplicantState supplicantState = mWifiInfo.getSupplicantState();
1713         if (supplicantState == SupplicantState.ASSOCIATING
1714                 || supplicantState == SupplicantState.AUTHENTICATING
1715                 || supplicantState == SupplicantState.FOUR_WAY_HANDSHAKE
1716                 || supplicantState == SupplicantState.GROUP_HANDSHAKE) {
1717 
1718             if (mVerboseLoggingEnabled) {
1719                 Log.d(getTag(), "Supplicant is under transient state: " + supplicantState);
1720             }
1721             return true;
1722         } else {
1723             if (mVerboseLoggingEnabled) {
1724                 Log.d(getTag(), "Supplicant is under steady state: " + supplicantState);
1725             }
1726         }
1727 
1728         return false;
1729     }
1730 
1731     /**
1732      * Get status information for the current connection, if any.
1733      * Note: This call is synchronized and hence safe to call from any thread (if called from wifi
1734      * thread, will execute synchronously).
1735      *
1736      * @return a {@link WifiInfo} object containing information about the current connection
1737      */
1738     @Override
getConnectionInfo()1739     public WifiInfo getConnectionInfo() {
1740         return new WifiInfo(mWifiInfo);
1741     }
1742 
1743     /**
1744      * Blocking call to get the current DHCP results
1745      *
1746      * @return DhcpResultsParcelable current results
1747      */
1748     @NonNull
syncGetDhcpResultsParcelable()1749     public DhcpResultsParcelable syncGetDhcpResultsParcelable() {
1750         synchronized (mDhcpResultsParcelableLock) {
1751             return mDhcpResultsParcelable;
1752         }
1753     }
1754 
1755     /**
1756      * When the underlying interface is destroyed, we must immediately tell connectivity service to
1757      * mark network agent as disconnected and stop the ip client.
1758      */
handleIfaceDestroyed()1759     public void handleIfaceDestroyed() {
1760         handleNetworkDisconnect(false,
1761                 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__IFACE_DESTROYED);
1762     }
1763 
1764     /** Stop this ClientModeImpl. Do not interact with ClientModeImpl after it has been stopped. */
stop()1765     public void stop() {
1766         mInsecureEapNetworkHandler.cleanup();
1767         mSupplicantStateTracker.stop();
1768         mWifiScoreCard.noteWifiDisabled(mWifiInfo);
1769         // capture StateMachine LogRecs since we will lose them after we call quitNow()
1770         // This is used for debugging.
1771         mObituary = new StateMachineObituary(this);
1772 
1773         // quit discarding all unprocessed messages - this is to preserve the legacy behavior of
1774         // using sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE) which would force a state
1775         // transition immediately
1776         quitNow();
1777 
1778         mWifiConfigManager.removeOnNetworkUpdateListener(mOnNetworkUpdateListener);
1779         mWifiCarrierInfoManager
1780                 .removeOnCarrierOffloadDisabledListener(mOnCarrierOffloadDisabledListener);
1781         if (mVcnPolicyChangeListener != null && SdkLevel.isAtLeastS()) {
1782             mVcnManager.removeVcnNetworkPolicyChangeListener(mVcnPolicyChangeListener);
1783             mVcnPolicyChangeListener = null;
1784         }
1785     }
1786 
checkAbnormalConnectionFailureAndTakeBugReport(String ssid)1787     private void checkAbnormalConnectionFailureAndTakeBugReport(String ssid) {
1788         if (mDeviceConfigFacade.isAbnormalConnectionFailureBugreportEnabled()) {
1789             int reasonCode = mWifiScoreCard.detectAbnormalConnectionFailure(ssid);
1790             if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) {
1791                 String bugTitle = "Wi-Fi BugReport: abnormal "
1792                         + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
1793                 String bugDetail = "Detect abnormal "
1794                         + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
1795                 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail);
1796             }
1797         }
1798     }
1799 
checkAbnormalDisconnectionAndTakeBugReport()1800     private void checkAbnormalDisconnectionAndTakeBugReport() {
1801         if (mDeviceConfigFacade.isAbnormalDisconnectionBugreportEnabled()) {
1802             int reasonCode = mWifiScoreCard.detectAbnormalDisconnection(mInterfaceName);
1803             if (reasonCode != WifiHealthMonitor.REASON_NO_FAILURE) {
1804                 String bugTitle = "Wi-Fi BugReport: abnormal "
1805                         + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
1806                 String bugDetail = "Detect abnormal "
1807                         + WifiHealthMonitor.FAILURE_REASON_NAME[reasonCode];
1808                 mWifiDiagnostics.takeBugReport(bugTitle, bugDetail);
1809             }
1810         }
1811     }
1812 
1813     /**
1814      * Retrieve the WifiMulticastLockManager.FilterController callback for registration.
1815      */
getMcastLockManagerFilterController()1816     public WifiMulticastLockManager.FilterController getMcastLockManagerFilterController() {
1817         return mMcastLockManagerFilterController;
1818     }
1819 
1820     /**
1821      * Blocking method to retrieve the passpoint icon.
1822      *
1823      * @param bssid representation of the bssid as a long
1824      * @param fileName name of the file
1825      *
1826      * @return boolean returning the result of the call
1827      */
syncQueryPasspointIcon(long bssid, String fileName)1828     public boolean syncQueryPasspointIcon(long bssid, String fileName) {
1829         return mWifiThreadRunner.call(
1830                 () -> mPasspointManager.queryPasspointIcon(bssid, fileName), false);
1831     }
1832 
1833     @Override
requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes)1834     public boolean requestAnqp(String bssid, Set<Integer> anqpIds, Set<Integer> hs20Subtypes) {
1835         return mWifiNative.requestAnqp(mInterfaceName, bssid, anqpIds, hs20Subtypes);
1836     }
1837 
1838     @Override
requestVenueUrlAnqp(String bssid)1839     public boolean requestVenueUrlAnqp(String bssid) {
1840         return mWifiNative.requestVenueUrlAnqp(mInterfaceName, bssid);
1841     }
1842 
1843     @Override
requestIcon(String bssid, String fileName)1844     public boolean requestIcon(String bssid, String fileName) {
1845         return mWifiNative.requestIcon(mInterfaceName, bssid, fileName);
1846     }
1847 
1848     /**
1849      * Disconnect from Access Point
1850      */
disconnect()1851     public void disconnect() {
1852         sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_GENERIC);
1853     }
1854 
1855     /**
1856      * Initiate a reconnection to AP
1857      */
reconnect(WorkSource workSource)1858     public void reconnect(WorkSource workSource) {
1859         sendMessage(CMD_RECONNECT, workSource);
1860     }
1861 
1862     /**
1863      * Initiate a re-association to AP
1864      */
reassociate()1865     public void reassociate() {
1866         sendMessage(CMD_REASSOCIATE);
1867     }
1868 
1869     /**
1870      * Start subscription provisioning synchronously
1871      *
1872      * @param provider {@link OsuProvider} the provider to provision with
1873      * @param callback {@link IProvisioningCallback} callback for provisioning status
1874      * @return boolean true indicates provisioning was started, false otherwise
1875      */
syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, IProvisioningCallback callback)1876     public boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider,
1877             IProvisioningCallback callback) {
1878         return mWifiThreadRunner.call(
1879                 () -> mPasspointManager.startSubscriptionProvisioning(
1880                         callingUid, provider, callback), false);
1881     }
1882 
1883     /**
1884      * Get the supported feature set synchronously
1885      */
getSupportedFeatures()1886     public long getSupportedFeatures() {
1887         return mWifiNative.getSupportedFeatureSet(mInterfaceName);
1888     }
1889 
1890     /**
1891      * Method to enable/disable RSSI polling
1892      * @param enabled boolean idicating if polling should start
1893      */
1894     @VisibleForTesting
enableRssiPolling(boolean enabled)1895     public void enableRssiPolling(boolean enabled) {
1896         sendMessage(CMD_ENABLE_RSSI_POLL, enabled ? 1 : 0, 0);
1897     }
1898 
1899     /**
1900      * reset cached SIM credential data
1901      */
resetSimAuthNetworks(@esetSimReason int resetReason)1902     public void resetSimAuthNetworks(@ResetSimReason int resetReason) {
1903         sendMessage(CMD_RESET_SIM_NETWORKS, resetReason);
1904     }
1905 
1906     /**
1907      * Get Network object of currently connected wifi network, or null if not connected.
1908      * @return Network object of current wifi network
1909      */
getCurrentNetwork()1910     public Network getCurrentNetwork() {
1911         if (getCurrentState() != mL3ConnectedState
1912                 && getCurrentState() != mRoamingState) return null;
1913         return (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null;
1914     }
1915 
1916     /**
1917      * Enable TDLS for a specific MAC address
1918      */
enableTdls(String remoteMacAddress, boolean enable)1919     public boolean enableTdls(String remoteMacAddress, boolean enable) {
1920         boolean ret;
1921         if (!canEnableTdls()) {
1922             return false;
1923         }
1924         ret = mWifiNative.startTdls(mInterfaceName, remoteMacAddress, enable);
1925         if (enable && ret) {
1926             mEnabledTdlsPeers.add(remoteMacAddress);
1927         } else {
1928             mEnabledTdlsPeers.remove(remoteMacAddress);
1929         }
1930         return ret;
1931     }
1932 
1933     /**
1934      * Enable TDLS for a specific IP address
1935      */
enableTdlsWithRemoteIpAddress(String remoteIpAddress, boolean enable)1936     public boolean enableTdlsWithRemoteIpAddress(String remoteIpAddress, boolean enable) {
1937         boolean ret;
1938         String remoteMacAddress = macAddressFromRoute(remoteIpAddress);
1939         if (remoteMacAddress == null) {
1940             return false;
1941         }
1942         ret = enableTdls(remoteMacAddress, enable);
1943         return ret;
1944     }
1945 
1946     /**
1947      *  Check if a TDLS session can be established
1948      */
isTdlsOperationCurrentlyAvailable()1949     public boolean isTdlsOperationCurrentlyAvailable() {
1950         return (getSupportedFeatures() & WIFI_FEATURE_TDLS) != 0 && isConnected()
1951                 && canEnableTdls();
1952     }
1953 
1954     /**
1955      *  Return the number of Mac addresses configured in the driver for TDLS connection.
1956      */
getNumberOfEnabledTdlsSessions()1957     public int getNumberOfEnabledTdlsSessions() {
1958         return mEnabledTdlsPeers.size();
1959     }
1960 
1961     /**
1962      *  Return the maximum number of TDLS sessions supported by the device.
1963      */
getMaxSupportedConcurrentTdlsSessions()1964     public int getMaxSupportedConcurrentTdlsSessions() {
1965         return mWifiNative.getMaxSupportedConcurrentTdlsSessions(mInterfaceName);
1966     }
1967 
canEnableTdls()1968     private boolean canEnableTdls() {
1969         // This function returns -1 if HAL doesn't have support for retrieving this info.
1970         int maxTdlsSessionCount = mWifiNative.getMaxSupportedConcurrentTdlsSessions(mInterfaceName);
1971         if (maxTdlsSessionCount < 0) {
1972             return true;
1973         }
1974         if (mEnabledTdlsPeers.size() >= maxTdlsSessionCount) {
1975             Log.e(TAG, "canEnableTdls() returned false: maxTdlsSessionCount: "
1976                     + maxTdlsSessionCount + "EnabledTdlsPeers count: " + mEnabledTdlsPeers.size());
1977             return false;
1978         }
1979         return true;
1980     }
1981 
1982     /** Send a message indicating bluetooth connection state changed, e.g. connected/disconnected */
onBluetoothConnectionStateChanged()1983     public void onBluetoothConnectionStateChanged() {
1984         sendMessage(CMD_BLUETOOTH_CONNECTION_STATE_CHANGE);
1985     }
1986 
1987     /**
1988      * Trigger dump on the class IpClient object.
1989      */
dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args)1990     public void dumpIpClient(FileDescriptor fd, PrintWriter pw, String[] args) {
1991         if (mIpClient != null) {
1992             // All dumpIpClient does is print this log message.
1993             // TODO: consider deleting this, since it's not useful.
1994             pw.println("IpClient logs have moved to dumpsys network_stack");
1995         }
1996     }
1997 
dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults)1998     private static String dhcpResultsParcelableToString(DhcpResultsParcelable dhcpResults) {
1999         return new StringBuilder()
2000                 .append("baseConfiguration ").append(dhcpResults.baseConfiguration)
2001                 .append("leaseDuration ").append(dhcpResults.leaseDuration)
2002                 .append("mtu ").append(dhcpResults.mtu)
2003                 .append("serverAddress ").append(dhcpResults.serverAddress)
2004                 .append("serverHostName ").append(dhcpResults.serverHostName)
2005                 .append("vendorInfo ").append(dhcpResults.vendorInfo)
2006                 .toString();
2007     }
2008 
2009     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2010     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2011         pw.println("Dump of ClientModeImpl id=" + mId);
2012         if (mObituary == null) {
2013             // StateMachine hasn't quit yet, dump `this` via StateMachineObituary's dump()
2014             // method for consistency with `else` branch.
2015             new StateMachineObituary(this).dump(fd, pw, args);
2016         } else {
2017             // StateMachine has quit and cleared all LogRecs.
2018             // Get them from the obituary instead.
2019             mObituary.dump(fd, pw, args);
2020         }
2021         mSupplicantStateTracker.dump(fd, pw, args);
2022         // Polls link layer stats and RSSI. This allows the stats to show up in
2023         // WifiScoreReport's dump() output when taking a bug report even if the screen is off.
2024         updateLinkLayerStatsRssiAndScoreReport();
2025         pw.println("mLinkProperties " + mLinkProperties);
2026         pw.println("mWifiInfo " + mWifiInfo);
2027         pw.println("mDhcpResultsParcelable "
2028                 + dhcpResultsParcelableToString(mDhcpResultsParcelable));
2029         pw.println("mLastSignalLevel " + mLastSignalLevel);
2030         pw.println("mLastTxKbps " + mLastTxKbps);
2031         pw.println("mLastRxKbps " + mLastRxKbps);
2032         pw.println("mLastBssid " + mLastBssid);
2033         pw.println("mLastNetworkId " + mLastNetworkId);
2034         pw.println("mLastSubId " + mLastSubId);
2035         pw.println("mLastSimBasedConnectionCarrierName " + mLastSimBasedConnectionCarrierName);
2036         pw.println("mSuspendOptimizationsEnabled " + mContext.getResources().getBoolean(
2037                 R.bool.config_wifiSuspendOptimizationsEnabled));
2038         pw.println("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
2039         pw.println("mPowerSaveDisableRequests " + mPowerSaveDisableRequests);
2040         dumpIpClient(fd, pw, args);
2041         pw.println("WifiScoreReport:");
2042         mWifiScoreReport.dump(fd, pw, args);
2043         pw.println("QosPolicyRequestHandler:");
2044         mQosPolicyRequestHandler.dump(fd, pw, args);
2045         pw.println();
2046     }
2047 
2048     /**
2049      * ******************************************************
2050      * Internal private functions
2051      * ******************************************************
2052      */
2053 
logStateAndMessage(Message message, State state)2054     private void logStateAndMessage(Message message, State state) {
2055         mMessageHandlingStatus = 0;
2056         if (mVerboseLoggingEnabled) {
2057             logd(" " + state.getClass().getSimpleName() + " " + getLogRecString(message));
2058         }
2059     }
2060 
2061     @Override
recordLogRec(Message msg)2062     protected boolean recordLogRec(Message msg) {
2063         switch (msg.what) {
2064             case CMD_RSSI_POLL:
2065                 return mVerboseLoggingEnabled;
2066             default:
2067                 return true;
2068         }
2069     }
2070 
2071     /**
2072      * Return the additional string to be logged by LogRec, default
2073      *
2074      * @param msg that was processed
2075      * @return information to be logged as a String
2076      */
2077     @Override
getLogRecString(Message msg)2078     protected String getLogRecString(Message msg) {
2079         WifiConfiguration config;
2080         Long now;
2081         String report;
2082         String key;
2083         StringBuilder sb = new StringBuilder();
2084         sb.append("screen=").append(mScreenOn ? "on" : "off");
2085         if (mMessageHandlingStatus != MESSAGE_HANDLING_STATUS_UNKNOWN) {
2086             sb.append("(").append(mMessageHandlingStatus).append(")");
2087         }
2088         if (msg.sendingUid > 0 && msg.sendingUid != Process.WIFI_UID) {
2089             sb.append(" uid=" + msg.sendingUid);
2090         }
2091         switch (msg.what) {
2092             case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
2093                 sb.append(" ");
2094                 sb.append(Integer.toString(msg.arg1));
2095                 sb.append(" ");
2096                 sb.append(Integer.toString(msg.arg2));
2097                 StateChangeResult stateChangeResult = (StateChangeResult) msg.obj;
2098                 if (stateChangeResult != null) {
2099                     sb.append(stateChangeResult.toString());
2100                 }
2101                 break;
2102             case CMD_CONNECT_NETWORK:
2103             case CMD_SAVE_NETWORK: {
2104                 ConnectNetworkMessage cnm = (ConnectNetworkMessage) msg.obj;
2105                 sb.append(" ");
2106                 sb.append(cnm.result.getNetworkId());
2107                 config = mWifiConfigManager.getConfiguredNetwork(cnm.result.getNetworkId());
2108                 if (config != null) {
2109                     sb.append(" ").append(config.getProfileKey());
2110                     sb.append(" nid=").append(config.networkId);
2111                     if (config.hiddenSSID) {
2112                         sb.append(" hidden");
2113                     }
2114                     if (config.preSharedKey != null
2115                             && !config.preSharedKey.equals("*")) {
2116                         sb.append(" hasPSK");
2117                     }
2118                     if (config.ephemeral) {
2119                         sb.append(" ephemeral");
2120                     }
2121                     sb.append(" cuid=").append(config.creatorUid);
2122                     sb.append(" suid=").append(config.lastUpdateUid);
2123                 }
2124                 break;
2125             }
2126             case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
2127                 if (msg.obj != null) {
2128                     sb.append(" ").append((AssocRejectEventInfo) msg.obj);
2129                 }
2130                 break;
2131             case WifiMonitor.NETWORK_CONNECTION_EVENT: {
2132                 NetworkConnectionEventInfo connectionInfo = (NetworkConnectionEventInfo) msg.obj;
2133                 sb.append(" ");
2134                 sb.append(connectionInfo.networkId);
2135                 sb.append(" ");
2136                 sb.append(connectionInfo.isFilsConnection);
2137                 sb.append(" ").append(mLastBssid);
2138                 sb.append(" nid=").append(mLastNetworkId);
2139                 config = getConnectedWifiConfigurationInternal();
2140                 if (config != null) {
2141                     sb.append(" ").append(config.getProfileKey());
2142                 }
2143                 key = mWifiConfigManager.getLastSelectedNetworkConfigKey();
2144                 if (key != null) {
2145                     sb.append(" last=").append(key);
2146                 }
2147                 break;
2148             }
2149             case WifiMonitor.TARGET_BSSID_EVENT:
2150             case WifiMonitor.ASSOCIATED_BSSID_EVENT:
2151                 sb.append(" ");
2152                 sb.append(Integer.toString(msg.arg1));
2153                 sb.append(" ");
2154                 sb.append(Integer.toString(msg.arg2));
2155                 if (msg.obj != null) {
2156                     sb.append(" BSSID=").append((String) msg.obj);
2157                 }
2158                 if (mTargetBssid != null) {
2159                     sb.append(" Target Bssid=").append(mTargetBssid);
2160                 }
2161                 if (mLastBssid != null) {
2162                     sb.append(" Last Bssid=").append(mLastBssid);
2163                 }
2164                 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
2165                 break;
2166             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
2167                 if (msg.obj != null) {
2168                     sb.append(" ").append((DisconnectEventInfo) msg.obj);
2169                 }
2170                 if (mLastBssid != null) {
2171                     sb.append(" lastbssid=").append(mLastBssid);
2172                 }
2173                 if (mWifiInfo.getFrequency() != -1) {
2174                     sb.append(" freq=").append(mWifiInfo.getFrequency());
2175                     sb.append(" rssi=").append(mWifiInfo.getRssi());
2176                 }
2177                 break;
2178             case CMD_RSSI_POLL:
2179             case CMD_ONESHOT_RSSI_POLL:
2180             case CMD_UNWANTED_NETWORK:
2181                 sb.append(" ");
2182                 sb.append(Integer.toString(msg.arg1));
2183                 sb.append(" ");
2184                 sb.append(Integer.toString(msg.arg2));
2185                 if (mWifiInfo.getSSID() != null) {
2186                     if (mWifiInfo.getSSID() != null) {
2187                         sb.append(" ").append(mWifiInfo.getSSID());
2188                     }
2189                 }
2190                 if (mWifiInfo.getBSSID() != null) {
2191                     sb.append(" ").append(mWifiInfo.getBSSID());
2192                 }
2193                 sb.append(" rssi=").append(mWifiInfo.getRssi());
2194                 sb.append(" f=").append(mWifiInfo.getFrequency());
2195                 sb.append(" sc=").append(mWifiInfo.getScore());
2196                 sb.append(" link=").append(mWifiInfo.getLinkSpeed());
2197                 sb.append(" tx=").append(
2198                         ((int) (mWifiInfo.getSuccessfulTxPacketsPerSecond() * 10)) / 10.0);
2199                 sb.append(", ").append(
2200                         ((int) (mWifiInfo.getRetriedTxPacketsPerSecond() * 10)) / 10.0);
2201                 sb.append(", ").append(((int) (mWifiInfo.getLostTxPacketsPerSecond() * 10)) / 10.0);
2202                 sb.append(" rx=").append(
2203                         ((int) (mWifiInfo.getSuccessfulRxPacketsPerSecond() * 10)) / 10.0);
2204                 sb.append(" bcn=" + mRunningBeaconCount);
2205                 report = reportOnTime();
2206                 if (report != null) {
2207                     sb.append(" ").append(report);
2208                 }
2209                 sb.append(" score=" + mWifiInfo.getScore());
2210                 break;
2211             case CMD_START_CONNECT:
2212                 sb.append(" ");
2213                 sb.append(Integer.toString(msg.arg1));
2214                 sb.append(" ");
2215                 sb.append(Integer.toString(msg.arg2));
2216                 config = mWifiConfigManager.getConfiguredNetwork(msg.arg1);
2217                 if (config != null) {
2218                     sb.append(" targetConfigKey=").append(config.getProfileKey());
2219                     sb.append(" BSSID=" + config.BSSID);
2220                 }
2221                 if (mTargetBssid != null) {
2222                     sb.append(" targetBssid=").append(mTargetBssid);
2223                 }
2224                 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
2225                 config = getConnectedWifiConfigurationInternal();
2226                 if (config != null) {
2227                     sb.append(" currentConfigKey=").append(config.getProfileKey());
2228                 }
2229                 break;
2230             case CMD_START_ROAM:
2231                 sb.append(" ");
2232                 sb.append(Integer.toString(msg.arg1));
2233                 sb.append(" ");
2234                 sb.append(Integer.toString(msg.arg2));
2235                 String bssid = (String) msg.obj;
2236                 sb.append(" bssid=").append(bssid);
2237                 if (mTargetBssid != null) {
2238                     sb.append(" ").append(mTargetBssid);
2239                 }
2240                 sb.append(" roam=").append(Boolean.toString(mIsAutoRoaming));
2241                 sb.append(" fail count=").append(Integer.toString(mRoamFailCount));
2242                 break;
2243             case CMD_PRE_DHCP_ACTION:
2244                 sb.append(" ");
2245                 sb.append(Integer.toString(msg.arg1));
2246                 sb.append(" ");
2247                 sb.append(Integer.toString(msg.arg2));
2248                 sb.append(" txpkts=").append(mWifiInfo.txSuccess);
2249                 sb.append(",").append(mWifiInfo.txBad);
2250                 sb.append(",").append(mWifiInfo.txRetries);
2251                 break;
2252             case CMD_POST_DHCP_ACTION:
2253                 if (mLinkProperties != null) {
2254                     sb.append(" ");
2255                     sb.append(getLinkPropertiesSummary(mLinkProperties));
2256                 }
2257                 break;
2258             case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
2259                 sb.append(" ");
2260                 sb.append(Integer.toString(msg.arg1));
2261                 sb.append(" ");
2262                 sb.append(Integer.toString(msg.arg2));
2263                 if (msg.obj != null) {
2264                     NetworkInfo info = (NetworkInfo) msg.obj;
2265                     NetworkInfo.State state = info.getState();
2266                     NetworkInfo.DetailedState detailedState = info.getDetailedState();
2267                     if (state != null) {
2268                         sb.append(" st=").append(state);
2269                     }
2270                     if (detailedState != null) {
2271                         sb.append("/").append(detailedState);
2272                     }
2273                 }
2274                 break;
2275             case CMD_IP_CONFIGURATION_LOST:
2276                 int count = -1;
2277                 WifiConfiguration c = getConnectedWifiConfigurationInternal();
2278                 if (c != null) {
2279                     count = c.getNetworkSelectionStatus().getDisableReasonCounter(
2280                             WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
2281                 }
2282                 sb.append(" ");
2283                 sb.append(Integer.toString(msg.arg1));
2284                 sb.append(" ");
2285                 sb.append(Integer.toString(msg.arg2));
2286                 sb.append(" failures: ");
2287                 sb.append(Integer.toString(count));
2288                 sb.append("/");
2289                 sb.append(Integer.toString(mFacade.getIntegerSetting(
2290                         mContext, Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT, 0)));
2291                 if (mWifiInfo.getBSSID() != null) {
2292                     sb.append(" ").append(mWifiInfo.getBSSID());
2293                 }
2294                 sb.append(" bcn=" + mRunningBeaconCount);
2295                 break;
2296             case CMD_UPDATE_LINKPROPERTIES:
2297                 sb.append(" ");
2298                 sb.append(Integer.toString(msg.arg1));
2299                 sb.append(" ");
2300                 sb.append(Integer.toString(msg.arg2));
2301                 if (mLinkProperties != null) {
2302                     sb.append(" ");
2303                     sb.append(getLinkPropertiesSummary(mLinkProperties));
2304                 }
2305                 break;
2306             case CMD_IP_REACHABILITY_LOST:
2307                 if (msg.obj != null) {
2308                     sb.append(" ").append((String) msg.obj);
2309                 }
2310                 break;
2311             case CMD_IP_REACHABILITY_FAILURE:
2312                 if (msg.obj != null) {
2313                     sb.append(" ").append(/* ReachabilityLossInfoParcelable */ msg.obj);
2314                 }
2315                 break;
2316             case CMD_INSTALL_PACKET_FILTER:
2317                 sb.append(" len=" + ((byte[]) msg.obj).length);
2318                 break;
2319             case CMD_SET_FALLBACK_PACKET_FILTERING:
2320                 sb.append(" enabled=" + (boolean) msg.obj);
2321                 break;
2322             case CMD_SET_MAX_DTIM_MULTIPLIER:
2323                 sb.append(" maximum multiplier=" + msg.arg1);
2324                 break;
2325             case CMD_ROAM_WATCHDOG_TIMER:
2326                 sb.append(" ");
2327                 sb.append(Integer.toString(msg.arg1));
2328                 sb.append(" ");
2329                 sb.append(Integer.toString(msg.arg2));
2330                 sb.append(" cur=").append(mRoamWatchdogCount);
2331                 break;
2332             case CMD_CONNECTING_WATCHDOG_TIMER:
2333                 sb.append(" ");
2334                 sb.append(Integer.toString(msg.arg1));
2335                 sb.append(" ");
2336                 sb.append(Integer.toString(msg.arg2));
2337                 sb.append(" cur=").append(mConnectingWatchdogCount);
2338                 break;
2339             case CMD_IPV4_PROVISIONING_SUCCESS:
2340                 sb.append(" ");
2341                 sb.append(/* DhcpResultsParcelable */ msg.obj);
2342                 break;
2343             case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE:
2344                 BtmFrameData frameData = (BtmFrameData) msg.obj;
2345                 if (frameData != null) {
2346                     sb.append(" ").append(frameData.toString());
2347                 }
2348                 break;
2349             case WifiMonitor.NETWORK_NOT_FOUND_EVENT:
2350                 sb.append(" ssid=" + msg.obj);
2351                 break;
2352             case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT:
2353                 sb.append(" frequency=" + msg.arg1);
2354                 break;
2355             default:
2356                 sb.append(" ");
2357                 sb.append(Integer.toString(msg.arg1));
2358                 sb.append(" ");
2359                 sb.append(Integer.toString(msg.arg2));
2360                 break;
2361         }
2362 
2363         return sb.toString();
2364     }
2365 
2366     @Override
getWhatToString(int what)2367     protected String getWhatToString(int what) {
2368         switch (what) {
2369             case CMD_ACCEPT_UNVALIDATED:
2370                 return "CMD_ACCEPT_UNVALIDATED";
2371             case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF:
2372                 return "CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF";
2373             case CMD_BLUETOOTH_CONNECTION_STATE_CHANGE:
2374                 return "CMD_BLUETOOTH_CONNECTION_STATE_CHANGE";
2375             case CMD_CONFIG_ND_OFFLOAD:
2376                 return "CMD_CONFIG_ND_OFFLOAD";
2377             case CMD_CONNECTING_WATCHDOG_TIMER:
2378                 return "CMD_CONNECTING_WATCHDOG_TIMER";
2379             case CMD_CONNECT_NETWORK:
2380                 return "CMD_CONNECT_NETWORK";
2381             case CMD_DISCONNECT:
2382                 return "CMD_DISCONNECT";
2383             case CMD_ENABLE_RSSI_POLL:
2384                 return "CMD_ENABLE_RSSI_POLL";
2385             case CMD_INSTALL_PACKET_FILTER:
2386                 return "CMD_INSTALL_PACKET_FILTER";
2387             case CMD_IP_CONFIGURATION_LOST:
2388                 return "CMD_IP_CONFIGURATION_LOST";
2389             case CMD_IP_CONFIGURATION_SUCCESSFUL:
2390                 return "CMD_IP_CONFIGURATION_SUCCESSFUL";
2391             case CMD_IP_REACHABILITY_LOST:
2392                 return "CMD_IP_REACHABILITY_LOST";
2393             case CMD_IP_REACHABILITY_FAILURE:
2394                 return "CMD_IP_REACHABILITY_FAILURE";
2395             case CMD_IPCLIENT_STARTUP_TIMEOUT:
2396                 return "CMD_IPCLIENT_STARTUP_TIMEOUT";
2397             case CMD_IPV4_PROVISIONING_FAILURE:
2398                 return "CMD_IPV4_PROVISIONING_FAILURE";
2399             case CMD_IPV4_PROVISIONING_SUCCESS:
2400                 return "CMD_IPV4_PROVISIONING_SUCCESS";
2401             case CMD_NETWORK_STATUS:
2402                 return "CMD_NETWORK_STATUS";
2403             case CMD_ONESHOT_RSSI_POLL:
2404                 return "CMD_ONESHOT_RSSI_POLL";
2405             case CMD_POST_DHCP_ACTION:
2406                 return "CMD_POST_DHCP_ACTION";
2407             case CMD_PRE_DHCP_ACTION:
2408                 return "CMD_PRE_DHCP_ACTION";
2409             case CMD_PRE_DHCP_ACTION_COMPLETE:
2410                 return "CMD_PRE_DHCP_ACTION_COMPLETE";
2411             case CMD_READ_PACKET_FILTER:
2412                 return "CMD_READ_PACKET_FILTER";
2413             case CMD_REASSOCIATE:
2414                 return "CMD_REASSOCIATE";
2415             case CMD_RECONNECT:
2416                 return "CMD_RECONNECT";
2417             case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF:
2418                 return "CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF";
2419             case CMD_RESET_SIM_NETWORKS:
2420                 return "CMD_RESET_SIM_NETWORKS";
2421             case CMD_ROAM_WATCHDOG_TIMER:
2422                 return "CMD_ROAM_WATCHDOG_TIMER";
2423             case CMD_RSSI_POLL:
2424                 return "CMD_RSSI_POLL";
2425             case CMD_SAVE_NETWORK:
2426                 return "CMD_SAVE_NETWORK";
2427             case CMD_SCREEN_STATE_CHANGED:
2428                 return "CMD_SCREEN_STATE_CHANGED";
2429             case CMD_SET_FALLBACK_PACKET_FILTERING:
2430                 return "CMD_SET_FALLBACK_PACKET_FILTERING";
2431             case CMD_SET_MAX_DTIM_MULTIPLIER:
2432                 return "CMD_SET_MAX_DTIM_MULTIPLIER";
2433             case CMD_SET_SUSPEND_OPT_ENABLED:
2434                 return "CMD_SET_SUSPEND_OPT_ENABLED";
2435             case CMD_START_CONNECT:
2436                 return "CMD_START_CONNECT";
2437             case CMD_START_FILS_CONNECTION:
2438                 return "CMD_START_FILS_CONNECTION";
2439             case CMD_START_IP_PACKET_OFFLOAD:
2440                 return "CMD_START_IP_PACKET_OFFLOAD";
2441             case CMD_START_ROAM:
2442                 return "CMD_START_ROAM";
2443             case CMD_STOP_IP_PACKET_OFFLOAD:
2444                 return "CMD_STOP_IP_PACKET_OFFLOAD";
2445             case CMD_UNWANTED_NETWORK:
2446                 return "CMD_UNWANTED_NETWORK";
2447             case CMD_UPDATE_LINKPROPERTIES:
2448                 return "CMD_UPDATE_LINKPROPERTIES";
2449             case CMD_IPCLIENT_CREATED:
2450                 return "CMD_IPCLIENT_CREATED";
2451             case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
2452                 return "CMD_ACCEPT_EAP_SERVER_CERTIFICATE";
2453             case CMD_REJECT_EAP_INSECURE_CONNECTION:
2454                 return "CMD_REJECT_EAP_SERVER_CERTIFICATE";
2455             case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
2456                 return "SUPPLICANT_STATE_CHANGE_EVENT";
2457             case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
2458                 return "AUTHENTICATION_FAILURE_EVENT";
2459             case WifiMonitor.SUP_REQUEST_IDENTITY:
2460                 return "SUP_REQUEST_IDENTITY";
2461             case WifiMonitor.NETWORK_CONNECTION_EVENT:
2462                 return "NETWORK_CONNECTION_EVENT";
2463             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
2464                 return "NETWORK_DISCONNECTION_EVENT";
2465             case WifiMonitor.ASSOCIATED_BSSID_EVENT:
2466                 return "ASSOCIATED_BSSID_EVENT";
2467             case WifiMonitor.TARGET_BSSID_EVENT:
2468                 return "TARGET_BSSID_EVENT";
2469             case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
2470                 return "ASSOCIATION_REJECTION_EVENT";
2471             case WifiMonitor.ANQP_DONE_EVENT:
2472                 return "ANQP_DONE_EVENT";
2473             case WifiMonitor.RX_HS20_ANQP_ICON_EVENT:
2474                 return "RX_HS20_ANQP_ICON_EVENT";
2475             case WifiMonitor.GAS_QUERY_DONE_EVENT:
2476                 return "GAS_QUERY_DONE_EVENT";
2477             case WifiMonitor.HS20_REMEDIATION_EVENT:
2478                 return "HS20_REMEDIATION_EVENT";
2479             case WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT:
2480                 return "HS20_DEAUTH_IMMINENT_EVENT";
2481             case WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT:
2482                 return "HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT";
2483             case WifiMonitor.GAS_QUERY_START_EVENT:
2484                 return "GAS_QUERY_START_EVENT";
2485             case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE:
2486                 return "MBO_OCE_BSS_TM_HANDLING_DONE";
2487             case WifiMonitor.TRANSITION_DISABLE_INDICATION:
2488                 return "TRANSITION_DISABLE_INDICATION";
2489             case WifiP2pServiceImpl.GROUP_CREATING_TIMED_OUT:
2490                 return "GROUP_CREATING_TIMED_OUT";
2491             case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
2492                 return "P2P_CONNECTION_CHANGED";
2493             case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST:
2494                 return "DISCONNECT_WIFI_REQUEST";
2495             case WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE:
2496                 return "DISCONNECT_WIFI_RESPONSE";
2497             case WifiP2pServiceImpl.SET_MIRACAST_MODE:
2498                 return "SET_MIRACAST_MODE";
2499             case WifiP2pServiceImpl.BLOCK_DISCOVERY:
2500                 return "BLOCK_DISCOVERY";
2501             case WifiMonitor.NETWORK_NOT_FOUND_EVENT:
2502                 return "NETWORK_NOT_FOUND_EVENT";
2503             case WifiMonitor.TOFU_CERTIFICATE_EVENT:
2504                 return "TOFU_CERTIFICATE_EVENT";
2505             case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT:
2506                 return "BSS_FREQUENCY_CHANGED_EVENT";
2507             case RunnerState.STATE_ENTER_CMD:
2508                 return "Enter";
2509             case RunnerState.STATE_EXIT_CMD:
2510                 return "Exit";
2511             default:
2512                 return "what:" + what;
2513         }
2514     }
2515 
2516     /** Check whether this connection is the primary connection on the device. */
isPrimary()2517     private boolean isPrimary() {
2518         return mClientModeManager.getRole() == ROLE_CLIENT_PRIMARY;
2519     }
2520 
isScanOnly()2521     private boolean isScanOnly() {
2522         return mClientModeManager.getRole() == ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
2523     }
2524 
2525     /** Check whether this connection is the secondary internet wifi connection. */
isSecondaryInternet()2526     private boolean isSecondaryInternet() {
2527         return mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_LONG_LIVED
2528                 && mClientModeManager.isSecondaryInternet();
2529     }
2530 
2531     /** Check whether this connection is for local only network. */
isLocalOnly()2532     private boolean isLocalOnly() {
2533         return mClientModeManager.getRole() == ROLE_CLIENT_LOCAL_ONLY;
2534     }
2535 
2536     /**
2537      * Check if originaly requested as local only for ClientModeManager before fallback.
2538      * A secondary role could fallback to primary due to hardware support limit.
2539      * @return true if the original request for ClientModeManager is local only.
2540      */
isRequestedForLocalOnly(WifiConfiguration currentWifiConfiguration, String currentBssid)2541     public boolean isRequestedForLocalOnly(WifiConfiguration currentWifiConfiguration,
2542             String currentBssid) {
2543         Set<Integer> uids =
2544                 mNetworkFactory.getSpecificNetworkRequestUids(
2545                         currentWifiConfiguration, currentBssid);
2546         // Check if there is an active specific request in WifiNetworkFactory for local only.
2547         return !uids.isEmpty();
2548     }
2549 
handleScreenStateChanged(boolean screenOn)2550     private void handleScreenStateChanged(boolean screenOn) {
2551         mScreenOn = screenOn;
2552         if (mVerboseLoggingEnabled) {
2553             logd(" handleScreenStateChanged Enter: screenOn=" + screenOn
2554                     + " mSuspendOptimizationsEnabled="
2555                     + mContext.getResources().getBoolean(
2556                             R.bool.config_wifiSuspendOptimizationsEnabled)
2557                     + " state " + getCurrentState().getName());
2558         }
2559         if (isPrimary() || isSecondaryInternet()) {
2560             // Only enable RSSI polling on primary STA, none of the secondary STA use-cases
2561             // can become the default route when other networks types that provide internet
2562             // connectivity (e.g. cellular) are available. So, no point in scoring
2563             // these connections for the purpose of switching between wifi and other network
2564             // types.
2565             // TODO(b/179518316): Enable this for secondary transient STA also if external scorer
2566             // is in charge of MBB.
2567             enableRssiPolling(screenOn);
2568         }
2569         if (mContext.getResources().getBoolean(R.bool.config_wifiSuspendOptimizationsEnabled)) {
2570             int shouldReleaseWakeLock = 0;
2571             if (screenOn) {
2572                 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 0, shouldReleaseWakeLock);
2573             } else {
2574                 if (isConnected()) {
2575                     // Allow 2s for suspend optimizations to be set
2576                     mSuspendWakeLock.acquire(2000);
2577                     shouldReleaseWakeLock = 1;
2578                 }
2579                 sendMessage(CMD_SET_SUSPEND_OPT_ENABLED, 1, shouldReleaseWakeLock);
2580             }
2581         }
2582 
2583         if (isConnected()) {
2584             getWifiLinkLayerStats();
2585         }
2586         mOnTimeScreenStateChange = mOnTime;
2587         mLastScreenStateChangeTimeStamp = mLastLinkLayerStatsUpdate;
2588 
2589         if (mVerboseLoggingEnabled) log("handleScreenStateChanged Exit: " + screenOn);
2590     }
2591 
setSuspendOptimizationsNative(int reason, boolean enabled)2592     private void setSuspendOptimizationsNative(int reason, boolean enabled) {
2593         if (mVerboseLoggingEnabled) {
2594             log("setSuspendOptimizationsNative: " + reason + " " + enabled
2595                     + " -want " + mContext.getResources().getBoolean(
2596                             R.bool.config_wifiSuspendOptimizationsEnabled)
2597                     + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
2598                     + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
2599                     + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
2600                     + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
2601         }
2602         //mWifiNative.setSuspendOptimizations(enabled);
2603 
2604         if (enabled) {
2605             mSuspendOptNeedsDisabled &= ~reason;
2606             /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
2607             if (mSuspendOptNeedsDisabled == 0
2608                     && mContext.getResources().getBoolean(
2609                             R.bool.config_wifiSuspendOptimizationsEnabled)) {
2610                 if (mVerboseLoggingEnabled) {
2611                     log("setSuspendOptimizationsNative do it " + reason + " " + enabled
2612                             + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
2613                             + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
2614                             + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
2615                             + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
2616                 }
2617                 mWifiNative.setSuspendOptimizations(mInterfaceName, true);
2618             }
2619         } else {
2620             mSuspendOptNeedsDisabled |= reason;
2621             mWifiNative.setSuspendOptimizations(mInterfaceName, false);
2622         }
2623     }
2624 
2625     /**
2626      * Makes a record of the user intent about suspend optimizations.
2627      */
setSuspendOptimizations(int reason, boolean enabled)2628     private void setSuspendOptimizations(int reason, boolean enabled) {
2629         if (mVerboseLoggingEnabled) log("setSuspendOptimizations: " + reason + " " + enabled);
2630         if (enabled) {
2631             mSuspendOptNeedsDisabled &= ~reason;
2632         } else {
2633             mSuspendOptNeedsDisabled |= reason;
2634         }
2635         if (mVerboseLoggingEnabled) log("mSuspendOptNeedsDisabled " + mSuspendOptNeedsDisabled);
2636     }
2637 
2638     /*
2639      * Fetch link layer stats, RSSI, linkspeed, and frequency on current connection
2640      * and update Network capabilities
2641      */
updateLinkLayerStatsRssiSpeedFrequencyCapabilities(long txBytes, long rxBytes)2642     private WifiLinkLayerStats updateLinkLayerStatsRssiSpeedFrequencyCapabilities(long txBytes,
2643             long rxBytes) {
2644         WifiLinkLayerStats stats = getWifiLinkLayerStats();
2645         WifiSignalPollResults pollResults = mWifiNative.signalPoll(mInterfaceName);
2646         if (pollResults == null) {
2647             return stats;
2648         }
2649 
2650         int newRssi = pollResults.getRssi();
2651         int newTxLinkSpeed = pollResults.getTxLinkSpeed();
2652         int newFrequency = pollResults.getFrequency();
2653         int newRxLinkSpeed = pollResults.getRxLinkSpeed();
2654         boolean updateNetworkCapabilities = false;
2655 
2656         if (mVerboseLoggingEnabled) {
2657             logd("updateLinkLayerStatsRssiSpeedFrequencyCapabilities rssi=" + newRssi
2658                     + " TxLinkspeed=" + newTxLinkSpeed + " freq=" + newFrequency
2659                     + " RxLinkSpeed=" + newRxLinkSpeed);
2660         }
2661 
2662         /* Set link specific signal poll results */
2663         for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) {
2664             int linkId = link.getLinkId();
2665             link.setRssi(pollResults.getRssi(linkId));
2666             link.setTxLinkSpeedMbps(pollResults.getTxLinkSpeed(linkId));
2667             link.setRxLinkSpeedMbps(pollResults.getRxLinkSpeed(linkId));
2668             link.setChannel(ScanResult.convertFrequencyMhzToChannelIfSupported(
2669                     pollResults.getFrequency(linkId)));
2670             link.setBand(ScanResult.toBand(pollResults.getFrequency(linkId)));
2671             if (mVerboseLoggingEnabled) {
2672                 logd("linkId=" + linkId + " rssi=" + link.getRssi()
2673                         + " channel=" + link.getChannel()
2674                         + " band=" + link.getBand()
2675                         + " TxLinkspeed=" + link.getTxLinkSpeedMbps()
2676                         + " RxLinkSpeed=" + link.getRxLinkSpeedMbps());
2677             }
2678         }
2679 
2680         /*
2681          * set Tx link speed only if it is valid
2682          */
2683         if (newTxLinkSpeed > 0) {
2684             mWifiInfo.setLinkSpeed(newTxLinkSpeed);
2685             mWifiInfo.setTxLinkSpeedMbps(newTxLinkSpeed);
2686         }
2687         /*
2688          * set Rx link speed only if it is valid
2689          */
2690         if (newRxLinkSpeed > 0) {
2691             mWifiInfo.setRxLinkSpeedMbps(newRxLinkSpeed);
2692         }
2693         if (newFrequency > 0) {
2694             if (mWifiInfo.getFrequency() != newFrequency) {
2695                 updateNetworkCapabilities = true;
2696             }
2697             mWifiInfo.setFrequency(newFrequency);
2698         }
2699         // updateLinkBandwidth() requires the latest frequency information
2700         if (newRssi > WifiInfo.INVALID_RSSI && newRssi < WifiInfo.MAX_RSSI) {
2701             /*
2702              * Positive RSSI is possible when devices are close(~0m apart) to each other.
2703              * And there are some driver/firmware implementation, where they avoid
2704              * reporting large negative rssi values by adding 256.
2705              * so adjust the valid rssi reports for such implementations.
2706              */
2707             if (newRssi > (WifiInfo.INVALID_RSSI + 256)) {
2708                 Log.wtf(getTag(), "Error! +ve value RSSI: " + newRssi);
2709                 newRssi -= 256;
2710             }
2711             mWifiInfo.setRssi(newRssi);
2712             /*
2713              * Rather than sending the raw RSSI out every time it
2714              * changes, we precalculate the signal level that would
2715              * be displayed in the status bar, and only send the
2716              * broadcast if that much more coarse-grained number
2717              * changes. This cuts down greatly on the number of
2718              * broadcasts, at the cost of not informing others
2719              * interested in RSSI of all the changes in signal
2720              * level.
2721              */
2722             int newSignalLevel = RssiUtil.calculateSignalLevel(mContext, newRssi);
2723             if (newSignalLevel != mLastSignalLevel) {
2724                 sendRssiChangeBroadcast(newRssi);
2725                 updateNetworkCapabilities = true;
2726             }
2727             updateLinkBandwidthAndCapabilities(stats, updateNetworkCapabilities, txBytes,
2728                     rxBytes);
2729             mLastSignalLevel = newSignalLevel;
2730         } else {
2731             mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
2732             updateCapabilities();
2733             mLastSignalLevel = -1;
2734         }
2735         mWifiConfigManager.updateScanDetailCacheFromWifiInfo(mWifiInfo);
2736         /*
2737          * Increment various performance metrics
2738          */
2739         mWifiMetrics.handlePollResult(mInterfaceName, mWifiInfo);
2740         updateCurrentConnectionInfo();
2741         return stats;
2742     }
2743 
2744     // Update the link bandwidth. Also update network capabilities if the link bandwidth changes
2745     // by a large amount or there is a change in signal level or frequency.
updateLinkBandwidthAndCapabilities(WifiLinkLayerStats stats, boolean updateNetworkCapabilities, long txBytes, long rxBytes)2746     private void updateLinkBandwidthAndCapabilities(WifiLinkLayerStats stats,
2747             boolean updateNetworkCapabilities, long txBytes, long rxBytes) {
2748         WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID());
2749         network.updateLinkBandwidth(mLastLinkLayerStats, stats, mWifiInfo, txBytes, rxBytes);
2750         int newTxKbps = network.getTxLinkBandwidthKbps();
2751         int newRxKbps = network.getRxLinkBandwidthKbps();
2752         int txDeltaKbps = Math.abs(newTxKbps - mLastTxKbps);
2753         int rxDeltaKbps = Math.abs(newRxKbps - mLastRxKbps);
2754         int bwUpdateThresholdPercent = mContext.getResources().getInteger(
2755                 R.integer.config_wifiLinkBandwidthUpdateThresholdPercent);
2756         if ((txDeltaKbps * 100  >  bwUpdateThresholdPercent * mLastTxKbps)
2757                 || (rxDeltaKbps * 100  >  bwUpdateThresholdPercent * mLastRxKbps)
2758                 || updateNetworkCapabilities) {
2759             mLastTxKbps = newTxKbps;
2760             mLastRxKbps = newRxKbps;
2761             updateCapabilities();
2762         }
2763 
2764         int l2TxKbps = mWifiDataStall.getTxThroughputKbps();
2765         int l2RxKbps = mWifiDataStall.getRxThroughputKbps();
2766         if (l2RxKbps < 0 && l2TxKbps > 0) {
2767             l2RxKbps = l2TxKbps;
2768         }
2769         int [] reportedKbps = {mLastTxKbps, mLastRxKbps};
2770         int [] l2Kbps = {l2TxKbps, l2RxKbps};
2771         network.updateBwMetrics(reportedKbps, l2Kbps);
2772     }
2773 
2774     // Polling has completed, hence we won't have a score anymore
cleanWifiScore()2775     private void cleanWifiScore() {
2776         mWifiInfo.setLostTxPacketsPerSecond(0);
2777         mWifiInfo.setSuccessfulTxPacketsPerSecond(0);
2778         mWifiInfo.setRetriedTxPacketsRate(0);
2779         mWifiInfo.setSuccessfulRxPacketsPerSecond(0);
2780         mWifiScoreReport.reset();
2781         mLastLinkLayerStats = null;
2782         updateCurrentConnectionInfo();
2783     }
2784 
updateLinkProperties(LinkProperties newLp)2785     private void updateLinkProperties(LinkProperties newLp) {
2786         if (mVerboseLoggingEnabled) {
2787             log("Link configuration changed for netId: " + mLastNetworkId
2788                     + " old: " + mLinkProperties + " new: " + newLp);
2789         }
2790         // We own this instance of LinkProperties because IpClient passes us a copy.
2791         mLinkProperties = newLp;
2792 
2793         if (mNetworkAgent != null) {
2794             mNetworkAgent.sendLinkProperties(mLinkProperties);
2795         }
2796 
2797         if (mNetworkAgentState == DetailedState.CONNECTED) {
2798             // If anything has changed and we're already connected, send out a notification.
2799             // TODO: Update all callers to use NetworkCallbacks and delete this.
2800             sendLinkConfigurationChangedBroadcast();
2801         }
2802         if (mVerboseLoggingEnabled) {
2803             StringBuilder sb = new StringBuilder();
2804             sb.append("updateLinkProperties nid: " + mLastNetworkId);
2805             sb.append(" state: " + mNetworkAgentState);
2806 
2807             if (mLinkProperties != null) {
2808                 sb.append(" ");
2809                 sb.append(getLinkPropertiesSummary(mLinkProperties));
2810             }
2811             logd(sb.toString());
2812         }
2813     }
2814 
2815     /**
2816      * Clears all our link properties.
2817      */
clearLinkProperties()2818     private void clearLinkProperties() {
2819         // Clear the link properties obtained from DHCP. The only caller of this
2820         // function has already called IpClient#stop(), which clears its state.
2821         synchronized (mDhcpResultsParcelableLock) {
2822             mDhcpResultsParcelable = new DhcpResultsParcelable();
2823         }
2824 
2825         // Now clear the merged link properties.
2826         mLinkProperties.clear();
2827         if (mNetworkAgent != null) mNetworkAgent.sendLinkProperties(mLinkProperties);
2828     }
2829 
2830     // TODO(b/193460475): Remove when tooling supports SystemApi to public API.
2831     @SuppressLint("NewApi")
sendRssiChangeBroadcast(final int newRssi)2832     private void sendRssiChangeBroadcast(final int newRssi) {
2833         mBatteryStatsManager.reportWifiRssiChanged(newRssi);
2834         WifiStatsLog.write(WifiStatsLog.WIFI_SIGNAL_STRENGTH_CHANGED,
2835                 RssiUtil.calculateSignalLevel(mContext, newRssi));
2836 
2837         Intent intent = new Intent(WifiManager.RSSI_CHANGED_ACTION);
2838         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2839         intent.putExtra(WifiManager.EXTRA_NEW_RSSI, newRssi);
2840         final Bundle opts;
2841         if (SdkLevel.isAtLeastU()) {
2842             opts = BroadcastOptions.makeBasic()
2843                     .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
2844                     .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
2845                     .toBundle();
2846         } else {
2847             opts = null;
2848         }
2849         mBroadcastQueue.queueOrSendBroadcast(
2850                 mClientModeManager,
2851                 () -> mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
2852                         android.Manifest.permission.ACCESS_WIFI_STATE, opts));
2853     }
2854 
sendLinkConfigurationChangedBroadcast()2855     private void sendLinkConfigurationChangedBroadcast() {
2856         Intent intent = new Intent(WifiManager.ACTION_LINK_CONFIGURATION_CHANGED);
2857         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2858         String summary = "broadcast=ACTION_LINK_CONFIGURATION_CHANGED";
2859         if (mVerboseLoggingEnabled) Log.d(getTag(), "Queuing " + summary);
2860         mBroadcastQueue.queueOrSendBroadcast(
2861                 mClientModeManager,
2862                 () -> {
2863                     if (mVerboseLoggingEnabled) Log.d(getTag(), "Sending " + summary);
2864                     mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2865                 });
2866     }
2867 
2868     /**
2869      * Helper method used to send state about supplicant - This is NOT information about the current
2870      * wifi connection state.
2871      *
2872      * TODO: b/79504296 This broadcast has been deprecated and should be removed
2873      */
sendSupplicantConnectionChangedBroadcast(boolean connected)2874     private void sendSupplicantConnectionChangedBroadcast(boolean connected) {
2875         Intent intent = new Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
2876         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2877         intent.putExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, connected);
2878         String summary = "broadcast=SUPPLICANT_CONNECTION_CHANGE_ACTION"
2879                 + " EXTRA_SUPPLICANT_CONNECTED=" + connected;
2880         if (mVerboseLoggingEnabled) Log.d(getTag(), "Queuing " + summary);
2881         mBroadcastQueue.queueOrSendBroadcast(
2882                 mClientModeManager,
2883                 () -> {
2884                     if (mVerboseLoggingEnabled) Log.d(getTag(), "Sending " + summary);
2885                     mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2886                 });
2887     }
2888 
2889     /**
2890      * Record the detailed state of a network.
2891      *
2892      * @param state the new {@code DetailedState}
2893      */
sendNetworkChangeBroadcast(NetworkInfo.DetailedState state)2894     private void sendNetworkChangeBroadcast(NetworkInfo.DetailedState state) {
2895         boolean hidden = false;
2896 
2897         if (mIsAutoRoaming) {
2898             // There is generally a confusion in the system about colluding
2899             // WiFi Layer 2 state (as reported by supplicant) and the Network state
2900             // which leads to multiple confusion.
2901             //
2902             // If link is roaming, we already have an IP address
2903             // as well we were connected and are doing L2 cycles of
2904             // reconnecting or renewing IP address to check that we still have it
2905             // This L2 link flapping should not be reflected into the Network state
2906             // which is the state of the WiFi Network visible to Layer 3 and applications
2907             // Note that once roaming is completed, we will
2908             // set the Network state to where it should be, or leave it as unchanged
2909             //
2910             hidden = true;
2911         }
2912         if (mVerboseLoggingEnabled) {
2913             log("sendNetworkChangeBroadcast"
2914                     + " oldState=" + mNetworkAgentState
2915                     + " newState=" + state
2916                     + " hidden=" + hidden);
2917         }
2918         if (hidden || state == mNetworkAgentState) return;
2919         mNetworkAgentState = state;
2920         sendNetworkChangeBroadcastWithCurrentState();
2921     }
2922 
getNetworkStateListenerCmmRole()2923     private int getNetworkStateListenerCmmRole() {
2924         if (isPrimary() || isScanOnly()) {
2925             // Wifi disconnect could be received in ScanOnlyMode when wifi scanning is enabled since
2926             // the mode switch happens before the disconnect actually happens. Therefore, treat
2927             // the scan only mode the same as primary since only the primary is allowed to change
2928             // into scan only mode.
2929             return WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY;
2930         }
2931         if (isSecondaryInternet()) {
2932             return WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_SECONDARY_INTERNET;
2933         }
2934         if (isLocalOnly()) {
2935             return WifiManager.WifiNetworkStateChangedListener
2936                     .WIFI_ROLE_CLIENT_SECONDARY_LOCAL_ONLY;
2937         }
2938         return -1;
2939     }
2940 
convertDetailedStateToNetworkStateChangedCode(DetailedState detailedState)2941     private int convertDetailedStateToNetworkStateChangedCode(DetailedState detailedState) {
2942         switch (detailedState) {
2943             case IDLE:
2944                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_IDLE;
2945             case SCANNING:
2946                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_SCANNING;
2947             case CONNECTING:
2948                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTING;
2949             case AUTHENTICATING:
2950                 return WifiManager.WifiNetworkStateChangedListener
2951                         .WIFI_NETWORK_STATUS_AUTHENTICATING;
2952             case OBTAINING_IPADDR:
2953                 return WifiManager.WifiNetworkStateChangedListener
2954                         .WIFI_NETWORK_STATUS_OBTAINING_IPADDR;
2955             case CONNECTED:
2956                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTED;
2957             case DISCONNECTED:
2958                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED;
2959             case FAILED:
2960                 return WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_FAILED;
2961             default:
2962                 // There are some DetailedState codes that are not being used in wifi, so ignore
2963                 // them.
2964                 return -1;
2965         }
2966     }
2967 
sendNetworkChangeBroadcastWithCurrentState()2968     private void sendNetworkChangeBroadcastWithCurrentState() {
2969         // copy into local variables to force lambda to capture by value and not reference, since
2970         // mNetworkAgentState is mutable and can change
2971         final DetailedState networkAgentState = mNetworkAgentState;
2972         if (mVerboseLoggingEnabled) {
2973             Log.d(getTag(), "Queueing broadcast=NETWORK_STATE_CHANGED_ACTION"
2974                     + " networkAgentState=" + networkAgentState);
2975         }
2976         int networkStateChangedCmmRole = getNetworkStateListenerCmmRole();
2977         int networkStateChangedState = convertDetailedStateToNetworkStateChangedCode(
2978                 networkAgentState);
2979         if (networkStateChangedCmmRole != -1 && networkStateChangedState != -1) {
2980             mWifiInjector.getActiveModeWarden().onNetworkStateChanged(
2981                     networkStateChangedCmmRole, networkStateChangedState);
2982         }
2983         mBroadcastQueue.queueOrSendBroadcast(
2984                 mClientModeManager,
2985                 () -> sendNetworkChangeBroadcast(
2986                         mContext, networkAgentState, mVerboseLoggingEnabled));
2987     }
2988 
2989     /** Send a NETWORK_STATE_CHANGED_ACTION broadcast. */
sendNetworkChangeBroadcast( Context context, DetailedState networkAgentState, boolean verboseLoggingEnabled)2990     public static void sendNetworkChangeBroadcast(
2991             Context context, DetailedState networkAgentState, boolean verboseLoggingEnabled) {
2992         Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
2993         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2994         NetworkInfo networkInfo = makeNetworkInfo(networkAgentState);
2995         intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
2996         if (verboseLoggingEnabled) {
2997             Log.d(TAG, "Sending broadcast=NETWORK_STATE_CHANGED_ACTION"
2998                     + " networkAgentState=" + networkAgentState);
2999         }
3000         //TODO(b/69974497) This should be non-sticky, but settings needs fixing first.
3001         if (SdkLevel.isAtLeastU()) {
3002             final Context userAllContext = context.createContextAsUser(
3003                     UserHandle.ALL, 0 /* flags */);
3004             final Bundle opts = BroadcastOptions.makeBasic()
3005                     .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
3006                     .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE)
3007                     .toBundle();
3008             userAllContext.sendStickyBroadcast(intent, opts);
3009         } else {
3010             context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
3011         }
3012     }
3013 
makeNetworkInfo(DetailedState networkAgentState)3014     private static NetworkInfo makeNetworkInfo(DetailedState networkAgentState) {
3015         final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
3016         ni.setDetailedState(networkAgentState, null, null);
3017         return ni;
3018     }
3019 
findMatchingInfoElements(@ullable String bssid)3020     private List<ScanResult.InformationElement> findMatchingInfoElements(@Nullable String bssid) {
3021         if (bssid == null) return null;
3022         ScanResult matchingScanResult = mScanRequestProxy.getScanResult(bssid);
3023         if (matchingScanResult == null || matchingScanResult.informationElements == null) {
3024             return null;
3025         }
3026         return Arrays.asList(matchingScanResult.informationElements);
3027     }
3028 
setMultiLinkInfoFromScanCache(@ullable String bssid)3029     private void setMultiLinkInfoFromScanCache(@Nullable String bssid) {
3030         if (bssid == null) return;
3031         ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(
3032                 mWifiInfo.getNetworkId());
3033         ScanResult matchingScanResult = null;
3034         if (scanDetailCache != null) {
3035             matchingScanResult = scanDetailCache.getScanResult(bssid);
3036         }
3037         /**
3038          * If FW roams to a new AP, the BSSID may not be in the scan detailed cache. Set Multi-Link
3039          * info only if the BSSID is present in the scan detailed cache and AP is a Multi-Link
3040          * Device. If not, clear Multi-Link info from WifiInfo. After association
3041          * {@link ClientModeImpl#updateMloLinkAddrAndStates(ConnectionMloLinksInfo)} will update
3042          * the Multi-Link info from supplicant if present.
3043          */
3044         if (matchingScanResult != null && matchingScanResult.getApMldMacAddress() != null) {
3045             mWifiInfo.setApMldMacAddress(matchingScanResult.getApMldMacAddress());
3046             mWifiInfo.setApMloLinkId(matchingScanResult.getApMloLinkId());
3047             mWifiInfo.setAffiliatedMloLinks(matchingScanResult.getAffiliatedMloLinks());
3048         } else {
3049             mWifiInfo.setApMldMacAddress(null);
3050             mWifiInfo.setApMloLinkId(MloLink.INVALID_MLO_LINK_ID);
3051             mWifiInfo.setAffiliatedMloLinks(Collections.emptyList());
3052         }
3053         updateCurrentConnectionInfo();
3054     }
3055 
3056     /**
3057      * Multi-link info should not be set from scan cache after 'SupplicantState.ASSOCIATED' as it
3058      * overwrites link states collected during ASSOCIATION. Return if multi-link info is settable
3059      * on the current state.
3060      */
isMultiLinkInfoSettableFromScanCache(SupplicantState currentState)3061     private boolean isMultiLinkInfoSettableFromScanCache(SupplicantState currentState) {
3062         return currentState != SupplicantState.FOUR_WAY_HANDSHAKE
3063                 && currentState != SupplicantState.GROUP_HANDSHAKE
3064                 && currentState != SupplicantState.COMPLETED;
3065     }
3066 
handleSupplicantStateChange(StateChangeResult stateChangeResult)3067     private SupplicantState handleSupplicantStateChange(StateChangeResult stateChangeResult) {
3068         SupplicantState state = stateChangeResult.state;
3069         mWifiScoreCard.noteSupplicantStateChanging(mWifiInfo, state);
3070         // Supplicant state change
3071         // [31-13] Reserved for future use
3072         // [8 - 0] Supplicant state (as defined in SupplicantState.java)
3073         // 50023 supplicant_state_changed (custom|1|5)
3074         mWifiInfo.setSupplicantState(state);
3075         // Network id and SSID are only valid when we start connecting
3076         if (SupplicantState.isConnecting(state)) {
3077             mWifiInfo.setNetworkId(stateChangeResult.networkId);
3078             mWifiInfo.setBSSID(stateChangeResult.bssid);
3079             mWifiInfo.setSSID(stateChangeResult.wifiSsid);
3080             if (stateChangeResult.frequencyMhz > 0) {
3081                 mWifiInfo.setFrequency(stateChangeResult.frequencyMhz);
3082             }
3083             // Multi-link info is set from scan cache (multi-link state: unassociated). On
3084             // association, connection capabilities and multi-link state are queried from
3085             // supplicant and link info is updated. (multi-link state: active/idle). After
3086             // association, don't set the multi-link info from scan cache.
3087             if (isMultiLinkInfoSettableFromScanCache(state)) {
3088                 setMultiLinkInfoFromScanCache(stateChangeResult.bssid);
3089             }
3090             if (state == SupplicantState.ASSOCIATED) {
3091                 updateWifiInfoLinkParamsAfterAssociation();
3092             }
3093             mWifiInfo.setInformationElements(findMatchingInfoElements(stateChangeResult.bssid));
3094         } else {
3095             // Reset parameters according to WifiInfo.reset()
3096             mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID());
3097             mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
3098             mWifiInfo.setBSSID(null);
3099             mWifiInfo.setSSID(null);
3100             mWifiInfo.setWifiStandard(ScanResult.WIFI_STANDARD_UNKNOWN);
3101             mWifiInfo.setInformationElements(null);
3102             mWifiInfo.clearCurrentSecurityType();
3103             mWifiInfo.resetMultiLinkInfo();
3104         }
3105 
3106         // SSID might have been updated, so call updateCapabilities
3107         updateCapabilities();
3108 
3109         WifiConfiguration config = getConnectedWifiConfigurationInternal();
3110         if (config == null) {
3111             // If not connected, this should be non-null.
3112             config = getConnectingWifiConfigurationInternal();
3113         }
3114         if (config != null && config.networkId == mWifiInfo.getNetworkId()) {
3115             updateWifiInfoWhenConnected(config);
3116 
3117             // Set meteredHint if scan result says network is expensive
3118             ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(
3119                     config.networkId);
3120             if (scanDetailCache != null) {
3121                 ScanDetail scanDetail = scanDetailCache.getScanDetail(stateChangeResult.bssid);
3122                 if (scanDetail != null) {
3123                     mWifiInfo.setFrequency(scanDetail.getScanResult().frequency);
3124                     NetworkDetail networkDetail = scanDetail.getNetworkDetail();
3125                     if (networkDetail != null
3126                             && networkDetail.getAnt() == NetworkDetail.Ant.ChargeablePublic) {
3127                         mWifiInfo.setMeteredHint(true);
3128                     }
3129                 }
3130             }
3131         }
3132         mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
3133         updateCurrentConnectionInfo();
3134         return state;
3135     }
3136 
handleNetworkConnectionEventInfo( WifiConfiguration config, NetworkConnectionEventInfo connectionInfo)3137     private void handleNetworkConnectionEventInfo(
3138             WifiConfiguration config, NetworkConnectionEventInfo connectionInfo) {
3139         if (connectionInfo == null) return;
3140 
3141         mWifiInfo.setBSSID(connectionInfo.bssid);
3142         mWifiInfo.setNetworkId(connectionInfo.networkId);
3143 
3144         if (config != null && connectionInfo.keyMgmtMask != null) {
3145             // Besides allowed key management, pmf and wep keys are necessary to
3146             // identify WPA3 Enterprise and WEP, so the original configuration
3147             // is still necessary.
3148             WifiConfiguration tmp = new WifiConfiguration(config);
3149             tmp.setSecurityParams(connectionInfo.keyMgmtMask);
3150             mWifiInfo.setCurrentSecurityType(tmp.getDefaultSecurityParams().getSecurityType());
3151             // Update the last used security params.
3152             config.getNetworkSelectionStatus().setLastUsedSecurityParams(
3153                     tmp.getDefaultSecurityParams());
3154             mWifiConfigManager.setNetworkLastUsedSecurityParams(config.networkId,
3155                     tmp.getDefaultSecurityParams());
3156             Log.i(getTag(), "Update current security type to " + mWifiInfo.getCurrentSecurityType()
3157                     + " from network connection event.");
3158         }
3159     }
3160 
updateWifiInfoWhenConnected(@onNull WifiConfiguration config)3161     private void updateWifiInfoWhenConnected(@NonNull WifiConfiguration config) {
3162         mWifiInfo.setEphemeral(config.ephemeral);
3163         mWifiInfo.setTrusted(config.trusted);
3164         mWifiInfo.setOemPaid(config.oemPaid);
3165         mWifiInfo.setOemPrivate(config.oemPrivate);
3166         mWifiInfo.setCarrierMerged(config.carrierMerged);
3167         mWifiInfo.setSubscriptionId(config.subscriptionId);
3168         mWifiInfo.setOsuAp(config.osu);
3169         mWifiInfo.setRestricted(config.restricted);
3170         if (config.fromWifiNetworkSpecifier || config.fromWifiNetworkSuggestion) {
3171             mWifiInfo.setRequestingPackageName(config.creatorName);
3172         }
3173         mWifiInfo.setIsPrimary(isPrimary());
3174         SecurityParams securityParams = config.getNetworkSelectionStatus()
3175                 .getLastUsedSecurityParams();
3176         if (securityParams != null) {
3177             Log.i(getTag(), "Update current security type to " + securityParams.getSecurityType());
3178             mWifiInfo.setCurrentSecurityType(securityParams.getSecurityType());
3179         } else {
3180             mWifiInfo.clearCurrentSecurityType();
3181             Log.e(TAG, "Network connection candidate with no security parameters");
3182         }
3183         updateCurrentConnectionInfo();
3184     }
3185 
3186     /**
3187      * Update mapping of affiliated BSSID in blocklist. Called when there is a change in MLO links.
3188      */
updateBlockListAffiliatedBssids()3189     private void updateBlockListAffiliatedBssids() {
3190         /**
3191          * getAffiliatedMloLinks() returns a list of MloLink objects for all the links
3192          * advertised by AP-MLD including the associated link. Update mWifiBlocklistMonitor
3193          * with all affiliated AP link MAC addresses, excluding the associated link, indexed
3194          * with associated AP link MAC address (BSSID).
3195          * For e.g.
3196          *  link1_bssid -> affiliated {link2_bssid, link3_bssid}
3197          * Above mapping is used to block list all affiliated links when associated link is
3198          * block listed.
3199          */
3200         List<String> affiliatedBssids = new ArrayList<>();
3201         for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) {
3202             if (link.getApMacAddress() != null && !Objects.equals(mWifiInfo.getBSSID(),
3203                     link.getApMacAddress().toString())) {
3204                 affiliatedBssids.add(link.getApMacAddress().toString());
3205             }
3206         }
3207         mWifiBlocklistMonitor.setAffiliatedBssids(mWifiInfo.getBSSID(), affiliatedBssids);
3208     }
3209 
3210     /**
3211      * Clear MLO link states to UNASSOCIATED.
3212      */
clearMloLinkStates()3213     private void clearMloLinkStates() {
3214         for (MloLink link : mWifiInfo.getAffiliatedMloLinks()) {
3215             link.setState(MloLink.MLO_LINK_STATE_UNASSOCIATED);
3216         }
3217     }
3218 
3219     /**
3220      * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the
3221      * link.
3222      *
3223      * @param info MLO link object from HAL.
3224      */
updateMloLinkStates(@ullable WifiNative.ConnectionMloLinksInfo info)3225     private void updateMloLinkStates(@Nullable WifiNative.ConnectionMloLinksInfo info) {
3226         if (info == null) return;
3227         for (int i = 0; i < info.links.length; i++) {
3228             mWifiInfo.updateMloLinkState(info.links[i].getLinkId(),
3229                     info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE
3230                             : MloLink.MLO_LINK_STATE_IDLE);
3231         }
3232     }
3233     /**
3234      * Update the MLO link states to ACTIVE or IDLE depending on any traffic stream is mapped to the
3235      * link. Also, update the link MAC address.
3236      *
3237      * @param info MLO link object from HAL.
3238      */
updateMloLinkAddrAndStates(@ullable WifiNative.ConnectionMloLinksInfo info)3239     private void updateMloLinkAddrAndStates(@Nullable WifiNative.ConnectionMloLinksInfo info) {
3240         if (info == null) return;
3241         // At this stage, the expectation is that we already have MLO link information collected
3242         // from scan detailed cache. If the MLO link information is empty, probably FW/driver roamed
3243         // to a new AP which is not in scan detailed cache. Update MLO links with the details
3244         // provided by the supplicant in ConnectionMloLinksInfo. The supplicant provides only the
3245         // associated links.
3246         if (mWifiInfo.getAffiliatedMloLinks().isEmpty()) {
3247             mWifiInfo.setApMldMacAddress(info.apMldMacAddress);
3248             mWifiInfo.setApMloLinkId(info.apMloLinkId);
3249             List<MloLink> affiliatedMloLinks = new ArrayList<>();
3250             for (int i = 0; i < info.links.length; i++) {
3251                 MloLink link = new MloLink();
3252                 link.setLinkId(info.links[i].getLinkId());
3253                 link.setStaMacAddress(info.links[i].getStaMacAddress());
3254                 link.setApMacAddress(info.links[i].getApMacAddress());
3255                 link.setChannel(ScanResult.convertFrequencyMhzToChannelIfSupported(
3256                         info.links[i].getFrequencyMHz()));
3257                 link.setBand(ScanResult.toBand(info.links[i].getFrequencyMHz()));
3258                 link.setState(info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE
3259                         : MloLink.MLO_LINK_STATE_IDLE);
3260                 affiliatedMloLinks.add(link);
3261             }
3262             mWifiInfo.setAffiliatedMloLinks(affiliatedMloLinks);
3263         } else {
3264             for (int i = 0; i < info.links.length; i++) {
3265                 mWifiInfo.updateMloLinkStaAddress(info.links[i].getLinkId(),
3266                         info.links[i].getStaMacAddress());
3267                 mWifiInfo.updateMloLinkState(info.links[i].getLinkId(),
3268                         info.links[i].isAnyTidMapped() ? MloLink.MLO_LINK_STATE_ACTIVE
3269                                 : MloLink.MLO_LINK_STATE_IDLE);
3270             }
3271         }
3272     }
3273 
updateWifiInfoLinkParamsAfterAssociation()3274     private void updateWifiInfoLinkParamsAfterAssociation() {
3275         mLastConnectionCapabilities = mWifiNative.getConnectionCapabilities(mInterfaceName);
3276         int maxTxLinkSpeedMbps = mThroughputPredictor.predictMaxTxThroughput(
3277                 mLastConnectionCapabilities);
3278         int maxRxLinkSpeedMbps = mThroughputPredictor.predictMaxRxThroughput(
3279                 mLastConnectionCapabilities);
3280         mWifiInfo.setWifiStandard(mLastConnectionCapabilities.wifiStandard);
3281         mWifiInfo.setMaxSupportedTxLinkSpeedMbps(maxTxLinkSpeedMbps);
3282         mWifiInfo.setMaxSupportedRxLinkSpeedMbps(maxRxLinkSpeedMbps);
3283         mWifiInfo.enableApTidToLinkMappingNegotiationSupport(
3284                 mLastConnectionCapabilities.apTidToLinkMapNegotiationSupported);
3285         mWifiMetrics.setConnectionMaxSupportedLinkSpeedMbps(mInterfaceName,
3286                 maxTxLinkSpeedMbps, maxRxLinkSpeedMbps);
3287         if (mLastConnectionCapabilities.wifiStandard == ScanResult.WIFI_STANDARD_11BE) {
3288             updateMloLinkAddrAndStates(mWifiNative.getConnectionMloLinksInfo(mInterfaceName));
3289             updateBlockListAffiliatedBssids();
3290         }
3291         if (mVerboseLoggingEnabled) {
3292             StringBuilder sb = new StringBuilder();
3293             logd(sb.append("WifiStandard: ").append(ScanResult.wifiStandardToString(
3294                             mLastConnectionCapabilities.wifiStandard))
3295                     .append(" maxTxSpeed: ").append(maxTxLinkSpeedMbps)
3296                     .append(" maxRxSpeed: ").append(maxRxLinkSpeedMbps)
3297                     .toString());
3298         }
3299         updateCurrentConnectionInfo();
3300     }
3301 
3302     /**
3303      * Tells IpClient what BSSID, L2Key and GroupHint to use for IpMemoryStore.
3304      */
updateLayer2Information()3305     private void updateLayer2Information() {
3306         if (mIpClient != null) {
3307             Pair<String, String> p = mWifiScoreCard.getL2KeyAndGroupHint(mWifiInfo);
3308             if (!p.equals(mLastL2KeyAndGroupHint)) {
3309                 final MacAddress currentBssid =
3310                         NativeUtil.getMacAddressOrNull(mWifiInfo.getBSSID());
3311                 final Layer2Information l2Information = new Layer2Information(
3312                         p.first, p.second, currentBssid);
3313                 // Update current BSSID on IpClient side whenever l2Key and groupHint
3314                 // pair changes (i.e. the initial connection establishment or L2 roaming
3315                 // happened). If we have COMPLETED the roaming to a different BSSID, start
3316                 // doing DNAv4/DNAv6 -style probing for on-link neighbors of interest (e.g.
3317                 // routers/DNS servers/default gateway).
3318                 if (mIpClient.updateLayer2Information(l2Information)) {
3319                     mLastL2KeyAndGroupHint = p;
3320                 } else {
3321                     mLastL2KeyAndGroupHint = null;
3322                 }
3323             }
3324         }
3325     }
3326     private @Nullable Pair<String, String> mLastL2KeyAndGroupHint = null;
3327 
3328     /**
3329      * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
3330      * using the interface, stopping DHCP & disabling interface
3331      *
3332      * @param disconnectReason must be one of WifiDisconnectReported.FailureReason values
3333      *                         defined in /frameworks/proto_logging/stats/atoms.proto
3334      */
handleNetworkDisconnect(boolean newConnectionInProgress, int disconnectReason)3335     private void handleNetworkDisconnect(boolean newConnectionInProgress, int disconnectReason) {
3336         mWifiMetrics.reportNetworkDisconnect(mInterfaceName, disconnectReason,
3337                 mWifiInfo.getRssi(),
3338                 mWifiInfo.getLinkSpeed());
3339 
3340         if (mVerboseLoggingEnabled) {
3341             Log.v(getTag(), "handleNetworkDisconnect: newConnectionInProgress: "
3342                     + newConnectionInProgress, new Throwable());
3343         }
3344 
3345         if (isPrimary()) {
3346             WifiConfiguration wifiConfig = getConnectedWifiConfigurationInternal();
3347             if (wifiConfig != null) {
3348                 ScanResultMatchInfo matchInfo =
3349                         ScanResultMatchInfo.fromWifiConfiguration(wifiConfig);
3350                 // WakeupController should only care about the primary, internet providing network
3351                 mWakeupController.setLastDisconnectInfo(matchInfo);
3352             }
3353             mRssiMonitor.reset();
3354         }
3355 
3356         clearTargetBssid("handleNetworkDisconnect");
3357 
3358         // Don't stop DHCP if Fils connection is in progress.
3359         if (newConnectionInProgress && mIpClientWithPreConnection) {
3360             if (mVerboseLoggingEnabled) {
3361                 log("handleNetworkDisconnect: Don't stop IpClient as fils connection in progress: "
3362                         + " mLastNetworkId: " + mLastNetworkId
3363                         + " mTargetNetworkId" + mTargetNetworkId);
3364             }
3365         } else {
3366             stopDhcpSetup();
3367         }
3368 
3369         // DISASSOC_AP_BUSY could be received in both after L3 connection is successful or right
3370         // after BSSID association if the AP can't accept more stations.
3371         if (disconnectReason == StaIfaceReasonCode.DISASSOC_AP_BUSY) {
3372             mWifiConfigManager.setRecentFailureAssociationStatus(
3373                     mWifiInfo.getNetworkId(),
3374                     WifiConfiguration.RECENT_FAILURE_DISCONNECTION_AP_BUSY);
3375         }
3376 
3377         mWifiScoreReport.stopConnectedNetworkScorer();
3378         /* Reset data structures */
3379         mWifiScoreReport.reset();
3380         mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID());
3381         mWifiInfo.reset();
3382         /* Reset roaming parameters */
3383         mIsAutoRoaming = false;
3384 
3385         sendNetworkChangeBroadcast(DetailedState.DISCONNECTED);
3386         if (mNetworkAgent != null) {
3387             mNetworkAgent.unregister();
3388             mNetworkAgent = null;
3389             mQosPolicyRequestHandler.setNetworkAgent(null);
3390         }
3391 
3392         /* Clear network properties */
3393         clearLinkProperties();
3394 
3395         mLastBssid = null;
3396         mLastLinkLayerStats = null;
3397         registerDisconnected();
3398         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
3399         mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
3400         mCurrentConnectionDetectedCaptivePortal = false;
3401         mLastSimBasedConnectionCarrierName = null;
3402         checkAbnormalDisconnectionAndTakeBugReport();
3403         mWifiScoreCard.resetConnectionState(mInterfaceName);
3404         updateLayer2Information();
3405         // If there is new connection in progress, this is for the new connection, so keept it.
3406         if (!newConnectionInProgress) {
3407             mIsUserSelected = false;
3408         }
3409         updateCurrentConnectionInfo();
3410     }
3411 
handlePreDhcpSetup()3412     void handlePreDhcpSetup() {
3413         if (!mWifiGlobals.isBluetoothConnected()) {
3414             /*
3415              * There are problems setting the Wi-Fi driver's power
3416              * mode to active when bluetooth coexistence mode is
3417              * enabled or sense.
3418              * <p>
3419              * We set Wi-Fi to active mode when
3420              * obtaining an IP address because we've found
3421              * compatibility issues with some routers with low power
3422              * mode.
3423              * <p>
3424              * In order for this active power mode to properly be set,
3425              * we disable coexistence mode until we're done with
3426              * obtaining an IP address.  One exception is if we
3427              * are currently connected to a headset, since disabling
3428              * coexistence would interrupt that connection.
3429              */
3430             // Disable the coexistence mode
3431             mWifiNative.setBluetoothCoexistenceMode(
3432                     mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_DISABLED);
3433         }
3434 
3435         // Disable power save and suspend optimizations during DHCP
3436         // Note: The order here is important for now. Brcm driver changes
3437         // power settings when we control suspend mode optimizations.
3438         // TODO: Remove this comment when the driver is fixed.
3439         setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, false);
3440         setPowerSave(POWER_SAVE_CLIENT_DHCP, false);
3441 
3442         // Update link layer stats
3443         getWifiLinkLayerStats();
3444 
3445         if (mWifiP2pConnection.isConnected()) {
3446             // P2P discovery breaks DHCP, so shut it down in order to get through this.
3447             // Once P2P service receives this message and processes it accordingly, it is supposed
3448             // to send arg2 (i.e. CMD_PRE_DHCP_ACTION_COMPLETE) in a new Message.what back to
3449             // ClientModeImpl so that we can continue.
3450             // TODO(b/159060934): Need to ensure that CMD_PRE_DHCP_ACTION_COMPLETE is sent back to
3451             //  the ClientModeImpl instance that originally sent it. Right now it is sent back to
3452             //  all ClientModeImpl instances by WifiP2pConnection.
3453             mWifiP2pConnection.sendMessage(
3454                     WifiP2pServiceImpl.BLOCK_DISCOVERY,
3455                     WifiP2pServiceImpl.ENABLED,
3456                     CMD_PRE_DHCP_ACTION_COMPLETE);
3457         } else {
3458             // If the p2p service is not running, we can proceed directly.
3459             sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE);
3460         }
3461     }
3462 
addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets)3463     void addLayer2PacketsToHlpReq(List<Layer2PacketParcelable> packets) {
3464         List<Layer2PacketParcelable> mLayer2Packet = packets;
3465         if ((mLayer2Packet != null) && (mLayer2Packet.size() > 0)) {
3466             mWifiNative.flushAllHlp(mInterfaceName);
3467 
3468             for (int j = 0; j < mLayer2Packet.size(); j++) {
3469                 byte [] bytes = mLayer2Packet.get(j).payload;
3470                 byte [] payloadBytes = Arrays.copyOfRange(bytes, 12, bytes.length);
3471                 MacAddress dstAddress = mLayer2Packet.get(j).dstMacAddress;
3472 
3473                 mWifiNative.addHlpReq(mInterfaceName, dstAddress, payloadBytes);
3474             }
3475         }
3476     }
3477 
handlePostDhcpSetup()3478     void handlePostDhcpSetup() {
3479         /* Restore power save and suspend optimizations */
3480         setSuspendOptimizationsNative(SUSPEND_DUE_TO_DHCP, true);
3481         setPowerSave(POWER_SAVE_CLIENT_DHCP, true);
3482 
3483         mWifiP2pConnection.sendMessage(
3484                 WifiP2pServiceImpl.BLOCK_DISCOVERY, WifiP2pServiceImpl.DISABLED);
3485 
3486         // Set the coexistence mode back to its default value
3487         mWifiNative.setBluetoothCoexistenceMode(
3488                 mInterfaceName, WifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
3489     }
3490 
3491     /**
3492      * Set power save mode
3493      *
3494      * @param ps true to enable power save (default behavior)
3495      *           false to disable power save.
3496      * @return true for success, false for failure
3497      */
setPowerSave(@owerSaveClientType int client, boolean ps)3498     public boolean setPowerSave(@PowerSaveClientType int client, boolean ps) {
3499         if (mInterfaceName != null) {
3500             if (mVerboseLoggingEnabled) {
3501                 Log.d(getTag(), "Request to set power save for: " + mInterfaceName + " to: " + ps
3502                         + " requested by: " + client + ", mPowerSaveDisableRequests = "
3503                         + mPowerSaveDisableRequests);
3504             }
3505             if (ps) {
3506                 mPowerSaveDisableRequests &= ~client;
3507             } else {
3508                 mPowerSaveDisableRequests |= client;
3509             }
3510             boolean actualPs = mPowerSaveDisableRequests == 0;
3511             if (mVerboseLoggingEnabled) {
3512                 Log.d(getTag(), "Setting power save to: " + actualPs
3513                         + ", mPowerSaveDisableRequests = " + mPowerSaveDisableRequests);
3514             }
3515 
3516             mWifiNative.setPowerSave(mInterfaceName, actualPs);
3517         } else {
3518             Log.e(getTag(), "Failed to setPowerSave, interfaceName is null");
3519             return false;
3520         }
3521         return true;
3522     }
3523 
3524     /**
3525      * Enable power save.
3526      *
3527      * @return true for success, false for failure.
3528      */
enablePowerSave()3529     public boolean enablePowerSave() {
3530         return setPowerSave(~0, true);
3531     }
3532 
3533     /**
3534      * Set low latency mode
3535      *
3536      * @param enabled true to enable low latency
3537      *                false to disable low latency (default behavior).
3538      * @return true for success, false for failure
3539      */
setLowLatencyMode(boolean enabled)3540     public boolean setLowLatencyMode(boolean enabled) {
3541         if (mVerboseLoggingEnabled) {
3542             Log.d(getTag(), "Setting low latency mode to " + enabled);
3543         }
3544         if (!mWifiNative.setLowLatencyMode(enabled)) {
3545             Log.e(getTag(), "Failed to setLowLatencyMode");
3546             return false;
3547         }
3548         return true;
3549     }
3550 
getClientRoleForMetrics(WifiConfiguration config)3551     private int getClientRoleForMetrics(WifiConfiguration config) {
3552         ActiveModeManager.ClientRole clientRole = mClientModeManager.getRole();
3553         if (clientRole == ROLE_CLIENT_PRIMARY) {
3554             return config != null && config.fromWifiNetworkSpecifier
3555                     ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY
3556                     : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY;
3557         } else if (clientRole == ROLE_CLIENT_LOCAL_ONLY) {
3558             return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY;
3559         } else if (clientRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) {
3560             return mClientModeManager.isSecondaryInternet()
3561                     ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET
3562                     : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED;
3563         } else if (clientRole == ROLE_CLIENT_SECONDARY_TRANSIENT) {
3564             return WifiStatsLog
3565                     .WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT;
3566         }
3567         return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS;
3568     }
3569 
3570     /**
3571      * Inform other components that a new connection attempt is starting.
3572      */
reportConnectionAttemptStart( WifiConfiguration config, String targetBSSID, int roamType)3573     private void reportConnectionAttemptStart(
3574             WifiConfiguration config, String targetBSSID, int roamType) {
3575         boolean isOobPseudonymEnabled = false;
3576         if (config.enterpriseConfig != null && config.enterpriseConfig.isAuthenticationSimBased()
3577                 && mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(config.carrierId)) {
3578             isOobPseudonymEnabled = true;
3579         }
3580         int overlapWithLastConnectionMs =
3581                 mWifiMetrics.startConnectionEvent(
3582                         mInterfaceName, config, targetBSSID, roamType, isOobPseudonymEnabled,
3583                         getClientRoleForMetrics(config));
3584         if (mDeviceConfigFacade.isOverlappingConnectionBugreportEnabled()
3585                 && overlapWithLastConnectionMs
3586                 > mDeviceConfigFacade.getOverlappingConnectionDurationThresholdMs()) {
3587             String bugTitle = "Wi-Fi BugReport: overlapping connection";
3588             String bugDetail = "Detect abnormal overlapping connection";
3589             mWifiDiagnostics.takeBugReport(bugTitle, bugDetail);
3590         }
3591         mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED,
3592                 mClientModeManager);
3593         if (isPrimary()) {
3594             mWrongPasswordNotifier.onNewConnectionAttempt();
3595         }
3596     }
3597 
handleConnectionAttemptEndForDiagnostics(int level2FailureCode)3598     private void handleConnectionAttemptEndForDiagnostics(int level2FailureCode) {
3599         switch (level2FailureCode) {
3600             case WifiMetrics.ConnectionEvent.FAILURE_NONE:
3601                 break;
3602             case WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED:
3603                 // WifiDiagnostics doesn't care about pre-empted connections, or cases
3604                 // where we failed to initiate a connection attempt with supplicant.
3605                 break;
3606             case WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE:
3607                 mWifiDiagnostics.reportConnectionEvent(
3608                         WifiDiagnostics.CONNECTION_EVENT_TIMEOUT, mClientModeManager);
3609                 break;
3610             default:
3611                 mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED,
3612                         mClientModeManager);
3613         }
3614     }
3615 
3616     /**
3617      * Inform other components (WifiMetrics, WifiDiagnostics, WifiConnectivityManager, etc.) that
3618      * the current connection attempt has concluded.
3619      */
reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode, int level2FailureReason)3620     private void reportConnectionAttemptEnd(int level2FailureCode, int connectivityFailureCode,
3621             int level2FailureReason) {
3622         // if connected, this should be non-null.
3623         WifiConfiguration configuration = getConnectedWifiConfigurationInternal();
3624         if (configuration == null) {
3625             // If not connected, this should be non-null.
3626             configuration = getConnectingWifiConfigurationInternal();
3627         }
3628         if (configuration == null) {
3629             Log.e(TAG, "Unexpected null WifiConfiguration. Config may have been removed.");
3630             return;
3631         }
3632 
3633         String bssid = mLastBssid == null ? mTargetBssid : mLastBssid;
3634         String ssid = mWifiInfo.getSSID();
3635         if (WifiManager.UNKNOWN_SSID.equals(ssid)) {
3636             ssid = getConnectingSsidInternal();
3637         }
3638         if (level2FailureCode != WifiMetrics.ConnectionEvent.FAILURE_NONE) {
3639             int blocklistReason = convertToWifiBlocklistMonitorFailureReason(
3640                     level2FailureCode, level2FailureReason);
3641             if (blocklistReason != -1) {
3642                 mWifiScoreCard.noteConnectionFailure(mWifiInfo, mLastScanRssi, ssid,
3643                         blocklistReason);
3644                 checkAbnormalConnectionFailureAndTakeBugReport(ssid);
3645                 mWifiBlocklistMonitor.handleBssidConnectionFailure(bssid, configuration,
3646                         blocklistReason, mLastScanRssi);
3647                 WifiScoreCard.NetworkConnectionStats recentStats = mWifiScoreCard.lookupNetwork(
3648                         ssid).getRecentStats();
3649                 // Skip the secondary internet connection failure for association rejection
3650                 final boolean shouldSkip = isSecondaryInternet() &&
3651                         (level2FailureCode
3652                                 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT
3653                                 || level2FailureCode
3654                                 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION);
3655                 if (recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_CONNECTION_FAILURE)
3656                         >= WifiBlocklistMonitor.NUM_CONSECUTIVE_FAILURES_PER_NETWORK_EXP_BACKOFF
3657                         && configuration.getNetworkSelectionStatus().isNetworkEnabled()
3658                         && !shouldSkip) {
3659                     mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId,
3660                             WifiConfiguration.NetworkSelectionStatus.DISABLED_CONSECUTIVE_FAILURES);
3661                 }
3662                 if (recentStats.getCount(WifiScoreCard.CNT_CONSECUTIVE_WRONG_PASSWORD_FAILURE)
3663                         >= THRESHOLD_TO_PERM_WRONG_PASSWORD) {
3664                     mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId,
3665                             WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD);
3666                 }
3667             }
3668         }
3669 
3670         if (configuration.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
3671             if (level2FailureCode == WifiMetrics.ConnectionEvent.FAILURE_NONE) {
3672                 mWifiMetrics.incrementNumOfCarrierWifiConnectionSuccess();
3673             } else if (level2FailureCode
3674                             == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE
3675                     && level2FailureReason
3676                             != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE) {
3677                 mWifiMetrics.incrementNumOfCarrierWifiConnectionAuthFailure();
3678             } else {
3679                 mWifiMetrics.incrementNumOfCarrierWifiConnectionNonAuthFailure();
3680             }
3681         }
3682 
3683         boolean isAssociationRejection = level2FailureCode
3684                 == WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION;
3685         boolean isAuthenticationFailure = level2FailureCode
3686                 == WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE
3687                 && level2FailureReason != WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD;
3688         if ((isAssociationRejection || isAuthenticationFailure)
3689                 && mWifiConfigManager.isInFlakyRandomizationSsidHotlist(mTargetNetworkId)
3690                 && isPrimary()) {
3691             mConnectionFailureNotifier
3692                     .showFailedToConnectDueToNoRandomizedMacSupportNotification(mTargetNetworkId);
3693         }
3694 
3695         ScanResult candidate = configuration.getNetworkSelectionStatus().getCandidate();
3696         int frequency = mWifiInfo.getFrequency();
3697         if (frequency == WifiInfo.UNKNOWN_FREQUENCY && candidate != null) {
3698             frequency = candidate.frequency;
3699         }
3700         mWifiMetrics.endConnectionEvent(mInterfaceName, level2FailureCode,
3701                 connectivityFailureCode, level2FailureReason, frequency);
3702         mWifiConnectivityManager.handleConnectionAttemptEnded(
3703                 mClientModeManager, level2FailureCode, level2FailureReason, bssid,
3704                 configuration);
3705         mNetworkFactory.handleConnectionAttemptEnded(level2FailureCode, configuration, bssid,
3706                 level2FailureReason);
3707         mWifiNetworkSuggestionsManager.handleConnectionAttemptEnded(
3708                 level2FailureCode, configuration, getConnectedBssidInternal());
3709         if (candidate != null
3710                 && !TextUtils.equals(candidate.BSSID, getConnectedBssidInternal())) {
3711             mWifiMetrics.incrementNumBssidDifferentSelectionBetweenFrameworkAndFirmware();
3712         }
3713         handleConnectionAttemptEndForDiagnostics(level2FailureCode);
3714     }
3715 
3716     /* If this connection attempt fails after 802.1x stage, clear intermediate cached data. */
clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason)3717     void clearNetworkCachedDataIfNeeded(WifiConfiguration config, int reason) {
3718         if (config == null) return;
3719 
3720         switch(reason) {
3721             case StaIfaceReasonCode.UNSPECIFIED:
3722             case StaIfaceReasonCode.DEAUTH_LEAVING:
3723                 logi("Keep PMK cache for network disconnection reason " + reason);
3724                 break;
3725             default:
3726                 mWifiNative.removeNetworkCachedData(config.networkId);
3727                 break;
3728         }
3729     }
3730 
3731     /**
3732      * Returns the sufficient RSSI for the frequency that this network is last seen on.
3733      */
getSufficientRssi(int networkId, String bssid)3734     private int getSufficientRssi(int networkId, String bssid) {
3735         ScanDetailCache scanDetailCache =
3736                 mWifiConfigManager.getScanDetailCacheForNetwork(networkId);
3737         if (scanDetailCache == null) {
3738             return WifiInfo.INVALID_RSSI;
3739         }
3740         ScanResult scanResult = scanDetailCache.getScanResult(bssid);
3741         if (scanResult == null) {
3742             return WifiInfo.INVALID_RSSI;
3743         }
3744         return mScoringParams.getSufficientRssi(scanResult.frequency);
3745     }
3746 
convertToWifiBlocklistMonitorFailureReason( int level2FailureCode, int failureReason)3747     private int convertToWifiBlocklistMonitorFailureReason(
3748             int level2FailureCode, int failureReason) {
3749         switch (level2FailureCode) {
3750             case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT:
3751                 return WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT;
3752             case WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION:
3753                 if (failureReason == WifiMetricsProto.ConnectionEvent
3754                         .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA) {
3755                     return WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA;
3756                 }
3757                 return WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION;
3758             case WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE:
3759                 if (failureReason == WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD) {
3760                     return WifiBlocklistMonitor.REASON_WRONG_PASSWORD;
3761                 } else if (failureReason == WifiMetricsProto.ConnectionEvent
3762                         .AUTH_FAILURE_EAP_FAILURE) {
3763                     return WifiBlocklistMonitor.REASON_EAP_FAILURE;
3764                 }
3765                 return WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE;
3766             case WifiMetrics.ConnectionEvent.FAILURE_DHCP:
3767                 return WifiBlocklistMonitor.REASON_DHCP_FAILURE;
3768             case WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION:
3769                 if (failureReason == WifiMetricsProto.ConnectionEvent.DISCONNECTION_NON_LOCAL) {
3770                     return WifiBlocklistMonitor.REASON_NONLOCAL_DISCONNECT_CONNECTING;
3771                 }
3772                 return -1;
3773             case WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE:
3774                 return WifiBlocklistMonitor.REASON_FAILURE_NO_RESPONSE;
3775             default:
3776                 return -1;
3777         }
3778     }
3779 
handleIPv4Success(DhcpResultsParcelable dhcpResults)3780     private void handleIPv4Success(DhcpResultsParcelable dhcpResults) {
3781         if (mVerboseLoggingEnabled) {
3782             logd("handleIPv4Success <" + dhcpResults.toString() + ">");
3783             logd("link address " + dhcpResults.baseConfiguration.getIpAddress());
3784         }
3785 
3786         Inet4Address addr;
3787         synchronized (mDhcpResultsParcelableLock) {
3788             mDhcpResultsParcelable = dhcpResults;
3789             addr = (Inet4Address) dhcpResults.baseConfiguration.getIpAddress().getAddress();
3790         }
3791 
3792         if (mIsAutoRoaming) {
3793             int previousAddress = mWifiInfo.getIpAddress();
3794             int newAddress = Inet4AddressUtils.inet4AddressToIntHTL(addr);
3795             if (previousAddress != newAddress) {
3796                 logd("handleIPv4Success, roaming and address changed"
3797                         + mWifiInfo + " got: " + addr);
3798             }
3799         }
3800 
3801         mWifiInfo.setInetAddress(addr);
3802 
3803         final WifiConfiguration config = getConnectedWifiConfigurationInternal();
3804         if (config != null) {
3805             updateWifiInfoWhenConnected(config);
3806             mWifiConfigManager.updateRandomizedMacExpireTime(config, dhcpResults.leaseDuration);
3807             mWifiBlocklistMonitor.handleDhcpProvisioningSuccess(mLastBssid, mWifiInfo.getSSID());
3808         }
3809 
3810         // Set meteredHint if DHCP result says network is metered
3811         if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) {
3812             mWifiInfo.setMeteredHint(true);
3813             mWifiMetrics.addMeteredStat(config, true);
3814         } else {
3815             mWifiMetrics.addMeteredStat(config, false);
3816         }
3817 
3818         updateCapabilities();
3819         updateCurrentConnectionInfo();
3820     }
3821 
handleSuccessfulIpConfiguration()3822     private void handleSuccessfulIpConfiguration() {
3823         mLastSignalLevel = -1; // Force update of signal strength
3824         WifiConfiguration c = getConnectedWifiConfigurationInternal();
3825         if (c != null) {
3826             // Reset IP failure tracking
3827             c.getNetworkSelectionStatus().clearDisableReasonCounter(
3828                     WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
3829         }
3830     }
3831 
handleIPv4Failure()3832     private void handleIPv4Failure() {
3833         // TODO: Move this to provisioning failure, not DHCP failure.
3834         // DHCPv4 failure is expected on an IPv6-only network.
3835         mWifiDiagnostics.triggerBugReportDataCapture(WifiDiagnostics.REPORT_REASON_DHCP_FAILURE);
3836         if (mVerboseLoggingEnabled) {
3837             int count = -1;
3838             WifiConfiguration config = getConnectedWifiConfigurationInternal();
3839             if (config != null) {
3840                 count = config.getNetworkSelectionStatus().getDisableReasonCounter(
3841                         WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
3842             }
3843             log("DHCP failure count=" + count);
3844         }
3845         synchronized (mDhcpResultsParcelableLock) {
3846             mDhcpResultsParcelable = new DhcpResultsParcelable();
3847         }
3848         if (mVerboseLoggingEnabled) {
3849             logd("handleIPv4Failure");
3850         }
3851     }
3852 
handleIpConfigurationLost()3853     private void handleIpConfigurationLost() {
3854         mWifiInfo.setInetAddress(null);
3855         mWifiInfo.setMeteredHint(false);
3856 
3857         mWifiConfigManager.updateNetworkSelectionStatus(mLastNetworkId,
3858                 WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE);
3859 
3860         /* DHCP times out after about 30 seconds, we do a
3861          * disconnect thru supplicant, we will let autojoin retry connecting to the network
3862          */
3863         mWifiNative.disconnect(mInterfaceName);
3864         updateCurrentConnectionInfo();
3865     }
3866 
handleIpReachabilityLost()3867     private void handleIpReachabilityLost() {
3868         mWifiBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
3869                 getConnectedWifiConfiguration(),
3870                 WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, mWifiInfo.getRssi());
3871         mWifiScoreCard.noteIpReachabilityLost(mWifiInfo);
3872         mWifiInfo.setInetAddress(null);
3873         mWifiInfo.setMeteredHint(false);
3874 
3875         // Disconnect via supplicant, and let autojoin retry connecting to the network.
3876         mWifiNative.disconnect(mInterfaceName);
3877         updateCurrentConnectionInfo();
3878     }
3879 
3880     /**
3881      * Process IP Reachability failures by recreating a new IpClient instance to refresh L3
3882      * provisioning while keeping L2 still connected.
3883      *
3884      * This method is invoked only upon receiving reachability failure post roaming or triggered
3885      * from Wi-Fi RSSI polling or organic kernel probe.
3886      */
processIpReachabilityFailure()3887     private void processIpReachabilityFailure() {
3888         WifiConfiguration config = getConnectedWifiConfigurationInternal();
3889         if (config == null) {
3890             // special case for IP reachability lost which happens right after linked network
3891             // roaming. The linked network roaming reset the mLastNetworkId which results in
3892             // the connected configuration to be null.
3893             config = getConnectingWifiConfigurationInternal();
3894         }
3895         if (config == null) {
3896             // config could be null if it had been removed from WifiConfigManager. In this case
3897             // we should simply disconnect.
3898             handleIpReachabilityLost();
3899             return;
3900         }
3901         final NetworkAgentConfig naConfig = getNetworkAgentConfigInternal(config);
3902         final NetworkCapabilities nc = getCapabilities(
3903                 getConnectedWifiConfigurationInternal(), getConnectedBssidInternal());
3904 
3905         mWifiInfo.setInetAddress(null);
3906         if (mNetworkAgent != null) {
3907             if (SdkLevel.isAtLeastT()) {
3908                 mNetworkAgent.unregisterAfterReplacement(NETWORK_AGENT_TEARDOWN_DELAY_MS);
3909             } else {
3910                 mNetworkAgent.unregister();
3911             }
3912         }
3913         mNetworkAgent = mWifiInjector.makeWifiNetworkAgent(nc, mLinkProperties, naConfig,
3914                 mNetworkFactory.getProvider(), new WifiNetworkAgentCallback());
3915         mWifiScoreReport.setNetworkAgent(mNetworkAgent);
3916         if (SdkLevel.isAtLeastT()) {
3917             mQosPolicyRequestHandler.setNetworkAgent(mNetworkAgent);
3918         }
3919 
3920         transitionTo(mWaitBeforeL3ProvisioningState);
3921 
3922         updateCurrentConnectionInfo();
3923     }
3924 
processLegacyIpReachabilityLost()3925     private void processLegacyIpReachabilityLost() {
3926         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_IP_REACHABILITY_LOST);
3927         mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName,
3928                 WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
3929         mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
3930                 WifiUsabilityStats.LABEL_BAD,
3931                 WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
3932         if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) {
3933             handleIpReachabilityLost();
3934         } else {
3935             logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore");
3936         }
3937     }
3938 
handleIpReachabilityFailure(@onNull ReachabilityLossInfoParcelable lossInfo)3939     private void handleIpReachabilityFailure(@NonNull ReachabilityLossInfoParcelable lossInfo) {
3940         if (lossInfo == null) {
3941             Log.e(getTag(), "lossInfo should never be null");
3942             processLegacyIpReachabilityLost();
3943             return;
3944         }
3945 
3946         switch (lossInfo.reason) {
3947             case ReachabilityLossReason.ROAM:
3948                 processIpReachabilityFailure();
3949                 break;
3950             case ReachabilityLossReason.CONFIRM:
3951             case ReachabilityLossReason.ORGANIC:
3952                 if (mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()) {
3953                     processIpReachabilityFailure();
3954                 } else {
3955                     processLegacyIpReachabilityLost();
3956                 }
3957                 break;
3958             default:
3959                 logd("Invalid failure reason " + lossInfo.reason + "from onIpReachabilityFailure");
3960         }
3961     }
3962 
getNetworkAgentConfigInternal(WifiConfiguration config)3963     private NetworkAgentConfig getNetworkAgentConfigInternal(WifiConfiguration config) {
3964         boolean explicitlySelected = false;
3965         // Non primary CMMs is never user selected. This prevents triggering the No Internet
3966         // dialog for those networks, which is difficult to handle.
3967         if (isPrimary() && isRecentlySelectedByTheUser(config)) {
3968             // If explicitlySelected is true, the network was selected by the user via Settings
3969             // or QuickSettings. If this network has Internet access, switch to it. Otherwise,
3970             // switch to it only if the user confirms that they really want to switch, or has
3971             // already confirmed and selected "Don't ask again".
3972             explicitlySelected =
3973                     mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid);
3974             if (mVerboseLoggingEnabled) {
3975                 log("Network selected by UID " + config.lastConnectUid
3976                         + " explicitlySelected=" + explicitlySelected);
3977             }
3978         }
3979         NetworkAgentConfig.Builder naConfigBuilder = new NetworkAgentConfig.Builder()
3980                 .setLegacyType(ConnectivityManager.TYPE_WIFI)
3981                 .setLegacyTypeName(NETWORKTYPE)
3982                 .setExplicitlySelected(explicitlySelected)
3983                 .setUnvalidatedConnectivityAcceptable(
3984                         explicitlySelected && config.noInternetAccessExpected)
3985                 .setPartialConnectivityAcceptable(config.noInternetAccessExpected);
3986         if (config.carrierMerged) {
3987             String subscriberId = null;
3988             TelephonyManager subMgr = mTelephonyManager.createForSubscriptionId(
3989                     config.subscriptionId);
3990             if (subMgr != null) {
3991                 subscriberId = subMgr.getSubscriberId();
3992             }
3993             if (subscriberId != null) {
3994                 naConfigBuilder.setSubscriberId(subscriberId);
3995             }
3996         }
3997         if (mVcnManager == null && SdkLevel.isAtLeastS()) {
3998             mVcnManager = mContext.getSystemService(VcnManager.class);
3999         }
4000         if (mVcnManager != null && mVcnPolicyChangeListener == null && SdkLevel.isAtLeastS()) {
4001             mVcnPolicyChangeListener = new WifiVcnNetworkPolicyChangeListener();
4002             mVcnManager.addVcnNetworkPolicyChangeListener(new HandlerExecutor(getHandler()),
4003                     mVcnPolicyChangeListener);
4004         }
4005         return naConfigBuilder.build();
4006     }
4007 
4008     /*
4009      * Read a MAC address in /proc/net/arp, used by ClientModeImpl
4010      * so as to record MAC address of default gateway.
4011      **/
macAddressFromRoute(String ipAddress)4012     private String macAddressFromRoute(String ipAddress) {
4013         String macAddress = null;
4014         BufferedReader reader = null;
4015         try {
4016             reader = mWifiInjector.createBufferedReader(ARP_TABLE_PATH);
4017 
4018             // Skip over the line bearing column titles
4019             String line = reader.readLine();
4020 
4021             while ((line = reader.readLine()) != null) {
4022                 String[] tokens = line.split("[ ]+");
4023                 if (tokens.length < 6) {
4024                     continue;
4025                 }
4026 
4027                 // ARP column format is
4028                 // IPAddress HWType Flags HWAddress Mask Device
4029                 String ip = tokens[0];
4030                 String mac = tokens[3];
4031 
4032                 if (TextUtils.equals(ipAddress, ip)) {
4033                     macAddress = mac;
4034                     break;
4035                 }
4036             }
4037 
4038             if (macAddress == null) {
4039                 loge("Did not find remoteAddress {" + ipAddress + "} in /proc/net/arp");
4040             }
4041 
4042         } catch (FileNotFoundException e) {
4043             loge("Could not open /proc/net/arp to lookup mac address");
4044         } catch (IOException e) {
4045             loge("Could not read /proc/net/arp to lookup mac address");
4046         } finally {
4047             try {
4048                 if (reader != null) {
4049                     reader.close();
4050                 }
4051             } catch (IOException e) {
4052                 // Do nothing
4053             }
4054         }
4055         return macAddress;
4056 
4057     }
4058 
4059     /**
4060      * Determine if the specified auth failure is considered to be a permanent wrong password
4061      * failure. The criteria for such failure is when wrong password error is detected
4062      * and the network had never been connected before.
4063      *
4064      * For networks that have previously connected successfully, we consider wrong password
4065      * failures to be temporary, to be on the conservative side.  Since this might be the
4066      * case where we are trying to connect to a wrong network (e.g. A network with same SSID
4067      * but different password).
4068      */
isPermanentWrongPasswordFailure(int networkId, int reasonCode)4069     private boolean isPermanentWrongPasswordFailure(int networkId, int reasonCode) {
4070         if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD) {
4071             return false;
4072         }
4073         WifiConfiguration network = mWifiConfigManager.getConfiguredNetwork(networkId);
4074         if (network != null && network.getNetworkSelectionStatus().hasEverConnected()) {
4075             return false;
4076         }
4077         return true;
4078     }
4079 
4080      /**
4081      * Dynamically change the MAC address to use the locally randomized
4082      * MAC address generated for each network.
4083      * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address
4084      * is masked out or not set, it will generate a new random MAC address.
4085      */
configureRandomizedMacAddress(WifiConfiguration config)4086     private void configureRandomizedMacAddress(WifiConfiguration config) {
4087         if (config == null) {
4088             Log.e(getTag(), "No config to change MAC address to");
4089             return;
4090         }
4091         String currentMacString = mWifiNative.getMacAddress(mInterfaceName);
4092         MacAddress currentMac = NativeUtil.getMacAddressOrNull(currentMacString);
4093         MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config,
4094                 isSecondaryInternet() && mClientModeManager.isSecondaryInternetDbsAp());
4095         if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) {
4096             Log.wtf(getTag(), "Config generated an invalid MAC address");
4097         } else if (Objects.equals(newMac, currentMac)) {
4098             Log.d(getTag(), "No changes in MAC address");
4099         } else {
4100             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_MAC_CHANGE, config);
4101             boolean setMacSuccess =
4102                     mWifiNative.setStaMacAddress(mInterfaceName, newMac);
4103             if (setMacSuccess) {
4104                 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac);
4105             }
4106             if (mVerboseLoggingEnabled) {
4107                 Log.d(getTag(), "ConnectedMacRandomization SSID(" + config.getPrintableSsid()
4108                         + "). setMacAddress(" + newMac.toString() + ") from "
4109                         + currentMacString + " = " + setMacSuccess);
4110             }
4111         }
4112     }
4113 
4114     /**
4115      * Sets the current MAC to the factory MAC address.
4116      */
setCurrentMacToFactoryMac(WifiConfiguration config)4117     private void setCurrentMacToFactoryMac(WifiConfiguration config) {
4118         MacAddress factoryMac = retrieveFactoryMacAddressAndStoreIfNecessary();
4119         if (factoryMac == null) {
4120             Log.e(getTag(), "Fail to set factory MAC address. Factory MAC is null.");
4121             return;
4122         }
4123         String currentMacStr = mWifiNative.getMacAddress(mInterfaceName);
4124         if (!TextUtils.equals(currentMacStr, factoryMac.toString())) {
4125             if (mWifiNative.setStaMacAddress(mInterfaceName, factoryMac)) {
4126                 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac);
4127                 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_MAC_CHANGE, config);
4128             } else {
4129                 Log.e(getTag(), "Failed to set MAC address to " + "'"
4130                         + factoryMac.toString() + "'");
4131             }
4132         }
4133     }
4134 
4135     /**
4136      * Helper method to start other services and get state ready for client mode
4137      */
setupClientMode()4138     private void setupClientMode() {
4139         Log.d(getTag(), "setupClientMode() ifacename = " + mInterfaceName);
4140 
4141         setMulticastFilter(true);
4142         registerForWifiMonitorEvents();
4143         if (isPrimary()) {
4144             mWifiLastResortWatchdog.clearAllFailureCounts();
4145         }
4146         mWifiNative.setSupplicantLogLevel(mVerboseLoggingEnabled);
4147 
4148         // Initialize data structures
4149         mTargetBssid = SUPPLICANT_BSSID_ANY;
4150         mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
4151         mLastBssid = null;
4152         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
4153         mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
4154         mLastSimBasedConnectionCarrierName = null;
4155         mLastSignalLevel = -1;
4156         mEnabledTdlsPeers.clear();
4157         // TODO: b/79504296 This broadcast has been deprecated and should be removed
4158         sendSupplicantConnectionChangedBroadcast(true);
4159 
4160         mWifiNative.setExternalSim(mInterfaceName, true);
4161 
4162         mWifiDiagnostics.startPktFateMonitoring(mInterfaceName);
4163         mWifiDiagnostics.startLogging(mInterfaceName);
4164 
4165         mMboOceController.enable();
4166 
4167         // Enable bluetooth coexistence scan mode when bluetooth connection is active.
4168         // When this mode is on, some of the low-level scan parameters used by the
4169         // driver are changed to reduce interference with bluetooth
4170         mWifiNative.setBluetoothCoexistenceScanMode(
4171                 mInterfaceName, mWifiGlobals.isBluetoothConnected());
4172         sendNetworkChangeBroadcast(DetailedState.DISCONNECTED);
4173 
4174         // Disable legacy multicast filtering, which on some chipsets defaults to enabled.
4175         // Legacy IPv6 multicast filtering blocks ICMPv6 router advertisements which breaks IPv6
4176         // provisioning. Legacy IPv4 multicast filtering may be re-enabled later via
4177         // IpClient.Callback.setFallbackMulticastFilter()
4178         mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName);
4179         mWifiNative.stopFilteringMulticastV6Packets(mInterfaceName);
4180 
4181         // Set the right suspend mode settings
4182         mWifiNative.setSuspendOptimizations(mInterfaceName, mSuspendOptNeedsDisabled == 0
4183                 && mContext.getResources().getBoolean(
4184                         R.bool.config_wifiSuspendOptimizationsEnabled));
4185 
4186         enablePowerSave();
4187 
4188         // Disable wpa_supplicant from auto reconnecting.
4189         mWifiNative.enableStaAutoReconnect(mInterfaceName, false);
4190         // STA has higher priority over P2P
4191         mWifiNative.setConcurrencyPriority(true);
4192 
4193         // Retrieve and store the factory MAC address (on first bootup).
4194         retrieveFactoryMacAddressAndStoreIfNecessary();
4195         updateCurrentConnectionInfo();
4196     }
4197 
4198     /**
4199      * Helper method to stop external services and clean up state from client mode.
4200      */
stopClientMode()4201     private void stopClientMode() {
4202         handleNetworkDisconnect(false,
4203                 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__WIFI_DISABLED);
4204         // exiting supplicant started state is now only applicable to client mode
4205         mWifiDiagnostics.stopLogging(mInterfaceName);
4206 
4207         mMboOceController.disable();
4208         maybeShutdownIpclient();
4209         deregisterForWifiMonitorEvents(); // uses mInterfaceName, must call before nulling out
4210         // TODO: b/79504296 This broadcast has been deprecated and should be removed
4211         sendSupplicantConnectionChangedBroadcast(false);
4212     }
4213 
4214     /**
4215      * Helper method called when a L3 connection is successfully established to a network.
4216      */
registerConnected()4217     void registerConnected() {
4218         if (isPrimary()) {
4219             mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork());
4220         }
4221         if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
4222             WifiConfiguration config = getConnectedWifiConfigurationInternal();
4223             boolean shouldSetUserConnectChoice = config != null
4224                     && isRecentlySelectedByTheUser(config)
4225                     && (config.getNetworkSelectionStatus().hasEverConnected()
4226                     || config.isEphemeral())
4227                     && mWifiPermissionsUtil.checkNetworkSettingsPermission(config.lastConnectUid);
4228             mWifiConfigManager.updateNetworkAfterConnect(mLastNetworkId,
4229                     mIsUserSelected, shouldSetUserConnectChoice, mWifiInfo.getRssi());
4230             // Notify PasspointManager of Passpoint network connected event.
4231             WifiConfiguration currentNetwork = getConnectedWifiConfigurationInternal();
4232             if (currentNetwork != null && currentNetwork.isPasspoint()) {
4233                 mPasspointManager.onPasspointNetworkConnected(
4234                         currentNetwork.getProfileKey(), currentNetwork.SSID);
4235             }
4236         }
4237     }
4238 
registerDisconnected()4239     void registerDisconnected() {
4240         // The role of the ClientModeManager may have been changed to scan only before handling
4241         // the network disconnect.
4242         if (isPrimary() || mClientModeManager.getRole() == ROLE_CLIENT_SCAN_ONLY) {
4243             mWifiInjector.getActiveModeWarden().setCurrentNetwork(getCurrentNetwork());
4244         }
4245         if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
4246             mWifiConfigManager.updateNetworkAfterDisconnect(mLastNetworkId);
4247         }
4248     }
4249 
4250     /**
4251      * Returns WifiConfiguration object corresponding to the currently connected network, null if
4252      * not connected.
4253      */
getConnectedWifiConfigurationInternal()4254     @Nullable private WifiConfiguration getConnectedWifiConfigurationInternal() {
4255         if (mLastNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
4256             return null;
4257         }
4258         return mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
4259     }
4260 
4261     /**
4262      * Returns WifiConfiguration object corresponding to the currently connecting network, null if
4263      * not connecting.
4264      */
getConnectingWifiConfigurationInternal()4265     @Nullable private WifiConfiguration getConnectingWifiConfigurationInternal() {
4266         if (mTargetNetworkId == WifiConfiguration.INVALID_NETWORK_ID) {
4267             return null;
4268         }
4269         return mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
4270     }
4271 
getConnectedBssidInternal()4272     @Nullable private String getConnectedBssidInternal() {
4273         return mLastBssid;
4274     }
4275 
getConnectingBssidInternal()4276     @Nullable private String getConnectingBssidInternal() {
4277         return mTargetBssid;
4278     }
4279 
4280     /**
4281      * Returns WifiConfiguration object corresponding to the currently connected network, null if
4282      * not connected.
4283      */
4284     @Override
getConnectedWifiConfiguration()4285     @Nullable public WifiConfiguration getConnectedWifiConfiguration() {
4286         if (!isConnected()) return null;
4287         return getConnectedWifiConfigurationInternal();
4288     }
4289 
4290     /**
4291      * Returns WifiConfiguration object corresponding to the currently connecting network, null if
4292      * not connecting.
4293      */
4294     @Override
getConnectingWifiConfiguration()4295     @Nullable public WifiConfiguration getConnectingWifiConfiguration() {
4296         if (!isConnecting() && !isRoaming()) return null;
4297         return getConnectingWifiConfigurationInternal();
4298     }
4299 
4300     @Override
getConnectedBssid()4301     @Nullable public String getConnectedBssid() {
4302         if (!isConnected()) return null;
4303         return getConnectedBssidInternal();
4304     }
4305 
4306     @Override
getConnectingBssid()4307     @Nullable public String getConnectingBssid() {
4308         if (!isConnecting() && !isRoaming()) return null;
4309         return getConnectingBssidInternal();
4310     }
4311 
getCurrentScanResult()4312     ScanResult getCurrentScanResult() {
4313         WifiConfiguration config = getConnectedWifiConfigurationInternal();
4314         if (config == null) {
4315             return null;
4316         }
4317         String bssid = mWifiInfo.getBSSID();
4318         if (bssid == null) {
4319             bssid = mTargetBssid;
4320         }
4321         ScanDetailCache scanDetailCache =
4322                 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
4323 
4324         if (scanDetailCache == null) {
4325             return null;
4326         }
4327 
4328         return scanDetailCache.getScanResult(bssid);
4329     }
4330 
getCurrentBssidInternalMacAddress()4331     private MacAddress getCurrentBssidInternalMacAddress() {
4332         return NativeUtil.getMacAddressOrNull(mLastBssid);
4333     }
4334 
connectToNetwork(WifiConfiguration config)4335     private void connectToNetwork(WifiConfiguration config) {
4336         if ((config != null) && mWifiNative.connectToNetwork(mInterfaceName, config)) {
4337             // Update the internal config once the connection request is accepted.
4338             mWifiConfigManager.setNetworkLastUsedSecurityParams(config.networkId,
4339                     config.getNetworkSelectionStatus().getCandidateSecurityParams());
4340             mWifiLastResortWatchdog.noteStartConnectTime(config.networkId);
4341             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CMD_START_CONNECT, config);
4342             mIsAutoRoaming = false;
4343             transitionTo(mL2ConnectingState);
4344         } else {
4345             loge("CMD_START_CONNECT Failed to start connection to network " + config);
4346             mTargetWifiConfiguration = null;
4347             stopIpClient();
4348             reportConnectionAttemptEnd(
4349                     WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
4350                     WifiMetricsProto.ConnectionEvent.HLF_NONE,
4351                     WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
4352         }
4353     }
4354 
makeIpClient()4355     private void makeIpClient() {
4356         mIpClientCallbacks = new IpClientCallbacksImpl();
4357         mFacade.makeIpClient(mContext, mInterfaceName, mIpClientCallbacks);
4358         mIpClientCallbacks.awaitCreation();
4359     }
4360 
maybeShutdownIpclient()4361     private void maybeShutdownIpclient() {
4362         if (mIpClient == null) return;
4363         if (!mIpClient.shutdown()) {
4364             logd("Fail to shut down IpClient");
4365             return;
4366         }
4367 
4368         // Block to make sure IpClient has really shut down, lest cleanup
4369         // race with, say, bringup code over in tethering.
4370         mIpClientCallbacks.awaitShutdown();
4371         mIpClientCallbacks = null;
4372         mIpClient = null;
4373     }
4374 
4375     /********************************************************
4376      * HSM states
4377      *******************************************************/
4378 
4379     class ConnectableState extends RunnerState {
4380         private boolean mIsScreenStateChangeReceiverRegistered = false;
4381         BroadcastReceiver mScreenStateChangeReceiver = new BroadcastReceiver() {
4382             @Override
4383             public void onReceive(Context context, Intent intent) {
4384                 String action = intent.getAction();
4385                 if (TextUtils.equals(action, Intent.ACTION_SCREEN_ON)) {
4386                     sendMessage(CMD_SCREEN_STATE_CHANGED, 1);
4387                 } else if (TextUtils.equals(action, Intent.ACTION_SCREEN_OFF)) {
4388                     sendMessage(CMD_SCREEN_STATE_CHANGED, 0);
4389                 }
4390             }
4391         };
4392 
ConnectableState(int threshold)4393         ConnectableState(int threshold) {
4394             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
4395         }
4396 
4397         @Override
enterImpl()4398         public void enterImpl() {
4399             Log.d(getTag(), "entering ConnectableState: ifaceName = " + mInterfaceName);
4400             setSuspendOptimizationsNative(SUSPEND_DUE_TO_HIGH_PERF, true);
4401             if (mWifiGlobals.isConnectedMacRandomizationEnabled()) {
4402                 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress(
4403                         mInterfaceName, MacAddressUtils.createRandomUnicastAddress());
4404                 if (mFailedToResetMacAddress) {
4405                     Log.e(getTag(), "Failed to set random MAC address on ClientMode creation");
4406                 }
4407             }
4408             mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
4409             updateCurrentConnectionInfo();
4410             mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.INVALID);
4411             makeIpClient();
4412         }
4413 
continueEnterSetup(IpClientManager ipClientManager)4414         private void continueEnterSetup(IpClientManager ipClientManager) {
4415             mIpClient = ipClientManager;
4416             setupClientMode();
4417 
4418             IntentFilter filter = new IntentFilter();
4419             filter.addAction(Intent.ACTION_SCREEN_ON);
4420             filter.addAction(Intent.ACTION_SCREEN_OFF);
4421             if (!mIsScreenStateChangeReceiverRegistered) {
4422                 mContext.registerReceiver(mScreenStateChangeReceiver, filter);
4423                 mIsScreenStateChangeReceiverRegistered = true;
4424             }
4425             // Learn the initial state of whether the screen is on.
4426             // We update this field when we receive broadcasts from the system.
4427             handleScreenStateChanged(mContext.getSystemService(PowerManager.class).isInteractive());
4428 
4429             if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
4430                 loge("Failed to remove networks on entering connect mode");
4431             }
4432             mWifiInfo.reset();
4433             mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
4434 
4435             sendNetworkChangeBroadcast(DetailedState.DISCONNECTED);
4436 
4437             // Inform metrics that Wifi is Enabled (but not yet connected)
4438             mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
4439             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_ENABLED);
4440             mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
4441             updateCurrentConnectionInfo();
4442         }
4443 
4444         @Override
exitImpl()4445         public void exitImpl() {
4446             // Inform metrics that Wifi is being disabled (Toggled, airplane enabled, etc)
4447             mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISABLED);
4448             mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_WIFI_DISABLED);
4449 
4450             if (!mWifiNative.removeAllNetworks(mInterfaceName)) {
4451                 loge("Failed to remove networks on exiting connect mode");
4452             }
4453             if (mIsScreenStateChangeReceiverRegistered) {
4454                 mContext.unregisterReceiver(mScreenStateChangeReceiver);
4455                 mIsScreenStateChangeReceiverRegistered = false;
4456             }
4457 
4458             stopClientMode();
4459             mWifiScoreCard.doWrites();
4460         }
4461 
4462         @Override
getMessageLogRec(int what)4463         String getMessageLogRec(int what) {
4464             return ClientModeImpl.class.getSimpleName() + "."
4465                     + ConnectableState.class.getSimpleName() + "." + getWhatToString(what);
4466         }
4467 
4468         @Override
processMessageImpl(Message message)4469         public boolean processMessageImpl(Message message) {
4470             switch (message.what) {
4471                 case CMD_IPCLIENT_CREATED:
4472                     if (mIpClient != null) {
4473                         loge("Setup connectable state again when IpClient is ready?");
4474                     } else {
4475                         IpClientManager ipClientManager = (IpClientManager) message.obj;
4476                         continueEnterSetup(ipClientManager);
4477                     }
4478                     break;
4479                 case CMD_ENABLE_RSSI_POLL: {
4480                     mEnableRssiPolling = (message.arg1 == 1);
4481                     break;
4482                 }
4483                 case CMD_SCREEN_STATE_CHANGED: {
4484                     handleScreenStateChanged(message.arg1 != 0);
4485                     break;
4486                 }
4487                 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: {
4488                     if (mIpClient == null) {
4489                         logd("IpClient is not ready, "
4490                                 + "WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST dropped");
4491                         break;
4492                     }
4493                     if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
4494                         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
4495                                 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
4496                         mWifiNative.disconnect(mInterfaceName);
4497                     } else {
4498                         mWifiNative.reconnect(mInterfaceName);
4499                     }
4500                     break;
4501                 }
4502                 case CMD_RECONNECT: {
4503                     WorkSource workSource = (WorkSource) message.obj;
4504                     mWifiConnectivityManager.forceConnectivityScan(workSource);
4505                     break;
4506                 }
4507                 case CMD_REASSOCIATE: {
4508                     if (mIpClient != null) {
4509                         logd("IpClient is not ready, REASSOCIATE dropped");
4510 
4511                         mWifiNative.reassociate(mInterfaceName);
4512                     }
4513                     break;
4514                 }
4515                 case CMD_START_CONNECT: {
4516                     if (mIpClient == null) {
4517                         logd("IpClient is not ready, START_CONNECT dropped");
4518 
4519                         break;
4520                     }
4521                     /* connect command coming from auto-join */
4522                     int netId = message.arg1;
4523                     int uid = message.arg2;
4524                     String bssid = (String) message.obj;
4525                     mSentHLPs = false;
4526                     // Stop lingering (if it was lingering before) if we start a new connection.
4527                     // This means that the ClientModeManager was reused for another purpose, so it
4528                     // should no longer be in lingering mode.
4529                     mClientModeManager.setShouldReduceNetworkScore(false);
4530 
4531                     if (!hasConnectionRequests()) {
4532                         if (mNetworkAgent == null) {
4533                             loge("CMD_START_CONNECT but no requests and not connected,"
4534                                     + " bailing");
4535                             break;
4536                         } else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
4537                             loge("CMD_START_CONNECT but no requests and connected, but app "
4538                                     + "does not have sufficient permissions, bailing");
4539                             break;
4540                         }
4541                     }
4542                     WifiConfiguration config =
4543                             mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId);
4544                     logd("CMD_START_CONNECT "
4545                             + " my state " + getCurrentState().getName()
4546                             + " nid=" + netId
4547                             + " roam=" + mIsAutoRoaming);
4548                     if (config == null) {
4549                         loge("CMD_START_CONNECT and no config, bail out...");
4550                         break;
4551                     }
4552                     mCurrentConnectionDetectedCaptivePortal = false;
4553                     mTargetNetworkId = netId;
4554                     // Update scorecard while there is still state from existing connection
4555                     mLastScanRssi = mWifiConfigManager.findScanRssi(netId,
4556                             mWifiHealthMonitor.getScanRssiValidTimeMs());
4557                     mWifiScoreCard.noteConnectionAttempt(mWifiInfo, mLastScanRssi, config.SSID);
4558                     if (isPrimary()) {
4559                         mWifiBlocklistMonitor.setAllowlistSsids(config.SSID,
4560                                 Collections.emptyList());
4561                         mWifiBlocklistMonitor.updateFirmwareRoamingConfiguration(
4562                                 Set.of(config.SSID));
4563                     }
4564 
4565                     updateWifiConfigOnStartConnection(config, bssid);
4566                     reportConnectionAttemptStart(config, mTargetBssid,
4567                             WifiMetricsProto.ConnectionEvent.ROAM_UNRELATED);
4568 
4569                     String currentMacAddress = mWifiNative.getMacAddress(mInterfaceName);
4570                     mWifiInfo.setMacAddress(currentMacAddress);
4571                     updateCurrentConnectionInfo();
4572                     if (mVerboseLoggingEnabled) {
4573                         Log.i(getTag(), "Connecting with " + currentMacAddress
4574                                 + " as the mac address");
4575                     }
4576                     mWifiPseudonymManager.enableStrictConservativePeerModeIfSupported(config);
4577                     mTargetWifiConfiguration = config;
4578                     mNetworkNotFoundEventCount = 0;
4579                     /* Check for FILS configuration again after updating the config */
4580                     if (config.isFilsSha256Enabled() || config.isFilsSha384Enabled()) {
4581                         boolean isIpClientStarted = startIpClient(config, true);
4582                         if (isIpClientStarted) {
4583                             mIpClientWithPreConnection = true;
4584                             transitionTo(mL2ConnectingState);
4585                             break;
4586                         }
4587                     }
4588                     setSelectedRcoiForPasspoint(config);
4589 
4590                     // TOFU flow for devices that do not support this feature
4591                     mInsecureEapNetworkHandler.prepareConnection(mTargetWifiConfiguration);
4592                     mLeafCertSent = false;
4593                     if (!isTrustOnFirstUseSupported()) {
4594                         mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected);
4595                     }
4596                     connectToNetwork(config);
4597                     break;
4598                 }
4599                 case CMD_START_FILS_CONNECTION: {
4600                     if (mIpClient == null) {
4601                         logd("IpClient is not ready, START_FILS_CONNECTION dropped");
4602                         break;
4603                     }
4604                     mWifiMetrics.incrementConnectRequestWithFilsAkmCount();
4605                     List<Layer2PacketParcelable> packets;
4606                     packets = (List<Layer2PacketParcelable>) message.obj;
4607                     if (mVerboseLoggingEnabled) {
4608                         Log.d(getTag(), "Send HLP IEs to supplicant");
4609                     }
4610                     addLayer2PacketsToHlpReq(packets);
4611                     WifiConfiguration config = mTargetWifiConfiguration;
4612                     connectToNetwork(config);
4613                     break;
4614                 }
4615                 case CMD_CONNECT_NETWORK: {
4616                     ConnectNetworkMessage cnm = (ConnectNetworkMessage) message.obj;
4617                     if (mIpClient == null) {
4618                         logd("IpClient is not ready, CONNECT_NETWORK dropped");
4619                         cnm.listener.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR);
4620                         break;
4621                     }
4622                     NetworkUpdateResult result = cnm.result;
4623                     int netId = result.getNetworkId();
4624                     connectToUserSelectNetwork(
4625                             netId, message.sendingUid, result.hasCredentialChanged(),
4626                             cnm.packageName);
4627                     mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_CONNECT_NETWORK,
4628                             mWifiConfigManager.getConfiguredNetwork(netId));
4629                     cnm.listener.sendSuccess();
4630                     break;
4631                 }
4632                 case CMD_SAVE_NETWORK: {
4633                     ConnectNetworkMessage cnm = (ConnectNetworkMessage) message.obj;
4634                     if (mIpClient == null) {
4635                         logd("IpClient is not ready, SAVE_NETWORK dropped");
4636                         cnm.listener.sendFailure(WifiManager.ActionListener.FAILURE_INTERNAL_ERROR);
4637                         break;
4638                     }
4639                     NetworkUpdateResult result = cnm.result;
4640                     int netId = result.getNetworkId();
4641                     if (mWifiInfo.getNetworkId() == netId) {
4642                         if (result.hasCredentialChanged()) {
4643                             // The network credentials changed and we're connected to this network,
4644                             // start a new connection with the updated credentials.
4645                             logi("CMD_SAVE_NETWORK credential changed for nid="
4646                                     + netId + ". Reconnecting.");
4647                             startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
4648                         } else {
4649                             if (result.hasProxyChanged()) {
4650                                 if (mIpClient != null) {
4651                                     log("Reconfiguring proxy on connection");
4652                                     WifiConfiguration currentConfig =
4653                                             getConnectedWifiConfigurationInternal();
4654                                     if (currentConfig != null) {
4655                                         mIpClient.setHttpProxy(currentConfig.getHttpProxy());
4656                                     } else {
4657                                         Log.w(getTag(),
4658                                                 "CMD_SAVE_NETWORK proxy change - but no current "
4659                                                         + "Wi-Fi config");
4660                                     }
4661                                 }
4662                             }
4663                             if (result.hasIpChanged()) {
4664                                 // The current connection configuration was changed
4665                                 // We switched from DHCP to static or from static to DHCP, or the
4666                                 // static IP address has changed.
4667                                 log("Reconfiguring IP on connection");
4668                                 WifiConfiguration currentConfig =
4669                                         getConnectedWifiConfigurationInternal();
4670                                 if (currentConfig != null) {
4671                                     transitionTo(mL3ProvisioningState);
4672                                 } else {
4673                                     Log.w(getTag(), "CMD_SAVE_NETWORK Ip change - but no current "
4674                                             + "Wi-Fi config");
4675                                 }
4676                             }
4677                         }
4678                     } else if (mWifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID
4679                             && result.hasCredentialChanged()) {
4680                         logi("CMD_SAVE_NETWORK credential changed for nid="
4681                                 + netId + " while disconnected. Connecting.");
4682                         WifiConfiguration config =
4683                                 mWifiConfigManager.getConfiguredNetwork(netId);
4684                         if (!mWifiPermissionsUtil.isAdminRestrictedNetwork(config)
4685                                 && !mWifiGlobals.isDeprecatedSecurityTypeNetwork(config)) {
4686                             startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
4687                         }
4688                     } else if (result.hasCredentialChanged()) {
4689                         WifiConfiguration currentConfig =
4690                                 getConnectedWifiConfigurationInternal();
4691                         WifiConfiguration updatedConfig =
4692                                 mWifiConfigManager.getConfiguredNetwork(netId);
4693                         if (currentConfig != null && currentConfig.isLinked(updatedConfig)) {
4694                             logi("current network linked config saved, update linked networks");
4695                             updateLinkedNetworks(currentConfig);
4696                         }
4697                     }
4698                     cnm.listener.sendSuccess();
4699                     break;
4700                 }
4701                 case CMD_BLUETOOTH_CONNECTION_STATE_CHANGE: {
4702                     mWifiNative.setBluetoothCoexistenceScanMode(
4703                             mInterfaceName, mWifiGlobals.isBluetoothConnected());
4704                     break;
4705                 }
4706                 case CMD_SET_SUSPEND_OPT_ENABLED: {
4707                     if (message.arg1 == 1) {
4708                         setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, true);
4709                         if (message.arg2 == 1) {
4710                             mSuspendWakeLock.release();
4711                         }
4712                     } else {
4713                         setSuspendOptimizationsNative(SUSPEND_DUE_TO_SCREEN, false);
4714                     }
4715                     break;
4716                 }
4717                 case WifiMonitor.ANQP_DONE_EVENT: {
4718                     mPasspointManager.notifyANQPDone((AnqpEvent) message.obj);
4719                     break;
4720                 }
4721                 case CMD_STOP_IP_PACKET_OFFLOAD: {
4722                     int slot = message.arg1;
4723                     int ret = stopWifiIPPacketOffload(slot);
4724                     if (mNetworkAgent != null) {
4725                         mNetworkAgent.sendSocketKeepaliveEvent(slot, ret);
4726                     }
4727                     break;
4728                 }
4729                 case WifiMonitor.RX_HS20_ANQP_ICON_EVENT: {
4730                     mPasspointManager.notifyIconDone((IconEvent) message.obj);
4731                     break;
4732                 }
4733                 case WifiMonitor.HS20_DEAUTH_IMMINENT_EVENT:
4734                     mPasspointManager.handleDeauthImminentEvent((WnmData) message.obj,
4735                             getConnectedWifiConfigurationInternal());
4736                     break;
4737                 case WifiMonitor.HS20_TERMS_AND_CONDITIONS_ACCEPTANCE_REQUIRED_EVENT:
4738                     mWifiMetrics
4739                             .incrementTotalNumberOfPasspointConnectionsWithTermsAndConditionsUrl();
4740                     mTermsAndConditionsUrl = mPasspointManager
4741                             .handleTermsAndConditionsEvent((WnmData) message.obj,
4742                             getConnectedWifiConfigurationInternal());
4743                     if (mTermsAndConditionsUrl == null) {
4744                         loge("Disconnecting from Passpoint network due to an issue with the "
4745                                 + "Terms and Conditions URL");
4746                         sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_PASSPOINT_TAC);
4747                     }
4748                     break;
4749                 case WifiMonitor.HS20_REMEDIATION_EVENT:
4750                     mPasspointManager.receivedWnmFrame((WnmData) message.obj);
4751                     break;
4752                 case WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE: {
4753                     handleBssTransitionRequest((BtmFrameData) message.obj);
4754                     break;
4755                 }
4756                 case CMD_CONFIG_ND_OFFLOAD: {
4757                     final boolean enabled = (message.arg1 > 0);
4758                     mWifiNative.configureNeighborDiscoveryOffload(mInterfaceName, enabled);
4759                     break;
4760                 }
4761                 // Link configuration (IP address, DNS, ...) changes notified via netlink
4762                 case CMD_UPDATE_LINKPROPERTIES: {
4763                     updateLinkProperties((LinkProperties) message.obj);
4764                     break;
4765                 }
4766                 case CMD_START_IP_PACKET_OFFLOAD:
4767                 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF:
4768                 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: {
4769                     if (mNetworkAgent != null) {
4770                         mNetworkAgent.sendSocketKeepaliveEvent(message.arg1,
4771                                 SocketKeepalive.ERROR_INVALID_NETWORK);
4772                     }
4773                     break;
4774                 }
4775                 case CMD_INSTALL_PACKET_FILTER: {
4776                     if (mContext.getResources().getBoolean(
4777                             R.bool.config_wifiEnableApfOnNonPrimarySta)
4778                             || isPrimary()) {
4779                         mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj);
4780                     } else {
4781                         Log.i(TAG, "Not applying packet filter on non primary CMM");
4782                     }
4783                     break;
4784                 }
4785                 case CMD_READ_PACKET_FILTER: {
4786                     byte[] packetFilter = null;
4787                     if (mContext.getResources().getBoolean(
4788                             R.bool.config_wifiEnableApfOnNonPrimarySta)
4789                             || isPrimary()) {
4790                         packetFilter = mWifiNative.readPacketFilter(mInterfaceName);
4791                     } else {
4792                         Log.v(TAG, "APF not supported on non primary CMM - return null");
4793                     }
4794                     if (mIpClient != null) {
4795                         mIpClient.readPacketFilterComplete(packetFilter);
4796                     }
4797                     break;
4798                 }
4799                 case CMD_SET_FALLBACK_PACKET_FILTERING: {
4800                     if ((boolean) message.obj) {
4801                         mWifiNative.startFilteringMulticastV4Packets(mInterfaceName);
4802                     } else {
4803                         mWifiNative.stopFilteringMulticastV4Packets(mInterfaceName);
4804                     }
4805                     break;
4806                 }
4807                 case CMD_SET_MAX_DTIM_MULTIPLIER: {
4808                     final int maxMultiplier = message.arg1;
4809                     final boolean success =
4810                             mWifiNative.setDtimMultiplier(mInterfaceName, maxMultiplier);
4811                     if (mVerboseLoggingEnabled) {
4812                         Log.d(TAG, "Set maximum DTIM Multiplier to " + maxMultiplier
4813                                 + (success ? " SUCCESS" : " FAIL"));
4814                     }
4815                     break;
4816                 }
4817                 case WifiP2pServiceImpl.P2P_CONNECTION_CHANGED:
4818                 case CMD_RESET_SIM_NETWORKS:
4819                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
4820                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
4821                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
4822                 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
4823                 case WifiMonitor.ASSOCIATION_REJECTION_EVENT:
4824                 case CMD_RSSI_POLL:
4825                 case CMD_ONESHOT_RSSI_POLL:
4826                 case CMD_PRE_DHCP_ACTION:
4827                 case CMD_PRE_DHCP_ACTION_COMPLETE:
4828                 case CMD_POST_DHCP_ACTION:
4829                 case WifiMonitor.SUP_REQUEST_IDENTITY:
4830                 case WifiMonitor.SUP_REQUEST_SIM_AUTH:
4831                 case WifiMonitor.TARGET_BSSID_EVENT:
4832                 case WifiMonitor.ASSOCIATED_BSSID_EVENT:
4833                 case WifiMonitor.TRANSITION_DISABLE_INDICATION:
4834                 case CMD_UNWANTED_NETWORK:
4835                 case CMD_CONNECTING_WATCHDOG_TIMER:
4836                 case WifiMonitor.NETWORK_NOT_FOUND_EVENT:
4837                 case CMD_ROAM_WATCHDOG_TIMER: {
4838                     // no-op: all messages must be handled in the base state in case it was missed
4839                     // in one of the child states.
4840                     break;
4841                 }
4842                 case CMD_ACCEPT_EAP_SERVER_CERTIFICATE:
4843                     // If TOFU is not supported, then we are already connected
4844                     if (!isTrustOnFirstUseSupported()) break;
4845                     // Got an approval for a TOFU network. Disconnect (if connected) and trigger
4846                     // a connection to the new approved network.
4847                     logd("User accepted TOFU provided certificate");
4848                     startConnectToNetwork(message.arg1, Process.WIFI_UID, SUPPLICANT_BSSID_ANY);
4849                     break;
4850                 case CMD_REJECT_EAP_INSECURE_CONNECTION:
4851                 case CMD_START_ROAM:
4852                 case CMD_IP_CONFIGURATION_SUCCESSFUL:
4853                 case CMD_IP_CONFIGURATION_LOST:
4854                 case CMD_IP_REACHABILITY_LOST:
4855                 case CMD_IP_REACHABILITY_FAILURE: {
4856                     mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
4857                     break;
4858                 }
4859                 case 0: {
4860                     // We want to notice any empty messages (with what == 0) that might crop up.
4861                     // For example, we may have recycled a message sent to multiple handlers.
4862                     Log.wtf(getTag(), "Error! empty message encountered");
4863                     break;
4864                 }
4865                 default: {
4866                     loge("Error! unhandled message" + message);
4867                     break;
4868                 }
4869             }
4870 
4871             logStateAndMessage(message, this);
4872             return HANDLED;
4873         }
4874     }
4875 
handleL3MessagesWhenNotConnected(Message message)4876     private boolean handleL3MessagesWhenNotConnected(Message message) {
4877         boolean handleStatus = HANDLED;
4878 
4879         if (!mIpClientWithPreConnection) {
4880             return NOT_HANDLED;
4881         }
4882 
4883         switch (message.what) {
4884             case CMD_PRE_DHCP_ACTION:
4885                 handlePreDhcpSetup();
4886                 break;
4887             case CMD_PRE_DHCP_ACTION_COMPLETE:
4888                 if (mIpClient != null) {
4889                     mIpClient.completedPreDhcpAction();
4890                 }
4891                 break;
4892             case CMD_IPV4_PROVISIONING_FAILURE:
4893                 stopDhcpSetup();
4894                 deferMessage(message);
4895                 break;
4896             case CMD_POST_DHCP_ACTION:
4897             case CMD_IPV4_PROVISIONING_SUCCESS:
4898             case CMD_IP_CONFIGURATION_SUCCESSFUL:
4899                 deferMessage(message);
4900                 break;
4901             default:
4902                 return NOT_HANDLED;
4903         }
4904 
4905         return handleStatus;
4906     }
4907 
createNetworkAgentSpecifier( @onNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid, boolean matchLocationSensitiveInformation)4908     private WifiNetworkAgentSpecifier createNetworkAgentSpecifier(
4909             @NonNull WifiConfiguration currentWifiConfiguration, @Nullable String currentBssid,
4910             boolean matchLocationSensitiveInformation) {
4911         // Defensive copy to avoid mutating the passed argument
4912         final WifiConfiguration conf = new WifiConfiguration(currentWifiConfiguration);
4913         conf.BSSID = currentBssid;
4914         WifiNetworkAgentSpecifier wns =
4915                 new WifiNetworkAgentSpecifier(conf,
4916                         WifiNetworkSpecifier.getBand(mWifiInfo.getFrequency()),
4917                         matchLocationSensitiveInformation);
4918         return wns;
4919     }
4920 
getCapabilities( WifiConfiguration currentWifiConfiguration, String currentBssid)4921     private NetworkCapabilities getCapabilities(
4922             WifiConfiguration currentWifiConfiguration, String currentBssid) {
4923         final NetworkCapabilities.Builder builder =
4924                 new NetworkCapabilities.Builder(mNetworkCapabilitiesFilter);
4925         // MatchAllNetworkSpecifier set in the mNetworkCapabilitiesFilter should never be set in the
4926         // agent's specifier.
4927         builder.setNetworkSpecifier(null);
4928         if (currentWifiConfiguration == null) {
4929             return builder.build();
4930         }
4931 
4932         if (mWifiInfo.isTrusted()) {
4933             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
4934         } else {
4935             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED);
4936         }
4937 
4938         if (mWifiInfo.isRestricted()) {
4939             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
4940         }
4941 
4942         if (SdkLevel.isAtLeastS()) {
4943             if (mWifiInfo.isOemPaid()) {
4944                 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID);
4945                 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
4946             } else {
4947                 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID);
4948             }
4949             if (mWifiInfo.isOemPrivate()) {
4950                 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE);
4951                 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
4952             } else {
4953                 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE);
4954             }
4955         }
4956 
4957         builder.setOwnerUid(currentWifiConfiguration.creatorUid);
4958         builder.setAdministratorUids(new int[]{currentWifiConfiguration.creatorUid});
4959         if (SdkLevel.isAtLeastT()) {
4960             builder.setAllowedUids(Set.of(currentWifiConfiguration.creatorUid));
4961         }
4962 
4963         if (!WifiConfiguration.isMetered(currentWifiConfiguration, mWifiInfo)) {
4964             builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4965         } else {
4966             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
4967         }
4968 
4969         if (mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI) {
4970             builder.setSignalStrength(mWifiInfo.getRssi());
4971         } else {
4972             builder.setSignalStrength(NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED);
4973         }
4974 
4975         if (currentWifiConfiguration.osu) {
4976             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
4977         }
4978 
4979         if (!WifiManager.UNKNOWN_SSID.equals(mWifiInfo.getSSID())) {
4980             builder.setSsid(mWifiInfo.getSSID());
4981         }
4982 
4983         // Only send out WifiInfo in >= Android S devices.
4984         if (SdkLevel.isAtLeastS()) {
4985             builder.setTransportInfo(new WifiInfo(mWifiInfo));
4986 
4987             if (mWifiInfo.getSubscriptionId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID
4988                     && mWifiInfo.isCarrierMerged()) {
4989                 builder.setSubscriptionIds(Collections.singleton(mWifiInfo.getSubscriptionId()));
4990             }
4991         }
4992 
4993         List<Integer> uids = new ArrayList<>(mNetworkFactory
4994                 .getSpecificNetworkRequestUids(
4995                         currentWifiConfiguration, currentBssid));
4996         // There is an active local only specific request.
4997         if (!uids.isEmpty()) {
4998             // Remove internet capability.
4999             if (!mNetworkFactory.shouldHaveInternetCapabilities()) {
5000                 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
5001             }
5002             if (SdkLevel.isAtLeastS()) {
5003                 builder.setUids(getUidRangeSet(uids));
5004             } else {
5005                 // Use requestor Uid and PackageName on pre-S device.
5006                 Pair<Integer, String> specificRequestUidAndPackageName = mNetworkFactory
5007                         .getSpecificNetworkRequestUidAndPackageName(currentWifiConfiguration,
5008                                 currentBssid);
5009                 // Fill up the uid/packageName for this connection.
5010                 builder.setRequestorUid(specificRequestUidAndPackageName.first);
5011                 builder.setRequestorPackageName(specificRequestUidAndPackageName.second);
5012             }
5013             // Fill up the network agent specifier for this connection, allowing NetworkCallbacks
5014             // to match local-only specifiers in requests. TODO(b/187921303): a third-party app can
5015             // observe this location-sensitive information by registering a NetworkCallback.
5016             builder.setNetworkSpecifier(createNetworkAgentSpecifier(currentWifiConfiguration,
5017                     getConnectedBssidInternal(), true /* matchLocalOnlySpecifiers */));
5018         } else {
5019             // Fill up the network agent specifier for this connection, without allowing
5020             // NetworkCallbacks to match local-only specifiers in requests.
5021             builder.setNetworkSpecifier(createNetworkAgentSpecifier(currentWifiConfiguration,
5022                     getConnectedBssidInternal(), false /* matchLocalOnlySpecifiers */));
5023         }
5024 
5025         updateLinkBandwidth(builder);
5026         final NetworkCapabilities networkCapabilities = builder.build();
5027         if (mVcnManager == null || !currentWifiConfiguration.carrierMerged
5028                 || !SdkLevel.isAtLeastS()) {
5029             return networkCapabilities;
5030         }
5031         final VcnNetworkPolicyResult vcnNetworkPolicy =
5032                 mVcnManager.applyVcnNetworkPolicy(networkCapabilities, mLinkProperties);
5033         if (vcnNetworkPolicy.isTeardownRequested()) {
5034             sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST);
5035         }
5036         final NetworkCapabilities vcnCapability = vcnNetworkPolicy.getNetworkCapabilities();
5037         if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)) {
5038             if (mVerboseLoggingEnabled) {
5039                 logd("NET_CAPABILITY_NOT_VCN_MANAGED is removed");
5040             }
5041             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
5042         }
5043         if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
5044             if (mVerboseLoggingEnabled) {
5045                 logd("NET_CAPABILITY_NOT_RESTRICTED is removed");
5046             }
5047             builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
5048         }
5049         return builder.build();
5050     }
5051 
getUidRangeSet(List<Integer> uids)5052     private Set<Range<Integer>> getUidRangeSet(List<Integer> uids) {
5053         Collections.sort(uids);
5054         Set<Range<Integer>> uidRanges = new ArraySet<>();
5055         int start = 0;
5056         int next = 0;
5057         for (int i : uids) {
5058             if (start == next) {
5059                 start = i;
5060                 next = start + 1;
5061             } else if (i == next) {
5062                 next++;
5063             } else {
5064                 uidRanges.add(new Range<>(start, next - 1));
5065                 start = i;
5066                 next = start + 1;
5067             }
5068         }
5069         uidRanges.add(new Range<>(start, next - 1));
5070         return uidRanges;
5071     }
5072 
updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder)5073     private void updateLinkBandwidth(NetworkCapabilities.Builder networkCapabilitiesBuilder) {
5074         int txTputKbps = 0;
5075         int rxTputKbps = 0;
5076         int currRssi = mWifiInfo.getRssi();
5077         if (currRssi != WifiInfo.INVALID_RSSI) {
5078             WifiScoreCard.PerNetwork network = mWifiScoreCard.lookupNetwork(mWifiInfo.getSSID());
5079             txTputKbps = network.getTxLinkBandwidthKbps();
5080             rxTputKbps = network.getRxLinkBandwidthKbps();
5081         } else {
5082             // Fall back to max link speed. This should rarely happen if ever
5083             int maxTxLinkSpeedMbps = mWifiInfo.getMaxSupportedTxLinkSpeedMbps();
5084             int maxRxLinkSpeedMbps = mWifiInfo.getMaxSupportedRxLinkSpeedMbps();
5085             txTputKbps = maxTxLinkSpeedMbps * 1000;
5086             rxTputKbps = maxRxLinkSpeedMbps * 1000;
5087         }
5088         if (mVerboseLoggingEnabled) {
5089             logd("reported txKbps " + txTputKbps + " rxKbps " + rxTputKbps);
5090         }
5091         if (txTputKbps > 0) {
5092             networkCapabilitiesBuilder.setLinkUpstreamBandwidthKbps(txTputKbps);
5093         }
5094         if (rxTputKbps > 0) {
5095             networkCapabilitiesBuilder.setLinkDownstreamBandwidthKbps(rxTputKbps);
5096         }
5097     }
5098 
5099     /**
5100      * Method to update network capabilities from the current WifiConfiguration.
5101      */
5102     @Override
updateCapabilities()5103     public void updateCapabilities() {
5104         updateCapabilities(getConnectedWifiConfigurationInternal());
5105     }
5106 
5107     /**
5108      * Check if BSSID belongs to any of the affiliated link BSSID's.
5109      * @param bssid BSSID of the AP.
5110      * @return true if BSSID matches to one of the affiliated link BSSIDs, false otherwise.
5111      */
isAffiliatedLinkBssid(@onNull MacAddress bssid)5112     public boolean isAffiliatedLinkBssid(@NonNull MacAddress bssid) {
5113         List<MloLink> links = mWifiInfo.getAffiliatedMloLinks();
5114         for (MloLink link: links) {
5115             if (link.getApMacAddress().equals(bssid)) {
5116                 return true;
5117             }
5118         }
5119         return false;
5120     }
5121 
5122     /**
5123      * Check if the connection is MLO (Multi-Link Operation).
5124      * @return true if connection is MLO, otherwise false.
5125      */
isMlo()5126     public boolean isMlo() {
5127         return !mWifiInfo.getAssociatedMloLinks().isEmpty();
5128     }
5129 
updateCapabilities(WifiConfiguration currentWifiConfiguration)5130     private void updateCapabilities(WifiConfiguration currentWifiConfiguration) {
5131         updateCapabilities(getCapabilities(currentWifiConfiguration, getConnectedBssidInternal()));
5132     }
5133 
updateCapabilities(NetworkCapabilities networkCapabilities)5134     private void updateCapabilities(NetworkCapabilities networkCapabilities) {
5135         if (mNetworkAgent == null) {
5136             return;
5137         }
5138         mNetworkAgent.sendNetworkCapabilitiesAndCache(networkCapabilities);
5139     }
5140 
handleEapAuthFailure(int networkId, int errorCode)5141     private void handleEapAuthFailure(int networkId, int errorCode) {
5142         WifiConfiguration targetedNetwork =
5143                 mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
5144         if (targetedNetwork != null) {
5145             switch (targetedNetwork.enterpriseConfig.getEapMethod()) {
5146                 case WifiEnterpriseConfig.Eap.SIM:
5147                 case WifiEnterpriseConfig.Eap.AKA:
5148                 case WifiEnterpriseConfig.Eap.AKA_PRIME:
5149                     if (errorCode == WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED) {
5150                         mWifiCarrierInfoManager.resetCarrierKeysForImsiEncryption(targetedNetwork);
5151                     } else {
5152                         int carrierId = targetedNetwork.carrierId;
5153                         if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(carrierId)) {
5154                             mWifiPseudonymManager.retrieveOobPseudonymWithRateLimit(carrierId);
5155                         }
5156                     }
5157                     break;
5158 
5159                 default:
5160                     // Do Nothing
5161             }
5162         }
5163     }
5164 
5165     /**
5166      * All callbacks are triggered on the main Wifi thread.
5167      * See {@link WifiNetworkAgent#WifiNetworkAgent}'s looper argument in
5168      * {@link WifiInjector#makeWifiNetworkAgent}.
5169      */
5170     private class WifiNetworkAgentCallback implements WifiNetworkAgent.Callback {
5171         private int mLastNetworkStatus = -1; // To detect when the status really changes
5172 
isThisCallbackActive()5173         private boolean isThisCallbackActive() {
5174             return mNetworkAgent != null && mNetworkAgent.getCallback() == this;
5175         }
5176 
5177         @Override
onNetworkUnwanted()5178         public void onNetworkUnwanted() {
5179             // Ignore if we're not the current networkAgent.
5180             if (!isThisCallbackActive()) return;
5181             if (mVerboseLoggingEnabled) {
5182                 logd("WifiNetworkAgent -> Wifi unwanted score " + mWifiInfo.getScore());
5183             }
5184             unwantedNetwork(NETWORK_STATUS_UNWANTED_DISCONNECT);
5185         }
5186 
5187         @Override
onValidationStatus(int status, @Nullable Uri redirectUri)5188         public void onValidationStatus(int status, @Nullable Uri redirectUri) {
5189             if (!isThisCallbackActive()) return;
5190             if (status == mLastNetworkStatus) return;
5191             mLastNetworkStatus = status;
5192             if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID) {
5193                 if (mVerboseLoggingEnabled) {
5194                     logd("WifiNetworkAgent -> Wifi networkStatus invalid, score="
5195                             + mWifiInfo.getScore());
5196                 }
5197                 unwantedNetwork(NETWORK_STATUS_UNWANTED_VALIDATION_FAILED);
5198             } else if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
5199                 if (mVerboseLoggingEnabled) {
5200                     logd("WifiNetworkAgent -> Wifi networkStatus valid, score= "
5201                             + mWifiInfo.getScore());
5202                 }
5203                 mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK);
5204                 doNetworkStatus(status);
5205             }
5206             boolean captivePortalDetected = redirectUri != null
5207                     && redirectUri.toString() != null
5208                     && redirectUri.toString().length() > 0;
5209             if (captivePortalDetected) {
5210                 Log.i(getTag(), "Captive Portal detected, status=" + status
5211                         + ", redirectUri=" + redirectUri);
5212                 mWifiConfigManager.noteCaptivePortalDetected(mWifiInfo.getNetworkId());
5213                 mCmiMonitor.onCaptivePortalDetected(mClientModeManager);
5214                 mCurrentConnectionDetectedCaptivePortal = true;
5215             }
5216         }
5217 
5218         @Override
onSaveAcceptUnvalidated(boolean accept)5219         public void onSaveAcceptUnvalidated(boolean accept) {
5220             if (!isThisCallbackActive()) return;
5221             ClientModeImpl.this.sendMessage(CMD_ACCEPT_UNVALIDATED, accept ? 1 : 0);
5222         }
5223 
5224         @Override
onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet)5225         public void onStartSocketKeepalive(int slot, @NonNull Duration interval,
5226                 @NonNull KeepalivePacketData packet) {
5227             if (!isThisCallbackActive()) return;
5228             ClientModeImpl.this.sendMessage(
5229                     CMD_START_IP_PACKET_OFFLOAD, slot, (int) interval.getSeconds(), packet);
5230         }
5231 
5232         @Override
onStopSocketKeepalive(int slot)5233         public void onStopSocketKeepalive(int slot) {
5234             if (!isThisCallbackActive()) return;
5235             ClientModeImpl.this.sendMessage(CMD_STOP_IP_PACKET_OFFLOAD, slot);
5236         }
5237 
5238         @Override
onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet)5239         public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) {
5240             if (!isThisCallbackActive()) return;
5241             ClientModeImpl.this.sendMessage(
5242                     CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0, packet);
5243         }
5244 
5245         @Override
onRemoveKeepalivePacketFilter(int slot)5246         public void onRemoveKeepalivePacketFilter(int slot) {
5247             if (!isThisCallbackActive()) return;
5248             ClientModeImpl.this.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF, slot);
5249         }
5250 
5251         @Override
onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)5252         public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
5253             if (!isThisCallbackActive()) return;
5254             // Enable RSSI monitoring only on primary STA
5255             if (!isPrimary()) {
5256                 return;
5257             }
5258             mWifiThreadRunner.post(
5259                     () -> mRssiMonitor.updateAppThresholdsAndStartMonitor(thresholds));
5260         }
5261 
5262         @Override
onAutomaticReconnectDisabled()5263         public void onAutomaticReconnectDisabled() {
5264             if (!isThisCallbackActive()) return;
5265             unwantedNetwork(NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN);
5266         }
5267 
5268         @Override
onDscpPolicyStatusUpdated(int policyId, int status)5269         public void onDscpPolicyStatusUpdated(int policyId, int status) {
5270             mQosPolicyRequestHandler.setQosPolicyStatus(policyId, status);
5271         }
5272     }
5273 
5274     @Override
onDeviceMobilityStateUpdated(@eviceMobilityState int newState)5275     public void onDeviceMobilityStateUpdated(@DeviceMobilityState int newState) {
5276         if (!mScreenOn) {
5277             return;
5278         }
5279         if (isPrimary()) {
5280             mRssiMonitor.updatePollRssiInterval(newState);
5281         }
5282     }
5283 
5284     @Override
setLinkLayerStatsPollingInterval(int newIntervalMs)5285     public void setLinkLayerStatsPollingInterval(int newIntervalMs) {
5286         mRssiMonitor.overridePollRssiInterval(newIntervalMs);
5287     }
5288 
isNewConnectionInProgress(@onNull String disconnectingSsid)5289     private boolean isNewConnectionInProgress(@NonNull String disconnectingSsid) {
5290         String targetSsid = getConnectingSsidInternal();
5291         // If network is removed while connecting, targetSsid can be null.
5292         if (targetSsid == null) {
5293             return false;
5294         }
5295         // When connecting to another network while already connected, the old network will first
5296         // disconnect before the new connection can begin. Thus, the presence of a mLastNetworkId
5297         // that's different from the mTargetNetworkId indicates that this network disconnection is
5298         // triggered for the previously connected network as opposed to the current ongoing
5299         // connection.
5300         boolean isConnectingWhileAlreadyConnected =
5301                 mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
5302                 && mLastNetworkId != mTargetNetworkId;
5303 
5304         // This second condition is needed to catch cases where 2 simultaneous connections happen
5305         // back-to-back. When a new connection start before the previous one finishes, the
5306         // previous network will get removed from the supplicant and cause a disconnect message
5307         // to be received with the previous network's SSID. Thus, if the disconnecting SSID does not
5308         // match the target SSID, it means a new connection is in progress.
5309         boolean isConnectingToAnotherNetwork = !disconnectingSsid.equals(targetSsid);
5310         return isConnectingWhileAlreadyConnected || isConnectingToAnotherNetwork;
5311     }
5312 
unwantedNetwork(int reason)5313     private void unwantedNetwork(int reason) {
5314         sendMessage(CMD_UNWANTED_NETWORK, reason);
5315     }
5316 
doNetworkStatus(int status)5317     private void doNetworkStatus(int status) {
5318         sendMessage(CMD_NETWORK_STATUS, status);
5319     }
5320 
updatePseudonymFromOob(int carrierId, String pseudonym)5321     private void updatePseudonymFromOob(int carrierId, String pseudonym) {
5322         sendMessage(CMD_UPDATE_OOB_PSEUDONYM, carrierId, 0, pseudonym);
5323     }
5324 
5325     class ConnectingOrConnectedState extends RunnerState {
ConnectingOrConnectedState(int threshold)5326         ConnectingOrConnectedState(int threshold) {
5327             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
5328         }
5329 
5330         @Override
enterImpl()5331         public void enterImpl() {
5332             if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering ConnectingOrConnectedState");
5333             mCmiMonitor.onConnectionStart(mClientModeManager);
5334         }
5335 
5336         @Override
exitImpl()5337         public void exitImpl() {
5338             if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting ConnectingOrConnectedState");
5339             mCmiMonitor.onConnectionEnd(mClientModeManager);
5340 
5341             // Not connected/connecting to any network:
5342             // 1. Disable the network in supplicant to prevent it from auto-connecting. We don't
5343             // remove the network to avoid losing any cached info in supplicant (reauth, etc) in
5344             // case we reconnect back to the same network.
5345             // 2. Set a random MAC address to ensure that we're not leaking the MAC address.
5346             mWifiNative.disableNetwork(mInterfaceName);
5347             if (mWifiGlobals.isConnectedMacRandomizationEnabled()) {
5348                 mFailedToResetMacAddress = !mWifiNative.setStaMacAddress(
5349                         mInterfaceName, MacAddressUtils.createRandomUnicastAddress());
5350                 if (mFailedToResetMacAddress) {
5351                     Log.e(getTag(), "Failed to set random MAC address on disconnect");
5352                 }
5353             }
5354             if (mWifiInfo.getBSSID() != null) {
5355                 mWifiBlocklistMonitor.removeAffiliatedBssids(mWifiInfo.getBSSID());
5356             }
5357             mWifiInfo.reset();
5358             mWifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
5359             mWifiScoreCard.noteSupplicantStateChanged(mWifiInfo);
5360             updateCurrentConnectionInfo();
5361 
5362             // For secondary client roles, they should stop themselves upon disconnection.
5363             // - Primary role shouldn't because it is persistent, and should try connecting to other
5364             //   networks upon disconnection.
5365             // - ROLE_CLIENT_LOCAL_ONLY shouldn't because it has auto-retry logic if the connection
5366             //   fails. WifiNetworkFactory will explicitly remove the CMM when the request is
5367             //   complete.
5368             // TODO(b/160346062): Maybe clean this up by having ClientModeManager register a
5369             //  onExitConnectingOrConnectedState() callback with ClientModeImpl and implementing
5370             //  this logic in ClientModeManager. ClientModeImpl should be role-agnostic.
5371             ClientRole role = mClientModeManager.getRole();
5372             if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED
5373                     || role == ROLE_CLIENT_SECONDARY_TRANSIENT) {
5374                 if (mVerboseLoggingEnabled) {
5375                     Log.d(getTag(), "Disconnected in ROLE_CLIENT_SECONDARY_*, "
5376                             + "stop ClientModeManager=" + mClientModeManager);
5377                 }
5378                 // stop owner ClientModeManager, which will in turn stop this ClientModeImpl
5379                 mClientModeManager.stop();
5380             }
5381         }
5382 
5383         @Override
getMessageLogRec(int what)5384         String getMessageLogRec(int what) {
5385             return ClientModeImpl.class.getSimpleName() + "."
5386                     + ConnectingOrConnectedState.class.getSimpleName() + "." + getWhatToString(
5387                     what);
5388         }
5389 
5390         @Override
processMessageImpl(Message message)5391         public boolean processMessageImpl(Message message) {
5392             boolean handleStatus = HANDLED;
5393             switch (message.what) {
5394                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: {
5395                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
5396                     SupplicantState state = handleSupplicantStateChange(stateChangeResult);
5397                     // Supplicant can fail to report a NETWORK_DISCONNECTION_EVENT
5398                     // when authentication times out after a successful connection,
5399                     // we can figure this from the supplicant state. If supplicant
5400                     // state is DISCONNECTED, but the agent is not disconnected, we
5401                     // need to handle a disconnection
5402                     if (mVerboseLoggingEnabled) {
5403                         log("ConnectingOrConnectedState: Supplicant State change "
5404                                 + stateChangeResult);
5405                     }
5406                     @SupplicantEventCode int supplicantEvent;
5407                     switch (stateChangeResult.state) {
5408                         case COMPLETED:
5409                             supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_CONNECTED;
5410                             break;
5411                         case ASSOCIATING:
5412                             supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_ASSOCIATING;
5413                             break;
5414                         case ASSOCIATED:
5415                             supplicantEvent = SupplicantStaIfaceHal.SUPPLICANT_EVENT_ASSOCIATED;
5416                             break;
5417                         default:
5418                             supplicantEvent = -1;
5419                     }
5420                     if (supplicantEvent != -1) {
5421                         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(
5422                                     stateChangeResult.networkId);
5423                         try {
5424                             logEventIfManagedNetwork(config, supplicantEvent,
5425                                     MacAddress.fromString(stateChangeResult.bssid), "");
5426                         } catch (IllegalArgumentException e) {
5427                             Log.i(TAG, "Invalid bssid received for state change event");
5428                         }
5429                     }
5430                     if (state == SupplicantState.DISCONNECTED && mNetworkAgent != null) {
5431                         if (mVerboseLoggingEnabled) {
5432                             log("Missed CTRL-EVENT-DISCONNECTED, disconnect");
5433                         }
5434                         handleNetworkDisconnect(false,
5435                                 WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED);
5436                         transitionTo(mDisconnectedState);
5437                     }
5438                     if (state == SupplicantState.COMPLETED) {
5439                         mWifiScoreReport.noteIpCheck();
5440                     }
5441                     break;
5442                 }
5443                 case WifiMonitor.ASSOCIATED_BSSID_EVENT: {
5444                     // This is where we can confirm the connection BSSID. Use it to find the
5445                     // right ScanDetail to populate metrics.
5446                     String someBssid = (String) message.obj;
5447                     if (someBssid != null) {
5448                         // Get the ScanDetail associated with this BSSID.
5449                         ScanDetailCache scanDetailCache =
5450                                 mWifiConfigManager.getScanDetailCacheForNetwork(mTargetNetworkId);
5451                         if (scanDetailCache != null) {
5452                             mWifiMetrics.setConnectionScanDetail(mInterfaceName,
5453                                     scanDetailCache.getScanDetail(someBssid));
5454                         }
5455                         // Update last associated BSSID
5456                         mLastBssid = someBssid;
5457                     }
5458                     handleStatus = NOT_HANDLED;
5459                     break;
5460                 }
5461                 case WifiMonitor.NETWORK_CONNECTION_EVENT: {
5462                     if (mVerboseLoggingEnabled) log("Network connection established");
5463                     NetworkConnectionEventInfo connectionInfo =
5464                             (NetworkConnectionEventInfo) message.obj;
5465                     mLastNetworkId = connectionInfo.networkId;
5466                     mSentHLPs = connectionInfo.isFilsConnection;
5467                     if (mSentHLPs) mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount();
5468                     mWifiConfigManager.clearRecentFailureReason(mLastNetworkId);
5469                     mLastBssid = connectionInfo.bssid;
5470                     // TODO: This check should not be needed after ClientModeImpl refactor.
5471                     // Currently, the last connected network configuration is left in
5472                     // wpa_supplicant, this may result in wpa_supplicant initiating connection
5473                     // to it after a config store reload. Hence the old network Id lookups may not
5474                     // work, so disconnect the network and let network selector reselect a new
5475                     // network.
5476                     WifiConfiguration config = getConnectedWifiConfigurationInternal();
5477                     if (config == null) {
5478                         logw("Connected to unknown networkId " + mLastNetworkId
5479                                 + ", disconnecting...");
5480                         sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK);
5481                         break;
5482                     }
5483                     handleNetworkConnectionEventInfo(config, connectionInfo);
5484                     mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
5485 
5486                     ScanDetailCache scanDetailCache =
5487                             mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
5488                     ScanResult scanResult = null;
5489                     if (scanDetailCache != null && mLastBssid != null) {
5490                         scanResult = scanDetailCache.getScanResult(mLastBssid);
5491                         if (scanResult != null) {
5492                             mWifiInfo.setFrequency(scanResult.frequency);
5493                         }
5494                     }
5495 
5496                     // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA'
5497                     if (config.enterpriseConfig != null
5498                             && config.enterpriseConfig.isAuthenticationSimBased()) {
5499                         if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(
5500                                 config.carrierId)) {
5501                             if (mVerboseLoggingEnabled) {
5502                                 logd("add PseudonymUpdatingListener");
5503                             }
5504                             mWifiPseudonymManager.registerPseudonymUpdatingListener(
5505                                     mPseudonymUpdatingListener);
5506                         }
5507                         mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config);
5508                         mLastSimBasedConnectionCarrierName =
5509                                 mWifiCarrierInfoManager.getCarrierNameForSubId(mLastSubId);
5510                         String anonymousIdentity =
5511                                 mWifiNative.getEapAnonymousIdentity(mInterfaceName);
5512                         if (!TextUtils.isEmpty(anonymousIdentity)
5513                                 && !WifiCarrierInfoManager
5514                                 .isAnonymousAtRealmIdentity(anonymousIdentity)) {
5515                             String decoratedPseudonym = mWifiCarrierInfoManager
5516                                     .decoratePseudonymWith3GppRealm(config,
5517                                             anonymousIdentity);
5518                             boolean updateToNativeService = false;
5519                             if (decoratedPseudonym != null
5520                                     && !decoratedPseudonym.equals(anonymousIdentity)) {
5521                                 anonymousIdentity = decoratedPseudonym;
5522                                 // propagate to the supplicant to avoid using
5523                                 // the original anonymous identity for firmware
5524                                 // roaming.
5525                                 if (mVerboseLoggingEnabled) {
5526                                     log("Update decorated pseudonym: " + anonymousIdentity);
5527                                 }
5528                                 updateToNativeService = true;
5529                             }
5530                             // This needs native change to avoid disconnecting from the current
5531                             // network. Consider that older releases might not be able to have
5532                             // the vendor partition updated, only update to native service on T
5533                             // or newer.
5534                             if (SdkLevel.isAtLeastT()) {
5535                                 mWifiNative.setEapAnonymousIdentity(mInterfaceName,
5536                                         anonymousIdentity, updateToNativeService);
5537                             }
5538                             if (mVerboseLoggingEnabled) {
5539                                 log("EAP Pseudonym: " + anonymousIdentity);
5540                             }
5541                             // Save the pseudonym only if it is a real one
5542                             config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
5543                             int carrierId = config.carrierId;
5544                             if (mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(
5545                                     carrierId)) {
5546                                 mWifiPseudonymManager.setInBandPseudonym(carrierId,
5547                                         anonymousIdentity);
5548                             }
5549                         } else {
5550                             // Clear any stored pseudonyms
5551                             config.enterpriseConfig.setAnonymousIdentity(null);
5552                         }
5553                         mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
5554                         if (config.isPasspoint()) {
5555                             mPasspointManager.setAnonymousIdentity(config);
5556                         } else if (config.fromWifiNetworkSuggestion) {
5557                             mWifiNetworkSuggestionsManager.setAnonymousIdentity(config);
5558                         }
5559                     }
5560                     // When connecting to Passpoint, ask for the Venue URL
5561                     if (config.isPasspoint()) {
5562                         mTermsAndConditionsUrl = null;
5563                         if (scanResult == null && mLastBssid != null) {
5564                             // The cached scan result of connected network would be null at the
5565                             // first connection, try to check full scan result list again to look up
5566                             // matched scan result associated to the current SSID and BSSID.
5567                             scanResult = mScanRequestProxy.getScanResult(mLastBssid);
5568                         }
5569                         if (scanResult != null) {
5570                             mPasspointManager.requestVenueUrlAnqpElement(scanResult);
5571                         }
5572                     }
5573                     mWifiInfo.setNetworkKey(config.getNetworkKeyFromSecurityType(
5574                             mWifiInfo.getCurrentSecurityType()));
5575                     if (mApplicationQosPolicyRequestHandler.isFeatureEnabled()) {
5576                         mApplicationQosPolicyRequestHandler.queueAllPoliciesOnIface(mInterfaceName);
5577                     }
5578                     updateLayer2Information();
5579                     updateCurrentConnectionInfo();
5580                     transitionTo(mL3ProvisioningState);
5581                     break;
5582                 }
5583                 case CMD_UPDATE_OOB_PSEUDONYM: {
5584                     WifiConfiguration config = getConnectedWifiConfigurationInternal();
5585                     if (config == null) {
5586                         log("OOB pseudonym is updated, but no valid connected network.");
5587                         break;
5588                     }
5589                     int updatingCarrierId = message.arg1;
5590                     if (config.enterpriseConfig == null
5591                             || !config.enterpriseConfig.isAuthenticationSimBased()
5592                             || !mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(
5593                                     config.carrierId)
5594                             || updatingCarrierId != config.carrierId) {
5595                         log("OOB pseudonym is not applied.");
5596                         break;
5597                     }
5598                     if (SdkLevel.isAtLeastT()) {
5599                         log("send OOB pseudonym to supplicant");
5600                         String pseudonym = (String) message.obj;
5601                         mWifiNative.setEapAnonymousIdentity(mInterfaceName,
5602                                 mWifiCarrierInfoManager.decoratePseudonymWith3GppRealm(
5603                                         config, pseudonym),
5604                                 /*updateToNativeService=*/ true);
5605                     }
5606                     break;
5607                 }
5608                 case WifiMonitor.SUP_REQUEST_SIM_AUTH: {
5609                     logd("Received SUP_REQUEST_SIM_AUTH");
5610                     SimAuthRequestData requestData = (SimAuthRequestData) message.obj;
5611                     if (requestData != null) {
5612                         if (requestData.protocol == WifiEnterpriseConfig.Eap.SIM) {
5613                             handleGsmAuthRequest(requestData);
5614                         } else if (requestData.protocol == WifiEnterpriseConfig.Eap.AKA
5615                                 || requestData.protocol == WifiEnterpriseConfig.Eap.AKA_PRIME) {
5616                             handle3GAuthRequest(requestData);
5617                         }
5618                     } else {
5619                         loge("Invalid SIM auth request");
5620                     }
5621                     break;
5622                 }
5623                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: {
5624                     DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj;
5625                     if (mVerboseLoggingEnabled) {
5626                         log("ConnectingOrConnectedState: Network disconnection " + eventInfo);
5627                     }
5628                     if (eventInfo.reasonCode
5629                             == StaIfaceReasonCode.FOURWAY_HANDSHAKE_TIMEOUT) {
5630                         String bssid = !isValidBssid(eventInfo.bssid)
5631                                 ? mTargetBssid : eventInfo.bssid;
5632                         mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
5633                                 getConnectingSsidInternal(), bssid,
5634                                 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION,
5635                                 isConnected());
5636                     }
5637                     WifiConfiguration config = getConnectedWifiConfigurationInternal();
5638                     if (config == null) {
5639                         config = getConnectingWifiConfigurationInternal();
5640                     }
5641                     clearNetworkCachedDataIfNeeded(config, eventInfo.reasonCode);
5642                     try {
5643                         logEventIfManagedNetwork(config,
5644                                 SupplicantStaIfaceHal.SUPPLICANT_EVENT_DISCONNECTED,
5645                                 MacAddress.fromString(eventInfo.bssid),
5646                                 "reason=" + StaIfaceReasonCode.toString(eventInfo.reasonCode));
5647                     } catch (IllegalArgumentException e) {
5648                         Log.e(TAG, "Invalid bssid received for disconnection event");
5649                     }
5650                     boolean newConnectionInProgress = isNewConnectionInProgress(eventInfo.ssid);
5651                     if (!newConnectionInProgress) {
5652                         int level2FailureReason = eventInfo.locallyGenerated
5653                                 ? WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN :
5654                                 WifiMetricsProto.ConnectionEvent.DISCONNECTION_NON_LOCAL;
5655                         if (!eventInfo.locallyGenerated) {
5656                             mWifiScoreCard.noteNonlocalDisconnect(
5657                                     mInterfaceName, eventInfo.reasonCode);
5658                         }
5659                         reportConnectionAttemptEnd(
5660                                 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
5661                                 WifiMetricsProto.ConnectionEvent.HLF_NONE, level2FailureReason);
5662                     }
5663                     handleNetworkDisconnect(newConnectionInProgress, eventInfo.reasonCode);
5664                     if (!newConnectionInProgress) {
5665                         transitionTo(mDisconnectedState);
5666                     }
5667                     mTermsAndConditionsUrl = null;
5668                     break;
5669                 }
5670                 case WifiMonitor.TARGET_BSSID_EVENT: {
5671                     // Trying to associate to this BSSID
5672                     if (message.obj != null) {
5673                         mTargetBssid = (String) message.obj;
5674                     }
5675                     break;
5676                 }
5677                 case WifiMonitor.AUXILIARY_SUPPLICANT_EVENT: {
5678                     SupplicantEventInfo eventInfo = (SupplicantEventInfo) message.obj;
5679                     logEventIfManagedNetwork(getConnectingWifiConfigurationInternal(),
5680                             eventInfo.eventCode, eventInfo.bssid,
5681                             eventInfo.reasonString);
5682                     break;
5683                 }
5684                 case CMD_DISCONNECT: {
5685                     mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
5686                             message.arg1);
5687                     mWifiNative.disconnect(mInterfaceName);
5688                     break;
5689                 }
5690                 case CMD_PRE_DHCP_ACTION:
5691                 case CMD_PRE_DHCP_ACTION_COMPLETE:
5692                 case CMD_POST_DHCP_ACTION:
5693                 case CMD_IPV4_PROVISIONING_SUCCESS:
5694                 case CMD_IP_CONFIGURATION_SUCCESSFUL:
5695                 case CMD_IPV4_PROVISIONING_FAILURE: {
5696                     handleStatus = handleL3MessagesWhenNotConnected(message);
5697                     break;
5698                 }
5699                 case WifiMonitor.TRANSITION_DISABLE_INDICATION: {
5700                     log("Received TRANSITION_DISABLE_INDICATION: networkId=" + message.arg1
5701                             + ", indication=" + message.arg2 + ", bssid=" + mLastBssid);
5702                     if (isValidTransitionDisableIndicationSource(mLastBssid, message.arg2)) {
5703                         mWifiConfigManager.updateNetworkTransitionDisable(message.arg1,
5704                                 message.arg2);
5705                     } else {
5706                         Log.w(getTag(), "Drop TRANSITION_DISABLE_INDICATION event"
5707                                 + " from an invalid source.");
5708                     }
5709                     break;
5710                 }
5711                 case WifiMonitor.QOS_POLICY_RESET_EVENT: {
5712                     if (SdkLevel.isAtLeastT() && mNetworkAgent != null
5713                             && mWifiNative.isQosPolicyFeatureEnabled()) {
5714                         mNetworkAgent.sendRemoveAllDscpPolicies();
5715                     }
5716                     break;
5717                 }
5718                 case WifiMonitor.QOS_POLICY_REQUEST_EVENT: {
5719                     if (SdkLevel.isAtLeastT() && mWifiNative.isQosPolicyFeatureEnabled()) {
5720                         mQosPolicyRequestHandler.queueQosPolicyRequest(
5721                                 message.arg1, (List<QosPolicyRequest>) message.obj);
5722                     }
5723                     break;
5724                 }
5725                 case CMD_REJECT_EAP_INSECURE_CONNECTION: {
5726                     log("Received CMD_REJECT_EAP_INSECURE_CONNECTION event");
5727                     boolean disconnectRequired = message.arg2 == 1;
5728 
5729                     // TOFU connections are not established until the user approves the certificate.
5730                     // If TOFU is not supported and the network is already connected, this will
5731                     // disconnect the network.
5732                     if (disconnectRequired) {
5733                         sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
5734                     }
5735                     break;
5736                 }
5737                 default: {
5738                     handleStatus = NOT_HANDLED;
5739                     break;
5740                 }
5741             }
5742             if (handleStatus == HANDLED) {
5743                 logStateAndMessage(message, this);
5744             }
5745             return handleStatus;
5746         }
5747 
isValidTransitionDisableIndicationSource(String bssid, @WifiMonitor.TransitionDisableIndication int indicationBit)5748         private boolean isValidTransitionDisableIndicationSource(String bssid,
5749                 @WifiMonitor.TransitionDisableIndication int indicationBit) {
5750             ScanResult result = mScanRequestProxy.getScanResult(mLastBssid);
5751             if (null == result) return false;
5752 
5753             // SAE TDI should only come from a PSK/SAE BSS or a SAE BSS.
5754             if (0 != (indicationBit & WifiMonitor.TDI_USE_WPA3_PERSONAL)) {
5755                 return ScanResultUtil.isScanResultForSaeNetwork(result)
5756                         || ScanResultUtil.isScanResultForPskSaeTransitionNetwork(result);
5757             }
5758             // SAE_PK TDI should only come from a SAE BSS.
5759             if (0 != (indicationBit & WifiMonitor.TDI_USE_SAE_PK)) {
5760                 return ScanResultUtil.isScanResultForSaeNetwork(result);
5761             }
5762             // WPA3 Enterprise TDI should only come from a WPA2/WPA3 Enterprise
5763             // BSS or a WPA3 Enterprise BSS.
5764             if (0 != (indicationBit & WifiMonitor.TDI_USE_WPA3_ENTERPRISE)) {
5765                 return ScanResultUtil.isScanResultForWpa3EnterpriseOnlyNetwork(result)
5766                         || ScanResultUtil.isScanResultForWpa3EnterpriseTransitionNetwork(result);
5767             }
5768             // OWE TDI should only come from an OPEN/OWE BSS or an OWE BSS.
5769             if (0 != (indicationBit & WifiMonitor.TDI_USE_ENHANCED_OPEN)) {
5770                 return ScanResultUtil.isScanResultForOweNetwork(result)
5771                         || ScanResultUtil.isScanResultForOweTransitionNetwork(result);
5772             }
5773             return false;
5774         }
5775     }
5776 
5777     class L2ConnectingState extends RunnerState {
L2ConnectingState(int threshold)5778         L2ConnectingState(int threshold) {
5779             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
5780         }
5781 
5782         @Override
enterImpl()5783         public void enterImpl() {
5784             if (mVerboseLoggingEnabled) Log.v(getTag(), "Entering L2ConnectingState");
5785             // Make sure we connect: we enter this state prior to connecting to a new
5786             // network. In some cases supplicant ignores the connect requests (it might not
5787             // find the target SSID in its cache), Therefore we end up stuck that state, hence the
5788             // need for the watchdog.
5789             mConnectingWatchdogCount++;
5790             logd("Start Connecting Watchdog " + mConnectingWatchdogCount);
5791             sendMessageDelayed(obtainMessage(CMD_CONNECTING_WATCHDOG_TIMER,
5792                     mConnectingWatchdogCount, 0), CONNECTING_WATCHDOG_TIMEOUT_MS);
5793         }
5794 
5795         @Override
exitImpl()5796         public void exitImpl() {
5797             if (mVerboseLoggingEnabled) Log.v(getTag(), "Exiting L2ConnectingState");
5798             // Cancel any pending CMD_CONNECTING_WATCHDOG_TIMER since this is only valid in
5799             // L2ConnectingState anyway.
5800             removeMessages(CMD_CONNECTING_WATCHDOG_TIMER);
5801         }
5802 
5803         @Override
getMessageLogRec(int what)5804         String getMessageLogRec(int what) {
5805             return ClientModeImpl.class.getSimpleName() + "."
5806                     + L2ConnectingState.class.getSimpleName() + "." + getWhatToString(what);
5807         }
5808 
5809         @Override
processMessageImpl(Message message)5810         public boolean processMessageImpl(Message message) {
5811             boolean handleStatus = HANDLED;
5812             switch (message.what) {
5813                 case WifiMonitor.NETWORK_NOT_FOUND_EVENT:
5814                     mNetworkNotFoundEventCount++;
5815                     String networkName = (String) message.obj;
5816                     if (networkName != null && !networkName.equals(getConnectingSsidInternal())) {
5817                         loge("Network not found event received, network: " + networkName
5818                                 + " which is not the target network: "
5819                                 + getConnectingSsidInternal());
5820                         break;
5821                     }
5822                     Log.d(getTag(), "Network not found event received: network: " + networkName);
5823                     if (mNetworkNotFoundEventCount
5824                             >= mWifiGlobals.getNetworkNotFoundEventThreshold()
5825                             && mTargetWifiConfiguration != null
5826                             && mTargetWifiConfiguration.SSID != null
5827                             && mTargetWifiConfiguration.SSID.equals(networkName)) {
5828                         stopIpClient();
5829                         mWifiConfigManager.updateNetworkSelectionStatus(
5830                                 mTargetWifiConfiguration.networkId,
5831                                 WifiConfiguration.NetworkSelectionStatus
5832                                         .DISABLED_NETWORK_NOT_FOUND);
5833                         if (SdkLevel.isAtLeastS()) {
5834                             mWifiConfigManager.setRecentFailureAssociationStatus(
5835                                     mTargetWifiConfiguration.networkId,
5836                                     WifiConfiguration.RECENT_FAILURE_NETWORK_NOT_FOUND);
5837                         }
5838                         reportConnectionAttemptEnd(
5839                                 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_NOT_FOUND,
5840                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
5841                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
5842                         handleNetworkDisconnect(false,
5843                                 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED);
5844                         transitionTo(mDisconnectedState); // End of connection attempt.
5845                     }
5846                     break;
5847                 case WifiMonitor.ASSOCIATION_REJECTION_EVENT: {
5848                     AssocRejectEventInfo assocRejectEventInfo = (AssocRejectEventInfo) message.obj;
5849                     log("L2ConnectingState: Association rejection " + assocRejectEventInfo);
5850                     if (!assocRejectEventInfo.ssid.equals(getConnectingSsidInternal())) {
5851                         loge("Association rejection event received on not target network");
5852                         break;
5853                     }
5854                     stopIpClient();
5855                     mWifiDiagnostics.triggerBugReportDataCapture(
5856                             WifiDiagnostics.REPORT_REASON_ASSOC_FAILURE);
5857                     String bssid = assocRejectEventInfo.bssid;
5858                     boolean timedOut = assocRejectEventInfo.timedOut;
5859                     int statusCode = assocRejectEventInfo.statusCode;
5860                     if (!isValidBssid(bssid)) {
5861                         // If BSSID is null, use the target roam BSSID
5862                         bssid = mTargetBssid;
5863                     } else if (SUPPLICANT_BSSID_ANY.equals(mTargetBssid)) {
5864                         // This is needed by WifiBlocklistMonitor to block continuously
5865                         // failing BSSIDs. Need to set here because mTargetBssid is currently
5866                         // not being set until association success.
5867                         mTargetBssid = bssid;
5868                     }
5869                     if (!isSecondaryInternet()) {
5870                         mWifiConfigManager.updateNetworkSelectionStatus(mTargetNetworkId,
5871                                 WifiConfiguration.NetworkSelectionStatus
5872                                         .DISABLED_ASSOCIATION_REJECTION);
5873                     }
5874                     setAssociationRejectionStatusInConfig(mTargetNetworkId, assocRejectEventInfo);
5875                     int level2FailureReason =
5876                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN;
5877                     if (statusCode == StaIfaceStatusCode.AP_UNABLE_TO_HANDLE_NEW_STA
5878                             || statusCode == StaIfaceStatusCode.ASSOC_REJECTED_TEMPORARILY
5879                             || statusCode == StaIfaceStatusCode.DENIED_INSUFFICIENT_BANDWIDTH) {
5880                         level2FailureReason = WifiMetricsProto.ConnectionEvent
5881                                 .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA;
5882                     }
5883 
5884                     // If rejection occurred while Metrics is tracking a ConnectionEvent, end it.
5885                     reportConnectionAttemptEnd(
5886                             timedOut
5887                                     ? WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_TIMED_OUT
5888                                     : WifiMetrics.ConnectionEvent.FAILURE_ASSOCIATION_REJECTION,
5889                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
5890                             level2FailureReason);
5891 
5892                     if (level2FailureReason != WifiMetricsProto.ConnectionEvent
5893                             .ASSOCIATION_REJECTION_AP_UNABLE_TO_HANDLE_NEW_STA
5894                             && !isSecondaryInternet()) {
5895                         mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
5896                                 getConnectingSsidInternal(), bssid,
5897                                 WifiLastResortWatchdog.FAILURE_CODE_ASSOCIATION,
5898                                 isConnected());
5899                     }
5900                     handleNetworkDisconnect(false,
5901                             WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED);
5902                     transitionTo(mDisconnectedState); // End of connection attempt.
5903                     break;
5904                 }
5905                 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT: {
5906                     AuthenticationFailureEventInfo authenticationFailureEventInfo =
5907                             (AuthenticationFailureEventInfo) message.obj;
5908                     if (!TextUtils.equals(authenticationFailureEventInfo.ssid,
5909                             getConnectingSsidInternal())) {
5910                         logw("Authentication failure event received on not target network");
5911                         break;
5912                     }
5913                     stopIpClient();
5914                     mWifiDiagnostics.triggerBugReportDataCapture(
5915                             WifiDiagnostics.REPORT_REASON_AUTH_FAILURE);
5916                     int disableReason = WifiConfiguration.NetworkSelectionStatus
5917                             .DISABLED_AUTHENTICATION_FAILURE;
5918                     int reasonCode = authenticationFailureEventInfo.reasonCode;
5919                     int errorCode = authenticationFailureEventInfo.errorCode;
5920                     log("L2ConnectingState: Authentication failure "
5921                             + " reason=" + reasonCode + " error=" + errorCode);
5922                     WifiConfiguration targetedNetwork =
5923                             mWifiConfigManager.getConfiguredNetwork(mTargetNetworkId);
5924                     // Check if this is a permanent wrong password failure.
5925                     if (isPermanentWrongPasswordFailure(mTargetNetworkId, reasonCode)) {
5926                         disableReason = WifiConfiguration.NetworkSelectionStatus
5927                                 .DISABLED_BY_WRONG_PASSWORD;
5928                         // For primary role, send error notification except for local only network,
5929                         // for secondary role, send only for secondary internet.
5930                         final boolean isForLocalOnly = isRequestedForLocalOnly(
5931                                 targetedNetwork, mTargetBssid) || isLocalOnly();
5932                         final boolean needNotifyError = isPrimary() ? !isForLocalOnly
5933                                 : isSecondaryInternet();
5934                         if (targetedNetwork != null && needNotifyError) {
5935                             mWrongPasswordNotifier.onWrongPasswordError(targetedNetwork);
5936                         }
5937                     } else if (reasonCode == WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) {
5938                         logEventIfManagedNetwork(targetedNetwork,
5939                                 SupplicantStaIfaceHal.SUPPLICANT_EVENT_EAP_FAILURE,
5940                                 authenticationFailureEventInfo.bssid, "error=" + errorCode);
5941                         if (targetedNetwork != null && targetedNetwork.enterpriseConfig != null
5942                                 && targetedNetwork.enterpriseConfig.isAuthenticationSimBased()) {
5943                             // only show EAP failure notification if primary
5944                             WifiBlocklistMonitor.CarrierSpecificEapFailureConfig eapFailureConfig =
5945                                     mEapFailureNotifier.onEapFailure(errorCode, targetedNetwork,
5946                                             isPrimary());
5947                             if (eapFailureConfig != null) {
5948                                 disableReason = WifiConfiguration.NetworkSelectionStatus
5949                                     .DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR;
5950                                 mWifiBlocklistMonitor.loadCarrierConfigsForDisableReasonInfos(
5951                                         eapFailureConfig);
5952                             }
5953                         }
5954                         handleEapAuthFailure(mTargetNetworkId, errorCode);
5955                         if (errorCode == WifiNative.EAP_SIM_NOT_SUBSCRIBED) {
5956                             disableReason = WifiConfiguration.NetworkSelectionStatus
5957                                     .DISABLED_AUTHENTICATION_NO_SUBSCRIPTION;
5958                         }
5959                     }
5960                     mWifiConfigManager.updateNetworkSelectionStatus(
5961                             mTargetNetworkId, disableReason);
5962                     mWifiConfigManager.clearRecentFailureReason(mTargetNetworkId);
5963 
5964                     //If failure occurred while Metrics is tracking a ConnnectionEvent, end it.
5965                     int level2FailureReason;
5966                     switch (reasonCode) {
5967                         case WifiManager.ERROR_AUTH_FAILURE_NONE:
5968                             level2FailureReason =
5969                                     WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_NONE;
5970                             break;
5971                         case WifiManager.ERROR_AUTH_FAILURE_TIMEOUT:
5972                             level2FailureReason =
5973                                     WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_TIMEOUT;
5974                             break;
5975                         case WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD:
5976                             level2FailureReason =
5977                                     WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_WRONG_PSWD;
5978                             break;
5979                         case WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE:
5980                             level2FailureReason =
5981                                     WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE;
5982                             break;
5983                         default:
5984                             level2FailureReason =
5985                                     WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN;
5986                             break;
5987                     }
5988                     reportConnectionAttemptEnd(
5989                             WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE,
5990                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
5991                             level2FailureReason);
5992                     if (reasonCode != WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD && reasonCode
5993                             != WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE) {
5994                         mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
5995                                 getConnectingSsidInternal(),
5996                                 (mLastBssid == null) ? mTargetBssid : mLastBssid,
5997                                 WifiLastResortWatchdog.FAILURE_CODE_AUTHENTICATION,
5998                                 isConnected());
5999                     }
6000                     handleNetworkDisconnect(false,
6001                             WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED);
6002                     transitionTo(mDisconnectedState); // End of connection attempt.
6003                     break;
6004                 }
6005                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: {
6006                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
6007                     if (SupplicantState.isConnecting(stateChangeResult.state)) {
6008                         WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(
6009                                 stateChangeResult.networkId);
6010                         // Update Passpoint information before setNetworkDetailedState as
6011                         // WifiTracker monitors NETWORK_STATE_CHANGED_ACTION to update UI.
6012                         mWifiInfo.setFQDN(null);
6013                         mWifiInfo.setPasspointUniqueId(null);
6014                         mWifiInfo.setOsuAp(false);
6015                         mWifiInfo.setProviderFriendlyName(null);
6016                         if (config != null && (config.isPasspoint() || config.osu)) {
6017                             if (config.isPasspoint()) {
6018                                 mWifiInfo.setFQDN(config.FQDN);
6019                                 mWifiInfo.setPasspointUniqueId(config.getPasspointUniqueId());
6020                             } else {
6021                                 mWifiInfo.setOsuAp(true);
6022                             }
6023                             mWifiInfo.setProviderFriendlyName(config.providerFriendlyName);
6024                             mWifiInfo.setNetworkKey(
6025                                     config.getNetworkKeyFromSecurityType(
6026                                             mWifiInfo.getCurrentSecurityType()));
6027                         }
6028                         updateCurrentConnectionInfo();
6029                     }
6030                     sendNetworkChangeBroadcast(
6031                             WifiInfo.getDetailedStateOf(stateChangeResult.state));
6032                     // Let the parent state handle the rest of the state changed.
6033                     handleStatus = NOT_HANDLED;
6034                     break;
6035                 }
6036                 case WifiMonitor.SUP_REQUEST_IDENTITY: {
6037                     int netId = message.arg2;
6038                     boolean identitySent = false;
6039                     // For SIM & AKA/AKA' EAP method Only, get identity from ICC
6040                     if (mTargetWifiConfiguration != null
6041                             && mTargetWifiConfiguration.networkId == netId
6042                             && mTargetWifiConfiguration.enterpriseConfig != null
6043                             && mTargetWifiConfiguration.enterpriseConfig
6044                             .isAuthenticationSimBased()) {
6045                         // Pair<identity, encrypted identity>
6046                         Pair<String, String> identityPair = mWifiCarrierInfoManager
6047                                 .getSimIdentity(mTargetWifiConfiguration);
6048                         if (identityPair != null && identityPair.first != null) {
6049                             Log.i(getTag(), "SUP_REQUEST_IDENTITY: identityPair=["
6050                                     + ((identityPair.first.length() >= 7)
6051                                     ? identityPair.first.substring(0, 7 /* Prefix+PLMN ID */)
6052                                     + "****"
6053                                     : identityPair.first) + ", "
6054                                     + (!TextUtils.isEmpty(identityPair.second) ? identityPair.second
6055                                     : "<NONE>") + "]");
6056                             mWifiNative.simIdentityResponse(mInterfaceName, identityPair.first,
6057                                     identityPair.second);
6058                             identitySent = true;
6059                         } else {
6060                             Log.e(getTag(), "Unable to retrieve identity from Telephony");
6061                         }
6062                     }
6063 
6064                     if (!identitySent) {
6065                         // Supplicant lacks credentials to connect to that network, hence block list
6066                         String ssid = (String) message.obj;
6067                         if (mTargetWifiConfiguration != null && ssid != null
6068                                 && mTargetWifiConfiguration.SSID != null
6069                                 && mTargetWifiConfiguration.SSID.equals("\"" + ssid + "\"")) {
6070                             mWifiConfigManager.updateNetworkSelectionStatus(
6071                                     mTargetWifiConfiguration.networkId,
6072                                     WifiConfiguration.NetworkSelectionStatus
6073                                             .DISABLED_AUTHENTICATION_NO_CREDENTIALS);
6074                         }
6075                         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
6076                                 StaEvent.DISCONNECT_GENERIC);
6077                         mWifiNative.disconnect(mInterfaceName);
6078                     }
6079                     break;
6080                 }
6081                 case CMD_CONNECTING_WATCHDOG_TIMER: {
6082                     if (mConnectingWatchdogCount == message.arg1) {
6083                         if (mVerboseLoggingEnabled) log("Connecting watchdog! -> disconnect");
6084                         reportConnectionAttemptEnd(
6085                                 WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE,
6086                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6087                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
6088                         handleNetworkDisconnect(false,
6089                                 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__CONNECTING_WATCHDOG_TIMER);
6090                         transitionTo(mDisconnectedState);
6091                     }
6092                     break;
6093                 }
6094                 case WifiMonitor.NETWORK_CONNECTION_EVENT: {
6095                     NetworkConnectionEventInfo connectionInfo =
6096                             (NetworkConnectionEventInfo) message.obj;
6097                     String quotedOrHexConnectingSsid = getConnectingSsidInternal();
6098                     String quotedOrHexConnectedSsid = connectionInfo.wifiSsid.toString();
6099                     if (quotedOrHexConnectingSsid != null
6100                             && !quotedOrHexConnectingSsid.equals(quotedOrHexConnectedSsid)) {
6101                         // possibly a NETWORK_CONNECTION_EVENT for a successful roam on the previous
6102                         // network while connecting to a new network, ignore it.
6103                         Log.d(TAG, "Connecting to ssid=" + quotedOrHexConnectingSsid + ", but got "
6104                                 + "NETWORK_CONNECTION_EVENT for ssid=" + quotedOrHexConnectedSsid
6105                                 + ", ignoring");
6106                         break;
6107                     }
6108                     handleStatus = NOT_HANDLED;
6109                     break;
6110                 }
6111                 case WifiMonitor.TOFU_CERTIFICATE_EVENT: {
6112                     if (null == mTargetWifiConfiguration) break;
6113                     final int certificateDepth = message.arg2;
6114                     final CertificateEventInfo eventInfo = (CertificateEventInfo) message.obj;
6115                     if (!mInsecureEapNetworkHandler.addPendingCertificate(
6116                             mTargetWifiConfiguration.SSID, certificateDepth, eventInfo)) {
6117                         Log.d(TAG, "Cannot set pending cert.");
6118                     }
6119                     // Launch user approval upon receiving the server certificate and disconnect
6120                     if (certificateDepth == 0 && !mLeafCertSent && mInsecureEapNetworkHandler
6121                             .startUserApprovalIfNecessary(mIsUserSelected)) {
6122                         // In the TOFU flow, the user approval dialog is now displayed and the
6123                         // network remains disconnected and disabled until it is approved.
6124                         sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED);
6125                         mLeafCertSent = true;
6126                     }
6127                     break;
6128                 }
6129                 default: {
6130                     handleStatus = NOT_HANDLED;
6131                     break;
6132                 }
6133             }
6134             if (handleStatus == HANDLED) {
6135                 logStateAndMessage(message, this);
6136             }
6137             return handleStatus;
6138         }
6139     }
6140 
6141     class L2ConnectedState extends RunnerState {
L2ConnectedState(int threshold)6142         L2ConnectedState(int threshold) {
6143             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
6144         }
6145 
6146         @Override
enterImpl()6147         public void enterImpl() {
6148             mRssiPollToken++;
6149             if (mEnableRssiPolling) {
6150                 if (isPrimary()) {
6151                     mLinkProbeManager.resetOnNewConnection();
6152                 }
6153                 sendMessage(CMD_RSSI_POLL, mRssiPollToken, 0);
6154             }
6155             sendNetworkChangeBroadcast(DetailedState.CONNECTING);
6156 
6157             // If this network was explicitly selected by the user, evaluate whether to inform
6158             // ConnectivityService of that fact so the system can treat it appropriately.
6159             final WifiConfiguration config = getConnectedWifiConfigurationInternal();
6160 
6161             final NetworkAgentConfig naConfig = getNetworkAgentConfigInternal(config);
6162             final NetworkCapabilities nc = getCapabilities(
6163                     getConnectedWifiConfigurationInternal(), getConnectedBssidInternal());
6164             // This should never happen.
6165             if (mNetworkAgent != null) {
6166                 Log.wtf(getTag(), "mNetworkAgent is not null: " + mNetworkAgent);
6167                 mNetworkAgent.unregister();
6168             }
6169             mNetworkAgent = mWifiInjector.makeWifiNetworkAgent(nc, mLinkProperties, naConfig,
6170                     mNetworkFactory.getProvider(), new WifiNetworkAgentCallback());
6171             mWifiScoreReport.setNetworkAgent(mNetworkAgent);
6172             if (SdkLevel.isAtLeastT()) {
6173                 mQosPolicyRequestHandler.setNetworkAgent(mNetworkAgent);
6174             }
6175 
6176             // We must clear the config BSSID, as the wifi chipset may decide to roam
6177             // from this point on and having the BSSID specified in the network block would
6178             // cause the roam to faile and the device to disconnect
6179             clearTargetBssid("L2ConnectedState");
6180             mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
6181             mWifiScoreCard.noteNetworkAgentCreated(mWifiInfo,
6182                     mNetworkAgent.getNetwork().getNetId());
6183             mWifiBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid, mWifiInfo.getSSID());
6184             // too many places to record connection failure with too many failure reasons.
6185             // So only record success here.
6186             mWifiMetrics.noteFirstL2ConnectionAfterBoot(true);
6187             mCmiMonitor.onL2Connected(mClientModeManager);
6188             mIsLinkedNetworkRoaming = false;
6189         }
6190 
6191         @Override
exitImpl()6192         public void exitImpl() {
6193             // This is handled by receiving a NETWORK_DISCONNECTION_EVENT in ConnectableState
6194             // Bug: 15347363
6195             // For paranoia's sake, call handleNetworkDisconnect
6196             // only if BSSID is null or last networkId
6197             // is not invalid.
6198             if (mVerboseLoggingEnabled) {
6199                 StringBuilder sb = new StringBuilder();
6200                 sb.append("leaving L2ConnectedState state nid=" + Integer.toString(mLastNetworkId));
6201                 if (mLastBssid != null) {
6202                     sb.append(" ").append(mLastBssid);
6203                 }
6204             }
6205             mWifiMetrics.setWifiState(mInterfaceName, WifiMetricsProto.WifiLog.WIFI_DISCONNECTED);
6206             mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.DISCONNECTED);
6207             // Inform WifiLockManager
6208             mWifiLockManager.updateWifiClientConnected(mClientModeManager, false);
6209             mLastConnectionCapabilities = null;
6210         }
6211 
6212         @Override
getMessageLogRec(int what)6213         String getMessageLogRec(int what) {
6214             return ClientModeImpl.class.getSimpleName() + "."
6215                     + L2ConnectedState.class.getSimpleName() + "." + getWhatToString(what);
6216         }
6217 
6218         @Override
processMessageImpl(Message message)6219         public boolean processMessageImpl(Message message) {
6220             boolean handleStatus = HANDLED;
6221 
6222             switch (message.what) {
6223                 case CMD_PRE_DHCP_ACTION: {
6224                     handlePreDhcpSetup();
6225                     break;
6226                 }
6227                 case CMD_PRE_DHCP_ACTION_COMPLETE: {
6228                     if (mIpClient != null) {
6229                         mIpClient.completedPreDhcpAction();
6230                     }
6231                     break;
6232                 }
6233                 case CMD_POST_DHCP_ACTION: {
6234                     handlePostDhcpSetup();
6235                     // We advance to mL3ConnectedState because IpClient will also send a
6236                     // CMD_IPV4_PROVISIONING_SUCCESS message, which calls handleIPv4Success(),
6237                     // which calls updateLinkProperties, which then sends
6238                     // CMD_IP_CONFIGURATION_SUCCESSFUL.
6239                     break;
6240                 }
6241                 case CMD_IPV4_PROVISIONING_SUCCESS: {
6242                     handleIPv4Success((DhcpResultsParcelable) message.obj);
6243                     sendNetworkChangeBroadcastWithCurrentState();
6244                     break;
6245                 }
6246                 case CMD_IPV4_PROVISIONING_FAILURE: {
6247                     handleIPv4Failure();
6248                     mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
6249                             getConnectingSsidInternal(),
6250                             (mLastBssid == null) ? mTargetBssid : mLastBssid,
6251                             WifiLastResortWatchdog.FAILURE_CODE_DHCP,
6252                             isConnected());
6253                     break;
6254                 }
6255                 case CMD_IP_CONFIGURATION_SUCCESSFUL: {
6256                     if (getConnectedWifiConfigurationInternal() == null || mNetworkAgent == null) {
6257                         // The current config may have been removed while we were connecting,
6258                         // trigger a disconnect to clear up state.
6259                         reportConnectionAttemptEnd(
6260                                 WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
6261                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6262                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
6263                         mWifiNative.disconnect(mInterfaceName);
6264                     } else {
6265                         handleSuccessfulIpConfiguration();
6266                         sendConnectedState();
6267                         transitionTo(mL3ConnectedState);
6268                     }
6269                     break;
6270                 }
6271                 case CMD_IP_CONFIGURATION_LOST: {
6272                     // Get Link layer stats so that we get fresh tx packet counters.
6273                     getWifiLinkLayerStats();
6274                     handleIpConfigurationLost();
6275                     reportConnectionAttemptEnd(
6276                             WifiMetrics.ConnectionEvent.FAILURE_DHCP,
6277                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
6278                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
6279                     mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
6280                             getConnectingSsidInternal(),
6281                             (mLastBssid == null) ? mTargetBssid : mLastBssid,
6282                             WifiLastResortWatchdog.FAILURE_CODE_DHCP,
6283                             isConnected());
6284                     handleNetworkDisconnect(false,
6285                             WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__UNSPECIFIED);
6286                     transitionTo(mDisconnectedState); // End of connection attempt.
6287                     break;
6288                 }
6289                 case CMD_IP_REACHABILITY_LOST: {
6290                     if (mVerboseLoggingEnabled && message.obj != null) log((String) message.obj);
6291                     mWifiDiagnostics.triggerBugReportDataCapture(
6292                             WifiDiagnostics.REPORT_REASON_REACHABILITY_LOST);
6293                     mWifiMetrics.logWifiIsUnusableEvent(mInterfaceName,
6294                             WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST);
6295                     mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
6296                             WifiUsabilityStats.LABEL_BAD,
6297                             WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST, -1);
6298                     if (mWifiGlobals.getIpReachabilityDisconnectEnabled()) {
6299                         handleIpReachabilityLost();
6300                     } else {
6301                         logd("CMD_IP_REACHABILITY_LOST but disconnect disabled -- ignore");
6302                     }
6303                     break;
6304                 }
6305                 case CMD_IP_REACHABILITY_FAILURE: {
6306                     mWifiDiagnostics.triggerBugReportDataCapture(
6307                             WifiDiagnostics.REPORT_REASON_REACHABILITY_FAILURE);
6308                     handleIpReachabilityFailure((ReachabilityLossInfoParcelable) message.obj);
6309                     break;
6310                 }
6311                 case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: {
6312                     if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
6313                         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
6314                                 StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST);
6315                         mWifiNative.disconnect(mInterfaceName);
6316                     }
6317                     break;
6318                 }
6319                 case WifiMonitor.NETWORK_CONNECTION_EVENT: {
6320                     NetworkConnectionEventInfo connectionInfo =
6321                             (NetworkConnectionEventInfo) message.obj;
6322                     mLastNetworkId = connectionInfo.networkId;
6323                     handleNetworkConnectionEventInfo(
6324                             getConnectedWifiConfigurationInternal(), connectionInfo);
6325                     mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
6326                     updateLayer2Information();
6327                     updateCurrentConnectionInfo();
6328                     if (!Objects.equals(mLastBssid, connectionInfo.bssid)) {
6329                         mLastBssid = connectionInfo.bssid;
6330                         sendNetworkChangeBroadcastWithCurrentState();
6331                     }
6332                     if (mIsLinkedNetworkRoaming) {
6333                         mIsLinkedNetworkRoaming = false;
6334                         mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
6335                         mTargetWifiConfiguration = null;
6336                         clearTargetBssid("AllowlistRoamingCompleted");
6337                         sendNetworkChangeBroadcast(DetailedState.CONNECTED);
6338                     }
6339                     checkIfNeedDisconnectSecondaryWifi();
6340                     if (mApplicationQosPolicyRequestHandler.isFeatureEnabled()) {
6341                         mApplicationQosPolicyRequestHandler.queueAllPoliciesOnIface(mInterfaceName);
6342                     }
6343                     break;
6344                 }
6345                 case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT: {
6346                     int newFrequency = message.arg1;
6347                     if (newFrequency > 0) {
6348                         if (mWifiInfo.getFrequency() != newFrequency) {
6349                             mWifiInfo.setFrequency(newFrequency);
6350                             updateCurrentConnectionInfo();
6351                             updateCapabilities();
6352                         }
6353                     }
6354                     break;
6355                 }
6356                 case CMD_ONESHOT_RSSI_POLL: {
6357                     if (!mEnableRssiPolling) {
6358                         updateLinkLayerStatsRssiDataStallScoreReport();
6359                     }
6360                     break;
6361                 }
6362                 case CMD_RSSI_POLL: {
6363                     // TODO(b/179792830): getBSSID() shouldn't be null in L2ConnectedState,
6364                     //  add debug logs in the meantime. Remove once root cause identified.
6365                     if (mWifiInfo.getBSSID() == null) {
6366                         Log.wtf(getTag(), "WifiInfo.getBSSID() is null in L2ConnectedState!");
6367                         break;
6368                     }
6369                     if (message.arg1 == mRssiPollToken) {
6370                         updateLinkLayerStatsRssiDataStallScoreReport();
6371                         mWifiScoreCard.noteSignalPoll(mWifiInfo);
6372                         if (isPrimary()) {
6373                             mLinkProbeManager.updateConnectionStats(mWifiInfo, mInterfaceName);
6374                         }
6375                         // Update the polling interval as needed before sending the delayed message
6376                         // so that the next polling can happen after the updated interval
6377                         if (isPrimary()) {
6378                             int curState = mWifiInjector.getActiveModeWarden()
6379                                     .getDeviceMobilityState();
6380                             mRssiMonitor.updatePollRssiInterval(curState);
6381                         }
6382                         sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
6383                                 mWifiGlobals.getPollRssiIntervalMillis());
6384                         if (isPrimary()) {
6385                             mWifiTrafficPoller.notifyOnDataActivity(
6386                                     mWifiInfo.txSuccess, mWifiInfo.rxSuccess);
6387                         }
6388                     } else {
6389                         // Polling has completed
6390                     }
6391                     break;
6392                 }
6393                 case CMD_ENABLE_RSSI_POLL: {
6394                     cleanWifiScore();
6395                     mEnableRssiPolling = (message.arg1 == 1);
6396                     mRssiPollToken++;
6397                     if (mEnableRssiPolling) {
6398                         // First poll
6399                         mLastSignalLevel = -1;
6400                         if (isPrimary()) {
6401                             mLinkProbeManager.resetOnScreenTurnedOn();
6402                         }
6403                         long txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes();
6404                         long rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes();
6405                         updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes, rxBytes);
6406                         sendMessageDelayed(obtainMessage(CMD_RSSI_POLL, mRssiPollToken, 0),
6407                                 mWifiGlobals.getPollRssiIntervalMillis());
6408                     }
6409                     else {
6410                         mRssiMonitor.setShortPollRssiInterval();
6411                     }
6412                     break;
6413                 }
6414                 case WifiMonitor.ASSOCIATED_BSSID_EVENT: {
6415                     if ((String) message.obj == null) {
6416                         logw("Associated command w/o BSSID");
6417                         break;
6418                     }
6419                     mLastBssid = (String) message.obj;
6420                     if (checkAndHandleLinkedNetworkRoaming(mLastBssid)) {
6421                         Log.i(TAG, "Driver initiated allowlist SSID roaming");
6422                         break;
6423                     }
6424                     if (mLastBssid != null && (mWifiInfo.getBSSID() == null
6425                             || !mLastBssid.equals(mWifiInfo.getBSSID()))) {
6426                         mWifiInfo.setBSSID(mLastBssid);
6427                         WifiConfiguration config = getConnectedWifiConfigurationInternal();
6428                         if (config != null) {
6429                             ScanDetailCache scanDetailCache = mWifiConfigManager
6430                                     .getScanDetailCacheForNetwork(config.networkId);
6431                             if (scanDetailCache != null) {
6432                                 ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
6433                                 if (scanResult != null) {
6434                                     mWifiInfo.setFrequency(scanResult.frequency);
6435                                     boolean isHidden = true;
6436                                     for (byte b : scanResult.getWifiSsid().getBytes()) {
6437                                         if (b != 0) {
6438                                             isHidden = false;
6439                                             break;
6440                                         }
6441                                     }
6442                                     mWifiInfo.setHiddenSSID(isHidden);
6443                                 }
6444                             }
6445                         }
6446                         sendNetworkChangeBroadcastWithCurrentState();
6447                         mMultiInternetManager.notifyBssidAssociatedEvent(mClientModeManager);
6448                         updateCurrentConnectionInfo();
6449                     }
6450                     break;
6451                 }
6452                 case CMD_RECONNECT: {
6453                     log(" Ignore CMD_RECONNECT request because wifi is already connected");
6454                     break;
6455                 }
6456                 case CMD_RESET_SIM_NETWORKS: {
6457                     if (message.arg1 != RESET_SIM_REASON_SIM_INSERTED
6458                             && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
6459                         WifiConfiguration config =
6460                                 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
6461                         if (config != null
6462                             && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED
6463                                 && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)
6464                                 || (config.enterpriseConfig != null
6465                                 && config.enterpriseConfig.isAuthenticationSimBased()
6466                                 && !mWifiCarrierInfoManager.isSimReady(mLastSubId)))) {
6467                             mWifiMetrics.logStaEvent(mInterfaceName,
6468                                     StaEvent.TYPE_FRAMEWORK_DISCONNECT,
6469                                     StaEvent.DISCONNECT_RESET_SIM_NETWORKS);
6470                             // remove local PMKSA cache in framework
6471                             mWifiNative.removeNetworkCachedData(mLastNetworkId);
6472                             // remove network so that supplicant's PMKSA cache is cleared
6473                             mWifiNative.removeAllNetworks(mInterfaceName);
6474                             if (isPrimary() && !mWifiCarrierInfoManager.isSimReady(mLastSubId)) {
6475                                 mSimRequiredNotifier.showSimRequiredNotification(
6476                                         config, mLastSimBasedConnectionCarrierName);
6477                             }
6478                         }
6479                     }
6480                     break;
6481                 }
6482                 case CMD_START_IP_PACKET_OFFLOAD: {
6483                     int slot = message.arg1;
6484                     int intervalSeconds = message.arg2;
6485                     KeepalivePacketData pkt = (KeepalivePacketData) message.obj;
6486                     int result = startWifiIPPacketOffload(slot, pkt, intervalSeconds);
6487                     if (mNetworkAgent != null) {
6488                         mNetworkAgent.sendSocketKeepaliveEvent(slot, result);
6489                     }
6490                     break;
6491                 }
6492                 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: {
6493                     if (mIpClient != null) {
6494                         final int slot = message.arg1;
6495                         if (message.obj instanceof NattKeepalivePacketData) {
6496                             final NattKeepalivePacketData pkt =
6497                                     (NattKeepalivePacketData) message.obj;
6498                             mIpClient.addKeepalivePacketFilter(slot, pkt);
6499                         } else if (SdkLevel.isAtLeastS()) {
6500                             if (message.obj instanceof TcpKeepalivePacketData) {
6501                                 final TcpKeepalivePacketData pkt =
6502                                         (TcpKeepalivePacketData) message.obj;
6503                                 mIpClient.addKeepalivePacketFilter(slot, pkt);
6504                             }
6505                             // Otherwise unsupported keepalive data class: skip
6506                         } else {
6507                             // Before S, non-NattKeepalivePacketData KeepalivePacketData would be
6508                             // the not-yet-SystemApi android.net.TcpKeepalivePacketData.
6509                             // Attempt to parse TcpKeepalivePacketDataParcelable from the
6510                             // KeepalivePacketData superclass.
6511                             final TcpKeepalivePacketDataParcelable p =
6512                                     parseTcpKeepalivePacketData((KeepalivePacketData) message.obj);
6513                             if (p != null) {
6514                                 mIpClient.addKeepalivePacketFilter(slot, p);
6515                             }
6516                         }
6517                     }
6518                     break;
6519                 }
6520                 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER_FROM_APF: {
6521                     if (mIpClient != null) {
6522                         mIpClient.removeKeepalivePacketFilter(message.arg1);
6523                     }
6524                     break;
6525                 }
6526                 case WifiMonitor.MLO_LINKS_INFO_CHANGED:
6527                     WifiMonitor.MloLinkInfoChangeReason reason =
6528                             (WifiMonitor.MloLinkInfoChangeReason) message.obj;
6529                     WifiNative.ConnectionMloLinksInfo newInfo =
6530                             mWifiNative.getConnectionMloLinksInfo(mInterfaceName);
6531                     if (reason == WifiMonitor.MloLinkInfoChangeReason.TID_TO_LINK_MAP) {
6532                         // Traffic stream mapping changed. Update link states.
6533                         updateMloLinkStates(newInfo);
6534                         // There is a change in link capabilities. Will trigger android.net
6535                         // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged().
6536                         updateCapabilities();
6537                     } else if (reason
6538                             == WifiMonitor.MloLinkInfoChangeReason.MULTI_LINK_RECONFIG_AP_REMOVAL) {
6539                         // Link is removed. Set removed link state to MLO_LINK_STATE_UNASSOCIATED.
6540                         // Also update block list mapping, as there is a change in affiliated
6541                         // BSSIDs.
6542                         clearMloLinkStates();
6543                         updateMloLinkStates(newInfo);
6544                         updateBlockListAffiliatedBssids();
6545                         // There is a change in link capabilities. Will trigger android.net
6546                         // .ConnectivityManager.NetworkCallback.onCapabilitiesChanged().
6547                         updateCapabilities();
6548                     } else {
6549                         logw("MLO_LINKS_INFO_CHANGED with UNKNOWN reason");
6550                     }
6551                     break;
6552                 default: {
6553                     handleStatus = NOT_HANDLED;
6554                     break;
6555                 }
6556             }
6557 
6558             if (handleStatus == HANDLED) {
6559                 logStateAndMessage(message, this);
6560             }
6561 
6562             return handleStatus;
6563         }
6564 
6565         /**
6566          * Fetches link stats, updates Wifi Data Stall, Score Card and Score Report.
6567          */
updateLinkLayerStatsRssiDataStallScoreReport()6568         private WifiLinkLayerStats updateLinkLayerStatsRssiDataStallScoreReport() {
6569             // Get Info and continue polling
6570             long txBytes;
6571             long rxBytes;
6572             if (SdkLevel.isAtLeastS()) {
6573                 txBytes = mFacade.getTxBytes(mInterfaceName);
6574                 rxBytes = mFacade.getRxBytes(mInterfaceName);
6575             } else {
6576                 txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes();
6577                 rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes();
6578             }
6579             WifiLinkLayerStats stats = updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes,
6580                     rxBytes);
6581             mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats);
6582             // checkDataStallAndThroughputSufficiency() should be called before
6583             // mWifiScoreReport.calculateAndReportScore() which needs the latest throughput
6584             int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency(
6585                     mInterfaceName, mLastConnectionCapabilities, mLastLinkLayerStats, stats,
6586                     mWifiInfo, txBytes, rxBytes);
6587             if (mDataStallTriggerTimeMs == -1
6588                     && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) {
6589                 mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis();
6590                 mLastStatusDataStall = statusDataStall;
6591             }
6592             if (mDataStallTriggerTimeMs != -1) {
6593                 long elapsedTime =  mClock.getElapsedSinceBootMillis()
6594                         - mDataStallTriggerTimeMs;
6595                 if (elapsedTime >= DURATION_TO_WAIT_ADD_STATS_AFTER_DATA_STALL_MS) {
6596                     mDataStallTriggerTimeMs = -1;
6597                     mWifiMetrics.addToWifiUsabilityStatsList(mInterfaceName,
6598                             WifiUsabilityStats.LABEL_BAD,
6599                             convertToUsabilityStatsTriggerType(mLastStatusDataStall),
6600                             -1);
6601                     mLastStatusDataStall = WifiIsUnusableEvent.TYPE_UNKNOWN;
6602                 }
6603             }
6604             // Send the update score to network agent.
6605             mWifiScoreReport.calculateAndReportScore();
6606 
6607             if (mWifiScoreReport.shouldCheckIpLayer()) {
6608                 if (mIpClient != null) {
6609                     mIpClient.confirmConfiguration();
6610                 }
6611                 mWifiScoreReport.noteIpCheck();
6612             }
6613 
6614             mLastLinkLayerStats = stats;
6615             return stats;
6616         }
6617     }
6618 
6619     /**
6620      * Fetches link stats and updates Wifi Score Report.
6621      */
updateLinkLayerStatsRssiAndScoreReport()6622     private void updateLinkLayerStatsRssiAndScoreReport() {
6623         sendMessage(CMD_ONESHOT_RSSI_POLL);
6624     }
6625 
convertToUsabilityStatsTriggerType(int unusableEventTriggerType)6626     private int convertToUsabilityStatsTriggerType(int unusableEventTriggerType) {
6627         int triggerType;
6628         switch (unusableEventTriggerType) {
6629             case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX:
6630                 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX;
6631                 break;
6632             case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX:
6633                 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_TX_WITHOUT_RX;
6634                 break;
6635             case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH:
6636                 triggerType = WifiUsabilityStats.TYPE_DATA_STALL_BOTH;
6637                 break;
6638             case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT:
6639                 triggerType = WifiUsabilityStats.TYPE_FIRMWARE_ALERT;
6640                 break;
6641             case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST:
6642                 triggerType = WifiUsabilityStats.TYPE_IP_REACHABILITY_LOST;
6643                 break;
6644             default:
6645                 triggerType = WifiUsabilityStats.TYPE_UNKNOWN;
6646                 Log.e(getTag(), "Unknown WifiIsUnusableEvent: " + unusableEventTriggerType);
6647         }
6648         return triggerType;
6649     }
6650 
6651     // Before transition to L3ProvisioningState, always shut down the current IpClient
6652     // instance and recreate a new IpClient and IpClientCallbacks instance, defer received
6653     // messages in this state except CMD_IPCLIENT_CREATED, recreation of a new IpClient
6654     // guarantees the out-of-date callbacks will be ignored, otherwise, it's not easy to
6655     // differentiate callbacks which comes from new IpClient or legacy IpClient. So far
6656     // only transit to this state iff IP reachability gets lost post roam.
6657     class WaitBeforeL3ProvisioningState extends RunnerState {
WaitBeforeL3ProvisioningState(int threshold)6658         WaitBeforeL3ProvisioningState(int threshold) {
6659             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
6660         }
6661 
6662         @Override
enterImpl()6663         public void enterImpl() {
6664             // Recreate a new IpClient instance.
6665             maybeShutdownIpclient();
6666             makeIpClient();
6667 
6668             // Given that {@link IpClientCallbacks#awaitCreation} is invoked when making a
6669             // IpClient instance, which waits for {@link IPCLIENT_STARTUP_TIMEOUT_MS}.
6670             // If await IpClient recreation times out, then send timeout message to proceed
6671             // to Disconnected state, otherwise, we will never exit this state.
6672             sendMessage(CMD_IPCLIENT_STARTUP_TIMEOUT);
6673         }
6674 
6675         @Override
exitImpl()6676         public void exitImpl() {
6677             removeMessages(CMD_IPCLIENT_STARTUP_TIMEOUT);
6678         }
6679 
6680         @Override
processMessageImpl(Message message)6681         public boolean processMessageImpl(Message message) {
6682             switch(message.what) {
6683                 case CMD_IPCLIENT_CREATED: {
6684                     mIpClient = (IpClientManager) message.obj;
6685                     transitionTo(mL3ProvisioningState);
6686                     break;
6687                 }
6688 
6689                 case CMD_IPCLIENT_STARTUP_TIMEOUT: {
6690                     Log.e(getTag(), "Fail to create an IpClient instance within "
6691                             + IPCLIENT_STARTUP_TIMEOUT_MS + "ms");
6692                     handleNetworkDisconnect(false,
6693                             WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__TIMEOUT);
6694                     transitionTo(mDisconnectedState);
6695                     break;
6696                 }
6697 
6698                 default:
6699                     // Do not process any other messages except CMD_IPCLIENT_CREATED and
6700                     // CMD_IPCLIENT_STARTUP_TIMEOUT. This means that this state can be very
6701                     // simple because it does not need to worry about messasge ordering.
6702                     // Re-creating IpClient should only take a few milliseconds, but in the
6703                     // worst case, this will result in the state machine not processing any
6704                     // messages for IPCLIENT_STARTUP_TIMEOUT_MS.
6705                     deferMessage(message);
6706             }
6707 
6708             logStateAndMessage(message, this);
6709             return HANDLED;
6710         }
6711 
6712         @Override
getMessageLogRec(int what)6713         String getMessageLogRec(int what) {
6714             return ClientModeImpl.class.getSimpleName() + "."
6715                     + WaitBeforeL3ProvisioningState.class.getSimpleName() + "."
6716                     + getWhatToString(what);
6717         }
6718     }
6719 
6720     class L3ProvisioningState extends RunnerState {
L3ProvisioningState(int threshold)6721         L3ProvisioningState(int threshold) {
6722             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
6723         }
6724 
6725         @Override
enterImpl()6726         public void enterImpl() {
6727             startL3Provisioning();
6728         }
6729 
6730         @Override
exitImpl()6731         public void exitImpl() {
6732         }
6733 
6734         @Override
getMessageLogRec(int what)6735         String getMessageLogRec(int what) {
6736             return ClientModeImpl.class.getSimpleName() + "."
6737                     + L3ProvisioningState.class.getSimpleName() + "." + getWhatToString(what);
6738         }
6739 
6740         @Override
processMessageImpl(Message message)6741         public boolean processMessageImpl(Message message) {
6742             boolean handleStatus = HANDLED;
6743 
6744             switch(message.what) {
6745                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: {
6746                     DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj;
6747                     mWifiLastResortWatchdog.noteConnectionFailureAndTriggerIfNeeded(
6748                             getConnectingSsidInternal(),
6749                             !isValidBssid(eventInfo.bssid)
6750                             ? mTargetBssid : eventInfo.bssid,
6751                             WifiLastResortWatchdog.FAILURE_CODE_DHCP,
6752                             isConnected());
6753                     handleStatus = NOT_HANDLED;
6754                     break;
6755                 }
6756                 default: {
6757                     handleStatus = NOT_HANDLED;
6758                     break;
6759                 }
6760             }
6761 
6762             if (handleStatus == HANDLED) {
6763                 logStateAndMessage(message, this);
6764             }
6765             return handleStatus;
6766         }
6767 
startL3Provisioning()6768         private void startL3Provisioning() {
6769             WifiConfiguration currentConfig = getConnectedWifiConfigurationInternal();
6770             if (mIpClientWithPreConnection && mIpClient != null) {
6771                 mIpClient.notifyPreconnectionComplete(mSentHLPs);
6772                 mIpClientWithPreConnection = false;
6773                 mSentHLPs = false;
6774             } else {
6775                 startIpClient(currentConfig, false);
6776             }
6777             // Get Link layer stats so as we get fresh tx packet counters
6778             getWifiLinkLayerStats();
6779         }
6780     }
6781 
6782     /**
6783      * Helper function to check if a network has been recently selected by the user.
6784      * (i.e less than {@link #LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS) before).
6785      */
6786     @VisibleForTesting
isRecentlySelectedByTheUser(@onNull WifiConfiguration currentConfig)6787     public boolean isRecentlySelectedByTheUser(@NonNull WifiConfiguration currentConfig) {
6788         long currentTimeMillis = mClock.getElapsedSinceBootMillis();
6789         return mWifiConfigManager.getLastSelectedNetwork() == currentConfig.networkId
6790                 && currentTimeMillis - mWifiConfigManager.getLastSelectedTimeStamp()
6791                 < LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS;
6792     }
6793 
sendConnectedState()6794     private void sendConnectedState() {
6795         mNetworkAgent.markConnected();
6796         sendNetworkChangeBroadcast(DetailedState.CONNECTED);
6797     }
6798 
6799     class RoamingState extends RunnerState {
6800         boolean mAssociated;
6801 
RoamingState(int threshold)6802         RoamingState(int threshold) {
6803             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
6804         }
6805 
6806         @Override
enterImpl()6807         public void enterImpl() {
6808             if (mVerboseLoggingEnabled) {
6809                 log("RoamingState Enter mScreenOn=" + mScreenOn);
6810             }
6811 
6812             // Make sure we disconnect if roaming fails
6813             mRoamWatchdogCount++;
6814             logd("Start Roam Watchdog " + mRoamWatchdogCount);
6815             sendMessageDelayed(obtainMessage(CMD_ROAM_WATCHDOG_TIMER,
6816                     mRoamWatchdogCount, 0), ROAM_GUARD_TIMER_MSEC);
6817             mAssociated = false;
6818         }
6819 
6820         @Override
exitImpl()6821         public void exitImpl() {
6822         }
6823 
6824         @Override
getMessageLogRec(int what)6825         String getMessageLogRec(int what) {
6826             return ClientModeImpl.class.getSimpleName() + "." + RoamingState.class.getSimpleName()
6827                     + "." + getWhatToString(what);
6828         }
6829 
6830         @Override
processMessageImpl(Message message)6831         public boolean processMessageImpl(Message message) {
6832             boolean handleStatus = HANDLED;
6833 
6834             switch (message.what) {
6835                 case CMD_IP_CONFIGURATION_LOST: {
6836                     WifiConfiguration config = getConnectedWifiConfigurationInternal();
6837                     if (config != null) {
6838                         mWifiDiagnostics.triggerBugReportDataCapture(
6839                                 WifiDiagnostics.REPORT_REASON_AUTOROAM_FAILURE);
6840                     }
6841                     handleStatus = NOT_HANDLED;
6842                     break;
6843                 }
6844                 case CMD_UNWANTED_NETWORK: {
6845                     if (mVerboseLoggingEnabled) {
6846                         log("Roaming and CS doesn't want the network -> ignore");
6847                     }
6848                     break;
6849                 }
6850                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT: {
6851                     /**
6852                      * If we get a SUPPLICANT_STATE_CHANGE_EVENT indicating a DISCONNECT
6853                      * before NETWORK_DISCONNECTION_EVENT
6854                      * And there is an associated BSSID corresponding to our target BSSID, then
6855                      * we have missed the network disconnection, transition to mDisconnectedState
6856                      * and handle the rest of the events there.
6857                      */
6858                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
6859                     SupplicantState state = handleSupplicantStateChange(stateChangeResult);
6860                     if (state == SupplicantState.DISCONNECTED
6861                             || state == SupplicantState.INACTIVE
6862                             || state == SupplicantState.INTERFACE_DISABLED) {
6863                         if (mVerboseLoggingEnabled) {
6864                             log("RoamingState: Supplicant State change " + stateChangeResult);
6865                         }
6866                         handleNetworkDisconnect(false,
6867                                 WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED);
6868                         transitionTo(mDisconnectedState);
6869                     }
6870                     if (stateChangeResult.state == SupplicantState.ASSOCIATED) {
6871                         // We completed the layer2 roaming part
6872                         mAssociated = true;
6873                         mTargetBssid = stateChangeResult.bssid;
6874                     }
6875                     break;
6876                 }
6877                 case CMD_ROAM_WATCHDOG_TIMER: {
6878                     if (mRoamWatchdogCount == message.arg1) {
6879                         if (mVerboseLoggingEnabled) log("roaming watchdog! -> disconnect");
6880                         mWifiMetrics.endConnectionEvent(
6881                                 mInterfaceName,
6882                                 WifiMetrics.ConnectionEvent.FAILURE_ROAM_TIMEOUT,
6883                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6884                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN,
6885                                 mWifiInfo.getFrequency());
6886                         mRoamFailCount++;
6887                         handleNetworkDisconnect(false,
6888                                 WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__ROAM_WATCHDOG_TIMER);
6889                         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
6890                                 StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER);
6891                         mWifiNative.disconnect(mInterfaceName);
6892                         transitionTo(mDisconnectedState);
6893                     }
6894                     break;
6895                 }
6896                 case WifiMonitor.NETWORK_CONNECTION_EVENT: {
6897                     if (mAssociated) {
6898                         if (mVerboseLoggingEnabled) {
6899                             log("roaming and Network connection established");
6900                         }
6901                         NetworkConnectionEventInfo connectionInfo =
6902                                 (NetworkConnectionEventInfo) message.obj;
6903                         mLastNetworkId = connectionInfo.networkId;
6904                         mLastBssid = connectionInfo.bssid;
6905                         handleNetworkConnectionEventInfo(
6906                                 getConnectedWifiConfigurationInternal(), connectionInfo);
6907                         updateLayer2Information();
6908                         sendNetworkChangeBroadcastWithCurrentState();
6909                         updateCurrentConnectionInfo();
6910                         // Successful framework roam! (probably)
6911                         mWifiBlocklistMonitor.handleBssidConnectionSuccess(mLastBssid,
6912                                 mWifiInfo.getSSID());
6913                         reportConnectionAttemptEnd(
6914                                 WifiMetrics.ConnectionEvent.FAILURE_NONE,
6915                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
6916                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
6917 
6918                         // We must clear the config BSSID, as the wifi chipset may decide to roam
6919                         // from this point on and having the BSSID specified by QNS would cause
6920                         // the roam to fail and the device to disconnect.
6921                         // When transition from RoamingState to DisconnectedState, the config BSSID
6922                         // is cleared by handleNetworkDisconnect().
6923                         clearTargetBssid("RoamingCompleted");
6924 
6925                         // We used to transition to L3ProvisioningState in an
6926                         // attempt to do DHCPv4 RENEWs on framework roams.
6927                         // DHCP can take too long to time out, and we now rely
6928                         // upon IpClient's use of IpReachabilityMonitor to
6929                         // confirm our current network configuration.
6930                         //
6931                         // mIpClient.confirmConfiguration() is called within
6932                         // the handling of SupplicantState.COMPLETED.
6933                         transitionTo(mL3ConnectedState);
6934                     } else {
6935                         mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_DISCARD;
6936                     }
6937                     break;
6938                 }
6939                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: {
6940                     // Throw away but only if it corresponds to the network we're roaming to
6941                     DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj;
6942                     if (true) {
6943                         String target = "";
6944                         if (mTargetBssid != null) target = mTargetBssid;
6945                         log("NETWORK_DISCONNECTION_EVENT in roaming state"
6946                                 + " BSSID=" + eventInfo.bssid
6947                                 + " target=" + target);
6948                     }
6949                     clearNetworkCachedDataIfNeeded(
6950                             getConnectingWifiConfigurationInternal(), eventInfo.reasonCode);
6951                     if (eventInfo.bssid.equals(mTargetBssid)) {
6952                         handleNetworkDisconnect(false, eventInfo.reasonCode);
6953                         transitionTo(mDisconnectedState);
6954                     }
6955                     break;
6956                 }
6957                 default: {
6958                     handleStatus = NOT_HANDLED;
6959                     break;
6960                 }
6961             }
6962 
6963             if (handleStatus == HANDLED) {
6964                 logStateAndMessage(message, this);
6965             }
6966             return handleStatus;
6967         }
6968 
6969         @Override
exit()6970         public void exit() {
6971             logd("ClientModeImpl: Leaving Roaming state");
6972         }
6973     }
6974 
6975     class L3ConnectedState extends RunnerState {
L3ConnectedState(int threshold)6976         L3ConnectedState(int threshold) {
6977             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
6978         }
6979 
6980         @Override
enterImpl()6981         public void enterImpl() {
6982             if (mVerboseLoggingEnabled) {
6983                 log("Enter ConnectedState  mScreenOn=" + mScreenOn);
6984             }
6985 
6986             reportConnectionAttemptEnd(
6987                     WifiMetrics.ConnectionEvent.FAILURE_NONE,
6988                     WifiMetricsProto.ConnectionEvent.HLF_NONE,
6989                     WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
6990             mWifiConnectivityManager.handleConnectionStateChanged(
6991                     mClientModeManager,
6992                     WifiConnectivityManager.WIFI_STATE_CONNECTED);
6993             registerConnected();
6994             mTargetWifiConfiguration = null;
6995             mWifiScoreReport.reset();
6996             mLastSignalLevel = -1;
6997 
6998             // Not roaming anymore
6999             mIsAutoRoaming = false;
7000 
7001             mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
7002             mWifiLastResortWatchdog.connectedStateTransition(true);
7003             mWifiStateTracker.updateState(mInterfaceName, WifiStateTracker.CONNECTED);
7004             // Inform WifiLockManager
7005             mWifiLockManager.updateWifiClientConnected(mClientModeManager, true);
7006             WifiConfiguration config = getConnectedWifiConfigurationInternal();
7007             mWifiScoreReport.startConnectedNetworkScorer(
7008                     mNetworkAgent.getNetwork().getNetId(), isRecentlySelectedByTheUser(config));
7009             updateLinkLayerStatsRssiAndScoreReport();
7010             mWifiScoreCard.noteIpConfiguration(mWifiInfo);
7011             // too many places to record L3 failure with too many failure reasons.
7012             // So only record success here.
7013             mWifiMetrics.noteFirstL3ConnectionAfterBoot(true);
7014             updateCurrentConnectionInfo();
7015         }
7016 
7017         @Override
getMessageLogRec(int what)7018         String getMessageLogRec(int what) {
7019             return ClientModeImpl.class.getSimpleName() + "."
7020                     + L3ConnectedState.class.getSimpleName() + "." + getWhatToString(what);
7021         }
7022 
7023         @Override
processMessageImpl(Message message)7024         public boolean processMessageImpl(Message message) {
7025             boolean handleStatus = HANDLED;
7026 
7027             switch (message.what) {
7028                 case CMD_UNWANTED_NETWORK: {
7029                     if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) {
7030                         mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT,
7031                                 StaEvent.DISCONNECT_UNWANTED);
7032                         if (mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT
7033                                 && mClientModeManager.getPreviousRole() == ROLE_CLIENT_PRIMARY) {
7034                             mWifiMetrics.incrementMakeBeforeBreakLingerCompletedCount(
7035                                     mClock.getElapsedSinceBootMillis()
7036                                             - mClientModeManager.getLastRoleChangeSinceBootMs());
7037                         }
7038                         WifiConfiguration config = getConnectedWifiConfigurationInternal();
7039                         if (mWifiGlobals.disableUnwantedNetworkOnLowRssi() && isPrimary()
7040                                 && config != null && !isRecentlySelectedByTheUser(config)
7041                                 && config.getNetworkSelectionStatus()
7042                                 .getNetworkSelectionDisableReason()
7043                                     == DISABLED_NONE && mWifiInfo.getRssi() != WifiInfo.INVALID_RSSI
7044                                 && mWifiInfo.getRssi() < mScoringParams.getSufficientRssi(
7045                                         mWifiInfo.getFrequency())) {
7046                             if (mVerboseLoggingEnabled) {
7047                                 Log.i(getTag(), "CMD_UNWANTED_NETWORK update network "
7048                                         + config.networkId + " with DISABLED_UNWANTED_LOW_RSSI "
7049                                         + "under rssi:" + mWifiInfo.getRssi());
7050                             }
7051                             mWifiConfigManager.updateNetworkSelectionStatus(
7052                                     config.networkId,
7053                                     DISABLED_UNWANTED_LOW_RSSI);
7054                         }
7055                         mWifiNative.disconnect(mInterfaceName);
7056                     } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
7057                             || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) {
7058                         Log.d(getTag(), (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN
7059                                 ? "NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN"
7060                                 : "NETWORK_STATUS_UNWANTED_VALIDATION_FAILED"));
7061                         WifiConfiguration config = getConnectedWifiConfigurationInternal();
7062                         if (config != null) {
7063                             // Disable autojoin
7064                             if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN) {
7065                                 mWifiConfigManager.setNetworkValidatedInternetAccess(
7066                                         config.networkId, false);
7067                                 WifiScoreCard.PerBssid perBssid = mWifiScoreCard.lookupBssid(
7068                                         mWifiInfo.getSSID(), mWifiInfo.getBSSID());
7069                                 int probInternet = perBssid.estimatePercentInternetAvailability();
7070                                 if (mVerboseLoggingEnabled) {
7071                                     Log.d(TAG, "Potentially disabling network due to no "
7072                                             + "internet. Probability of having internet = "
7073                                             + probInternet);
7074                                 }
7075                                 // Only permanently disable a network if probability of having
7076                                 // internet from the currently connected BSSID is less than 60%.
7077                                 // If there is no historically information of the current BSSID,
7078                                 // the probability of internet will default to 50%, and the network
7079                                 // will be permanently disabled.
7080                                 mWifiConfigManager.updateNetworkSelectionStatus(config.networkId,
7081                                         probInternet < PROBABILITY_WITH_INTERNET_TO_PERMANENTLY_DISABLE_NETWORK
7082                                                 ? DISABLED_NO_INTERNET_PERMANENT
7083                                                 : DISABLED_NO_INTERNET_TEMPORARY);
7084                             } else { // NETWORK_STATUS_UNWANTED_VALIDATION_FAILED
7085                                 // stop collect last-mile stats since validation fail
7086                                 mWifiDiagnostics.reportConnectionEvent(
7087                                         WifiDiagnostics.CONNECTION_EVENT_FAILED,
7088                                         mClientModeManager);
7089                                 mWifiConfigManager.incrementNetworkNoInternetAccessReports(
7090                                         config.networkId);
7091                                 // If this was not recently selected by the user, update network
7092                                 // selection status to temporarily disable the network.
7093                                 if (!isRecentlySelectedByTheUser(config)
7094                                         && !config.noInternetAccessExpected) {
7095                                     if (config.getNetworkSelectionStatus()
7096                                             .getNetworkSelectionDisableReason()
7097                                             != DISABLED_NO_INTERNET_PERMANENT) {
7098                                         Log.i(getTag(), "Temporarily disabling network "
7099                                                 + "because of no-internet access");
7100                                         mWifiConfigManager.updateNetworkSelectionStatus(
7101                                                 config.networkId,
7102                                                 DISABLED_NO_INTERNET_TEMPORARY);
7103                                     }
7104                                     mWifiBlocklistMonitor.handleBssidConnectionFailure(
7105                                             mLastBssid, config,
7106                                             WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE,
7107                                             mWifiInfo.getRssi());
7108                                 }
7109                                 mWifiScoreCard.noteValidationFailure(mWifiInfo);
7110                                 mCmiMonitor.onInternetValidationFailed(mClientModeManager,
7111                                         mCurrentConnectionDetectedCaptivePortal);
7112                             }
7113                         }
7114                     }
7115                     break;
7116                 }
7117                 case CMD_NETWORK_STATUS: {
7118                     if (message.arg1 == NetworkAgent.VALIDATION_STATUS_VALID) {
7119                         // stop collect last-mile stats since validation pass
7120                         mWifiDiagnostics.reportConnectionEvent(
7121                                 WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED, mClientModeManager);
7122                         mWifiScoreCard.noteValidationSuccess(mWifiInfo);
7123                         mWifiBlocklistMonitor.handleNetworkValidationSuccess(mLastBssid,
7124                                 mWifiInfo.getSSID());
7125                         WifiConfiguration config = getConnectedWifiConfigurationInternal();
7126                         if (config != null) {
7127                             // re-enable autojoin
7128                             mWifiConfigManager.updateNetworkSelectionStatus(
7129                                     config.networkId,
7130                                     WifiConfiguration.NetworkSelectionStatus
7131                                             .DISABLED_NONE);
7132                             mWifiConfigManager.setNetworkValidatedInternetAccess(
7133                                     config.networkId, true);
7134                             if (config.isPasspoint()
7135                                     && mTermsAndConditionsUrl != null) {
7136                                 // Clear the T&C after the user accepted them and the we are
7137                                 // notified that the network validation is successful
7138                                 mTermsAndConditionsUrl = null;
7139                                 LinkProperties newLp = new LinkProperties(mLinkProperties);
7140                                 addPasspointInfoToLinkProperties(newLp);
7141                                 sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);
7142                                 mWifiMetrics
7143                                         .incrementTotalNumberOfPasspointAcceptanceOfTermsAndConditions();
7144                             }
7145                             if (retrieveConnectedNetworkDefaultGateway()) {
7146                                 updateLinkedNetworks(config);
7147                             }
7148                         }
7149                         mCmiMonitor.onInternetValidated(mClientModeManager);
7150                     }
7151                     break;
7152                 }
7153                 case CMD_ACCEPT_UNVALIDATED: {
7154                     boolean accept = (message.arg1 != 0);
7155                     mWifiConfigManager.setNetworkNoInternetAccessExpected(mLastNetworkId, accept);
7156                     break;
7157                 }
7158                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT: {
7159                     DisconnectEventInfo eventInfo = (DisconnectEventInfo) message.obj;
7160                     reportConnectionAttemptEnd(
7161                             WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION,
7162                             WifiMetricsProto.ConnectionEvent.HLF_NONE,
7163                             WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
7164                     if (unexpectedDisconnectedReason(eventInfo.reasonCode)) {
7165                         mWifiDiagnostics.triggerBugReportDataCapture(
7166                                 WifiDiagnostics.REPORT_REASON_UNEXPECTED_DISCONNECT);
7167                     }
7168 
7169                     if (!eventInfo.locallyGenerated) {
7170                         // ignore disconnects initiated by wpa_supplicant.
7171                         mWifiScoreCard.noteNonlocalDisconnect(mInterfaceName, eventInfo.reasonCode);
7172                         int rssi = mWifiInfo.getRssi();
7173                         mWifiBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
7174                                 getConnectedWifiConfiguration(),
7175                                 WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, rssi);
7176                     }
7177                     WifiConfiguration config = getConnectedWifiConfigurationInternal();
7178 
7179                     if (mVerboseLoggingEnabled) {
7180                         log("NETWORK_DISCONNECTION_EVENT in connected state"
7181                                 + " BSSID=" + mWifiInfo.getBSSID()
7182                                 + " RSSI=" + mWifiInfo.getRssi()
7183                                 + " freq=" + mWifiInfo.getFrequency()
7184                                 + " reason=" + eventInfo.reasonCode
7185                                 + " Network Selection Status=" + (config == null ? "Unavailable"
7186                                 : config.getNetworkSelectionStatus().getNetworkStatusString()));
7187                     }
7188                     handleNetworkDisconnect(false, eventInfo.reasonCode);
7189                     transitionTo(mDisconnectedState);
7190                     break;
7191                 }
7192                 case CMD_START_ROAM: {
7193                     /* Connect command coming from auto-join */
7194                     int netId = message.arg1;
7195                     String bssid = (String) message.obj;
7196                     if (bssid == null) {
7197                         bssid = SUPPLICANT_BSSID_ANY;
7198                     }
7199                     WifiConfiguration config =
7200                             mWifiConfigManager.getConfiguredNetworkWithoutMasking(netId);
7201                     if (config == null) {
7202                         loge("CMD_START_ROAM and no config, bail out...");
7203                         break;
7204                     }
7205                     mLastScanRssi = mWifiConfigManager.findScanRssi(netId,
7206                             mWifiHealthMonitor.getScanRssiValidTimeMs());
7207                     mWifiScoreCard.noteConnectionAttempt(mWifiInfo, mLastScanRssi, config.SSID);
7208                     setTargetBssid(config, bssid);
7209                     mTargetNetworkId = netId;
7210                     mWifiPseudonymManager.enableStrictConservativePeerModeIfSupported(config);
7211                     logd("CMD_START_ROAM sup state "
7212                             + " my state " + getCurrentState().getName()
7213                             + " nid=" + Integer.toString(netId)
7214                             + " config " + config.getProfileKey()
7215                             + " targetRoamBSSID " + mTargetBssid);
7216 
7217                     reportConnectionAttemptStart(config, mTargetBssid,
7218                             WifiMetricsProto.ConnectionEvent.ROAM_ENTERPRISE);
7219                     if (mWifiNative.roamToNetwork(mInterfaceName, config)) {
7220                         mTargetWifiConfiguration = config;
7221                         mIsAutoRoaming = true;
7222                         mWifiMetrics.logStaEvent(
7223                                 mInterfaceName, StaEvent.TYPE_CMD_START_ROAM, config);
7224                         transitionTo(mRoamingState);
7225                     } else {
7226                         loge("CMD_START_ROAM Failed to start roaming to network " + config);
7227                         reportConnectionAttemptEnd(
7228                                 WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED,
7229                                 WifiMetricsProto.ConnectionEvent.HLF_NONE,
7230                                 WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN);
7231                         mMessageHandlingStatus = MESSAGE_HANDLING_STATUS_FAIL;
7232                         break;
7233                     }
7234                     break;
7235                 }
7236                 case CMD_IP_CONFIGURATION_LOST: {
7237                     mWifiMetrics.incrementIpRenewalFailure();
7238                     handleStatus = NOT_HANDLED;
7239                     break;
7240                 }
7241                 default: {
7242                     handleStatus = NOT_HANDLED;
7243                     break;
7244                 }
7245             }
7246 
7247             if (handleStatus == HANDLED) {
7248                 logStateAndMessage(message, this);
7249             }
7250 
7251             return handleStatus;
7252         }
7253 
7254         @Override
exitImpl()7255         public void exitImpl() {
7256             logd("ClientModeImpl: Leaving Connected state");
7257             mWifiConnectivityManager.handleConnectionStateChanged(
7258                     mClientModeManager,
7259                      WifiConnectivityManager.WIFI_STATE_TRANSITIONING);
7260 
7261             mWifiLastResortWatchdog.connectedStateTransition(false);
7262         }
7263     }
7264 
7265     class DisconnectedState extends RunnerState {
DisconnectedState(int threshold)7266         DisconnectedState(int threshold) {
7267             super(threshold, mWifiInjector.getWifiHandlerLocalLog());
7268         }
7269 
7270         @Override
enterImpl()7271         public void enterImpl() {
7272             Log.i(getTag(), "disconnectedstate enter");
7273             // We don't scan frequently if this is a temporary disconnect
7274             // due to p2p
7275             if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
7276                 // TODO(b/161569371): P2P should wait for all ClientModeImpls to enter
7277                 //  DisconnectedState, not just one instance.
7278                 // (Does P2P Service support STA+P2P concurrency?)
7279                 mWifiP2pConnection.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
7280                 return;
7281             }
7282 
7283             if (mVerboseLoggingEnabled) {
7284                 logd(" Enter DisconnectedState screenOn=" + mScreenOn);
7285             }
7286 
7287             /** clear the roaming state, if we were roaming, we failed */
7288             mIsAutoRoaming = false;
7289             mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
7290 
7291             mWifiConnectivityManager.handleConnectionStateChanged(
7292                     mClientModeManager,
7293                     WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
7294 
7295             if (mDeviceConfigFacade.isOobPseudonymEnabled()) {
7296                 if (mVerboseLoggingEnabled) {
7297                     logd("unregister PseudonymUpdatingListener");
7298                 }
7299                 // unregister it any way, if it was not registered, it's no OP.
7300                 mWifiPseudonymManager
7301                         .unregisterPseudonymUpdatingListener(mPseudonymUpdatingListener);
7302             }
7303         }
7304 
7305         @Override
getMessageLogRec(int what)7306         String getMessageLogRec(int what) {
7307             return ClientModeImpl.class.getSimpleName() + "."
7308                     + DisconnectedState.class.getSimpleName() + "." + getWhatToString(what);
7309         }
7310 
7311         @Override
processMessageImpl(Message message)7312         public boolean processMessageImpl(Message message) {
7313             boolean handleStatus = HANDLED;
7314 
7315             switch (message.what) {
7316                 case CMD_RECONNECT:
7317                 case CMD_REASSOCIATE: {
7318                     if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) {
7319                         // Drop a third party reconnect/reassociate if STA is
7320                         // temporarily disconnected for p2p
7321                         break;
7322                     } else {
7323                         // ConnectableState handles it
7324                         handleStatus = NOT_HANDLED;
7325                     }
7326                     break;
7327                 }
7328                 default: {
7329                     handleStatus = NOT_HANDLED;
7330                     break;
7331                 }
7332             }
7333 
7334             if (handleStatus == HANDLED) {
7335                 logStateAndMessage(message, this);
7336             }
7337             return handleStatus;
7338         }
7339 
7340         @Override
exitImpl()7341         public void exitImpl() {
7342             mWifiConnectivityManager.handleConnectionStateChanged(
7343                     mClientModeManager,
7344                      WifiConnectivityManager.WIFI_STATE_TRANSITIONING);
7345         }
7346     }
7347 
handleGsmAuthRequest(SimAuthRequestData requestData)7348     void handleGsmAuthRequest(SimAuthRequestData requestData) {
7349         WifiConfiguration requestingWifiConfiguration = null;
7350         if (mTargetWifiConfiguration != null
7351                 && mTargetWifiConfiguration.networkId
7352                 == requestData.networkId) {
7353             requestingWifiConfiguration = mTargetWifiConfiguration;
7354             logd("id matches targetWifiConfiguration");
7355         } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
7356                 && mLastNetworkId == requestData.networkId) {
7357             requestingWifiConfiguration = getConnectedWifiConfigurationInternal();
7358             logd("id matches currentWifiConfiguration");
7359         }
7360 
7361         if (requestingWifiConfiguration == null) {
7362             logd("GsmAuthRequest received with null target/current WifiConfiguration.");
7363             return;
7364         }
7365 
7366         /*
7367          * Try authentication in the following order.
7368          *
7369          *    Standard       Cellular_auth     Type Command
7370          *
7371          * 1. 3GPP TS 31.102 3G_authentication [Length][RAND][Length][AUTN]
7372          *                            [Length][RES][Length][CK][Length][IK] and more
7373          * 2. 3GPP TS 31.102 2G_authentication [Length][RAND]
7374          *                            [Length][SRES][Length][Cipher Key Kc]
7375          * 3. 3GPP TS 11.11  2G_authentication [RAND]
7376          *                            [SRES][Cipher Key Kc]
7377          */
7378         String response = mWifiCarrierInfoManager
7379                 .getGsmSimAuthResponse(requestData.data, requestingWifiConfiguration);
7380         if (response == null) {
7381             // In case of failure, issue may be due to sim type, retry as No.2 case
7382             response = mWifiCarrierInfoManager
7383                     .getGsmSimpleSimAuthResponse(requestData.data, requestingWifiConfiguration);
7384             if (response == null) {
7385                 // In case of failure, issue may be due to sim type, retry as No.3 case
7386                 response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
7387                                 requestData.data, requestingWifiConfiguration);
7388             }
7389         }
7390         if (response == null || response.length() == 0) {
7391             mWifiNative.simAuthFailedResponse(mInterfaceName);
7392         } else {
7393             logv("Supplicant Response -" + response);
7394             mWifiNative.simAuthResponse(
7395                     mInterfaceName, WifiNative.SIM_AUTH_RESP_TYPE_GSM_AUTH, response);
7396         }
7397     }
7398 
handle3GAuthRequest(SimAuthRequestData requestData)7399     void handle3GAuthRequest(SimAuthRequestData requestData) {
7400         WifiConfiguration requestingWifiConfiguration = null;
7401         if (mTargetWifiConfiguration != null
7402                 && mTargetWifiConfiguration.networkId
7403                 == requestData.networkId) {
7404             requestingWifiConfiguration = mTargetWifiConfiguration;
7405             logd("id matches targetWifiConfiguration");
7406         } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
7407                 && mLastNetworkId == requestData.networkId) {
7408             requestingWifiConfiguration = getConnectedWifiConfigurationInternal();
7409             logd("id matches currentWifiConfiguration");
7410         }
7411 
7412         if (requestingWifiConfiguration == null) {
7413             logd("3GAuthRequest received with null target/current WifiConfiguration.");
7414             return;
7415         }
7416 
7417         SimAuthResponseData response = mWifiCarrierInfoManager
7418                 .get3GAuthResponse(requestData, requestingWifiConfiguration);
7419         if (response != null) {
7420             mWifiNative.simAuthResponse(
7421                     mInterfaceName, response.type, response.response);
7422         } else {
7423             mWifiNative.umtsAuthFailedResponse(mInterfaceName);
7424         }
7425     }
7426 
7427     /**
7428      * Automatically connect to the network specified
7429      *
7430      * @param networkId ID of the network to connect to
7431      * @param uid UID of the app triggering the connection.
7432      * @param bssid BSSID of the network
7433      */
startConnectToNetwork(int networkId, int uid, String bssid)7434     public void startConnectToNetwork(int networkId, int uid, String bssid) {
7435         sendMessage(CMD_START_CONNECT, networkId, uid, bssid);
7436     }
7437 
7438     /**
7439      * Automatically roam to the network specified
7440      *
7441      * @param networkId ID of the network to roam to
7442      * @param bssid BSSID of the access point to roam to.
7443      */
startRoamToNetwork(int networkId, String bssid)7444     public void startRoamToNetwork(int networkId, String bssid) {
7445         sendMessage(CMD_START_ROAM, networkId, 0, bssid);
7446     }
7447 
7448     /**
7449      * @param reason reason code from supplicant on network disconnected event
7450      * @return true if this is a suspicious disconnect
7451      */
unexpectedDisconnectedReason(int reason)7452     static boolean unexpectedDisconnectedReason(int reason) {
7453         return reason == StaIfaceReasonCode.PREV_AUTH_NOT_VALID
7454                 || reason == StaIfaceReasonCode.CLASS2_FRAME_FROM_NONAUTH_STA
7455                 || reason == StaIfaceReasonCode.CLASS3_FRAME_FROM_NONASSOC_STA
7456                 || reason == StaIfaceReasonCode.DISASSOC_STA_HAS_LEFT
7457                 || reason == StaIfaceReasonCode.STA_REQ_ASSOC_WITHOUT_AUTH
7458                 || reason == StaIfaceReasonCode.MICHAEL_MIC_FAILURE
7459                 || reason == StaIfaceReasonCode.FOURWAY_HANDSHAKE_TIMEOUT
7460                 || reason == StaIfaceReasonCode.GROUP_KEY_UPDATE_TIMEOUT
7461                 || reason == StaIfaceReasonCode.GROUP_CIPHER_NOT_VALID
7462                 || reason == StaIfaceReasonCode.PAIRWISE_CIPHER_NOT_VALID
7463                 || reason == StaIfaceReasonCode.IEEE_802_1X_AUTH_FAILED
7464                 || reason == StaIfaceReasonCode.DISASSOC_LOW_ACK;
7465     }
7466 
getLinkPropertiesSummary(LinkProperties lp)7467     private static String getLinkPropertiesSummary(LinkProperties lp) {
7468         List<String> attributes = new ArrayList<>(6);
7469         if (lp.hasIpv4Address()) {
7470             attributes.add("v4");
7471         }
7472         if (lp.hasIpv4DefaultRoute()) {
7473             attributes.add("v4r");
7474         }
7475         if (lp.hasIpv4DnsServer()) {
7476             attributes.add("v4dns");
7477         }
7478         if (lp.hasGlobalIpv6Address()) {
7479             attributes.add("v6");
7480         }
7481         if (lp.hasIpv6DefaultRoute()) {
7482             attributes.add("v6r");
7483         }
7484         if (lp.hasIpv6DnsServer()) {
7485             attributes.add("v6dns");
7486         }
7487 
7488         return TextUtils.join(" ", attributes);
7489     }
7490 
7491     /**
7492      * Gets the SSID from the WifiConfiguration pointed at by 'mTargetNetworkId'
7493      * This should match the network config framework is attempting to connect to.
7494      */
getConnectingSsidInternal()7495     private String getConnectingSsidInternal() {
7496         WifiConfiguration config = getConnectingWifiConfigurationInternal();
7497         return config != null ? config.SSID : null;
7498     }
7499 
7500     /**
7501      * Check if there is any connection request for WiFi network.
7502      */
hasConnectionRequests()7503     private boolean hasConnectionRequests() {
7504         return mNetworkFactory.hasConnectionRequests()
7505                 || mUntrustedNetworkFactory.hasConnectionRequests()
7506                 || mOemWifiNetworkFactory.hasConnectionRequests()
7507                 || mRestrictedWifiNetworkFactory.hasConnectionRequests()
7508                 || mMultiInternetManager.hasPendingConnectionRequests();
7509     }
7510 
7511     /**
7512      * Retrieve the factory MAC address from config store (stored on first bootup). If we don't have
7513      * a factory MAC address stored in config store, retrieve it now and store it.
7514      *
7515      * Note:
7516      * <li> Retries added to deal with any transient failures when invoking
7517      * {@link WifiNative#getStaFactoryMacAddress(String)}.
7518      */
7519     @Nullable
retrieveFactoryMacAddressAndStoreIfNecessary()7520     private MacAddress retrieveFactoryMacAddressAndStoreIfNecessary() {
7521         boolean saveFactoryMacInConfigStore =
7522                 mWifiGlobals.isSaveFactoryMacToConfigStoreEnabled();
7523         if (saveFactoryMacInConfigStore) {
7524             // Already present, just return.
7525             String factoryMacAddressStr = mSettingsConfigStore.get(isPrimary()
7526                     ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS);
7527             if (factoryMacAddressStr != null) return MacAddress.fromString(factoryMacAddressStr);
7528         }
7529         MacAddress factoryMacAddress = mWifiNative.getStaFactoryMacAddress(mInterfaceName);
7530         if (factoryMacAddress == null) {
7531             // the device may be running an older HAL (version < 1.3).
7532             Log.w(TAG, (isPrimary() ? "Primary" : "Secondary")
7533                     + " failed to retrieve factory MAC address");
7534             return null;
7535         }
7536         if (saveFactoryMacInConfigStore) {
7537             mSettingsConfigStore.put(isPrimary()
7538                             ? WIFI_STA_FACTORY_MAC_ADDRESS : SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS,
7539                     factoryMacAddress.toString());
7540             Log.i(TAG, (isPrimary() ? "Primary" : "Secondary")
7541                     + " factory MAC address stored in config store: " + factoryMacAddress);
7542         }
7543         Log.i(TAG, (isPrimary() ? "Primary" : "Secondary")
7544                 + " factory MAC address retrieved: " + factoryMacAddress);
7545         return factoryMacAddress;
7546     }
7547 
7548     /**
7549      * Gets the factory MAC address of wlan0 (station interface).
7550      * @return String representation of the factory MAC address.
7551      */
7552     @Nullable
getFactoryMacAddress()7553     public String getFactoryMacAddress() {
7554         MacAddress factoryMacAddress = retrieveFactoryMacAddressAndStoreIfNecessary();
7555         if (factoryMacAddress != null) return factoryMacAddress.toString();
7556 
7557         // For devices with older HAL's (version < 1.3), no API exists to retrieve factory MAC
7558         // address (and also does not support MAC randomization - needs verson 1.2). So, just
7559         // return the regular MAC address from the interface.
7560         if (!mWifiGlobals.isConnectedMacRandomizationEnabled()) {
7561             Log.w(TAG, "Can't get factory MAC address, return the MAC address");
7562             return mWifiNative.getMacAddress(mInterfaceName);
7563         }
7564         return null;
7565     }
7566 
7567     /** Sends a link probe. */
probeLink(LinkProbeCallback callback, int mcs)7568     public void probeLink(LinkProbeCallback callback, int mcs) {
7569         String bssid = mWifiInfo.getBSSID();
7570         if (bssid == null) {
7571             Log.w(getTag(), "Attempted to send link probe when not connected!");
7572             callback.onFailure(LinkProbeCallback.LINK_PROBE_ERROR_NOT_CONNECTED);
7573             return;
7574         }
7575         mWifiNative.probeLink(mInterfaceName, MacAddress.fromString(bssid), callback, mcs);
7576     }
7577 
7578     private static class ConnectNetworkMessage {
7579         public final NetworkUpdateResult result;
7580         public final ActionListenerWrapper listener;
7581         public final String packageName;
7582 
ConnectNetworkMessage(NetworkUpdateResult result, ActionListenerWrapper listener, String packageName)7583         ConnectNetworkMessage(NetworkUpdateResult result, ActionListenerWrapper listener,
7584                 String packageName) {
7585             this.result = result;
7586             this.listener = listener;
7587             this.packageName = packageName;
7588         }
7589     }
7590 
7591     /** Trigger network connection and provide status via the provided callback. */
connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid, @NonNull String packageName)7592     public void connectNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper,
7593             int callingUid, @NonNull String packageName) {
7594         Message message =
7595                 obtainMessage(CMD_CONNECT_NETWORK,
7596                 new ConnectNetworkMessage(result, wrapper, packageName));
7597         message.sendingUid = callingUid;
7598         sendMessage(message);
7599     }
7600 
7601     /** Trigger network save and provide status via the provided callback. */
saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper, int callingUid, @NonNull String packageName)7602     public void saveNetwork(NetworkUpdateResult result, ActionListenerWrapper wrapper,
7603             int callingUid, @NonNull String packageName) {
7604         Message message =
7605                 obtainMessage(CMD_SAVE_NETWORK,
7606                 new ConnectNetworkMessage(result, wrapper, packageName));
7607         message.sendingUid = callingUid;
7608         sendMessage(message);
7609     }
7610 
7611     /**
7612      * Handle BSS transition request from Connected BSS.
7613      *
7614      * @param frameData Data retrieved from received BTM request frame.
7615      */
handleBssTransitionRequest(BtmFrameData frameData)7616     private void handleBssTransitionRequest(BtmFrameData frameData) {
7617         if (frameData == null) {
7618             return;
7619         }
7620 
7621         String bssid = mWifiInfo.getBSSID();
7622         String ssid = mWifiInfo.getSSID();
7623         if ((bssid == null) || (ssid == null) || WifiManager.UNKNOWN_SSID.equals(ssid)) {
7624             Log.e(getTag(), "Failed to handle BSS transition: bssid: " + bssid + " ssid: " + ssid);
7625             return;
7626         }
7627 
7628         mWifiMetrics.incrementSteeringRequestCount();
7629 
7630         if ((frameData.mBssTmDataFlagsMask
7631                 & MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED)
7632                 != 0) {
7633             mWifiMetrics.incrementMboCellularSwitchRequestCount();
7634         }
7635 
7636 
7637         if ((frameData.mBssTmDataFlagsMask
7638                 & MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT) != 0) {
7639             long duration = 0;
7640             if ((frameData.mBssTmDataFlagsMask
7641                     & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) {
7642                 mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
7643                 duration = frameData.mBlockListDurationMs;
7644             }
7645             if (duration == 0) {
7646                 /*
7647                  * When disassoc imminent bit alone is set or MBO assoc retry delay is
7648                  * set to zero(reserved as per spec), blocklist the BSS for sometime to
7649                  * avoid AP rejecting the re-connect request.
7650                  */
7651                 duration = MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS;
7652             }
7653             // Blocklist the current BSS
7654             WifiConfiguration config = getConnectedWifiConfiguration();
7655             if (config == null) {
7656                 config = getConnectingWifiConfiguration();
7657             }
7658             mWifiBlocklistMonitor.blockBssidForDurationMs(bssid, config, duration,
7659                     WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0);
7660         }
7661 
7662         if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) {
7663             // Trigger the network selection and re-connect to new network if available.
7664             mWifiMetrics.incrementForceScanCountDueToSteeringRequest();
7665             mWifiConnectivityManager.forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
7666         }
7667     }
7668 
7669     /**
7670      * @return true if this device supports FILS-SHA256
7671      */
isFilsSha256Supported()7672     private boolean isFilsSha256Supported() {
7673         return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA256) != 0;
7674     }
7675 
7676     /**
7677      * @return true if this device supports FILS-SHA384
7678      */
isFilsSha384Supported()7679     private boolean isFilsSha384Supported() {
7680         return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA384) != 0;
7681     }
7682 
7683     /**
7684      * @return true if this device supports Trust On First Use
7685      */
isTrustOnFirstUseSupported()7686     private boolean isTrustOnFirstUseSupported() {
7687         return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0;
7688     }
7689 
7690     /**
7691      * Helper method to set the allowed key management schemes from
7692      * scan result.
7693      * When the AKM is updated, changes should be propagated to the
7694      * actual saved network, and the correct AKM could be retrieved
7695      * on selecting the security params.
7696      */
updateAllowedKeyManagementSchemesFromScanResult( WifiConfiguration config, ScanResult scanResult)7697     private void updateAllowedKeyManagementSchemesFromScanResult(
7698             WifiConfiguration config, ScanResult scanResult) {
7699         config.enableFils(
7700                 isFilsSha256Supported()
7701                 && ScanResultUtil.isScanResultForFilsSha256Network(scanResult),
7702                 isFilsSha384Supported()
7703                 && ScanResultUtil.isScanResultForFilsSha384Network(scanResult));
7704         mWifiConfigManager.updateFilsAkms(config.networkId,
7705                 config.isFilsSha256Enabled(), config.isFilsSha384Enabled());
7706     }
7707     /**
7708      * Update wifi configuration based on the matching scan result.
7709      *
7710      * @param config Wifi configuration object.
7711      * @param scanResult Scan result matching the network.
7712      */
updateWifiConfigFromMatchingScanResult(WifiConfiguration config, ScanResult scanResult)7713     private void updateWifiConfigFromMatchingScanResult(WifiConfiguration config,
7714             ScanResult scanResult) {
7715         updateAllowedKeyManagementSchemesFromScanResult(config, scanResult);
7716         if (config.isFilsSha256Enabled() || config.isFilsSha384Enabled()) {
7717             config.enterpriseConfig.setFieldValue(WifiEnterpriseConfig.EAP_ERP, "1");
7718         }
7719     }
7720 
selectCandidateSecurityParamsIfNecessary( WifiConfiguration config, List<ScanResult> scanResults)7721     private void selectCandidateSecurityParamsIfNecessary(
7722             WifiConfiguration config,
7723             List<ScanResult> scanResults) {
7724         if (null != config.getNetworkSelectionStatus().getCandidateSecurityParams()) return;
7725         if (mVerboseLoggingEnabled) {
7726             Log.d(getTag(), "Select candidate security params for " + config.getProfileKey());
7727         }
7728 
7729         // This comes from wifi picker directly so there is no candidate security params.
7730         // Run network selection against this SSID.
7731         List<ScanDetail> scanDetailsList = scanResults.stream()
7732                 .filter(scanResult -> config.SSID.equals(
7733                         ScanResultUtil.createQuotedSsid(scanResult.SSID)))
7734                 .map(ScanDetail::new)
7735                 .collect(Collectors.toList());
7736         List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector
7737                 .getCandidatesForUserSelection(config, scanDetailsList);
7738         mWifiNetworkSelector.selectNetwork(candidates);
7739 
7740         SecurityParams params = null;
7741         // Get the fresh copy again to retrieve the candidate security params.
7742         WifiConfiguration freshConfig = mWifiConfigManager.getConfiguredNetwork(config.networkId);
7743         if (null != freshConfig
7744                 && null != freshConfig.getNetworkSelectionStatus().getCandidateSecurityParams()) {
7745             params = freshConfig.getNetworkSelectionStatus().getCandidateSecurityParams();
7746             Log.i(getTag(), "Select best-fit security params: " + params.getSecurityType());
7747         } else if (null != config.getNetworkSelectionStatus().getLastUsedSecurityParams()
7748                 && config.getNetworkSelectionStatus().getLastUsedSecurityParams().isEnabled()) {
7749             params = config.getNetworkSelectionStatus().getLastUsedSecurityParams();
7750             Log.i(getTag(), "Select the last used security params: " + params.getSecurityType());
7751         } else {
7752             params = config.getSecurityParamsList().stream()
7753                     .filter(WifiConfigurationUtil::isSecurityParamsValid)
7754                     .findFirst().orElse(null);
7755             if (null != params) {
7756                 Log.i(getTag(), "Select the first available security params: "
7757                         + params.getSecurityType());
7758             } else {
7759                 Log.w(getTag(), "No available security params.");
7760             }
7761         }
7762 
7763         config.getNetworkSelectionStatus().setCandidateSecurityParams(params);
7764         // populate the target security params to the internal configuration manually,
7765         // and then wifi info could retrieve this information.
7766         mWifiConfigManager.setNetworkCandidateScanResult(
7767                 config.networkId,
7768                 freshConfig == null ? null : freshConfig.getNetworkSelectionStatus().getCandidate(),
7769                 0, params);
7770     }
7771 
7772     /**
7773      * Update the wifi configuration before sending connect to
7774      * supplicant/driver.
7775      *
7776      * @param config wifi configuration object.
7777      * @param bssid BSSID to assocaite with.
7778      */
updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid)7779     void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) {
7780         setTargetBssid(config, bssid);
7781 
7782         // Go through the matching scan results and update wifi config.
7783         ScanResultMatchInfo key1 = ScanResultMatchInfo.fromWifiConfiguration(config);
7784         List<ScanResult> scanResults = mScanRequestProxy.getScanResults();
7785         for (ScanResult scanResult : scanResults) {
7786             if (!config.SSID.equals(ScanResultUtil.createQuotedSsid(scanResult.SSID))) {
7787                 continue;
7788             }
7789             ScanResultMatchInfo key2 = ScanResultMatchInfo.fromScanResult(scanResult);
7790             if (!key1.equals(key2)) {
7791                 continue;
7792             }
7793             updateWifiConfigFromMatchingScanResult(config, scanResult);
7794         }
7795 
7796         selectCandidateSecurityParamsIfNecessary(config, scanResults);
7797 
7798         if (mWifiGlobals.isConnectedMacRandomizationEnabled()) {
7799             boolean isMacRandomizationForceDisabled = isMacRandomizationForceDisabledOnSsid(config);
7800             if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NONE
7801                     || isMacRandomizationForceDisabled) {
7802                 setCurrentMacToFactoryMac(config);
7803             } else {
7804                 configureRandomizedMacAddress(config);
7805             }
7806             if (isMacRandomizationForceDisabled
7807                     && config.macRandomizationSetting != WifiConfiguration.RANDOMIZATION_NONE) {
7808                 // update WifiConfigManager to disable MAC randomization so Settings show the right
7809                 // MAC randomization information.
7810                 config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
7811                 mWifiConfigManager.addOrUpdateNetwork(config, Process.SYSTEM_UID);
7812             }
7813         }
7814 
7815         if (config.enterpriseConfig != null
7816                 && config.enterpriseConfig.isAuthenticationSimBased()
7817                 && mWifiCarrierInfoManager.isImsiEncryptionInfoAvailable(
7818                 mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))
7819                 && TextUtils.isEmpty(config.enterpriseConfig.getAnonymousIdentity())) {
7820             String anonAtRealm = mWifiCarrierInfoManager
7821                     .getAnonymousIdentityWith3GppRealm(config);
7822             // Use anonymous@<realm> when pseudonym is not available
7823             config.enterpriseConfig.setAnonymousIdentity(anonAtRealm);
7824         }
7825     }
7826 
isMacRandomizationForceDisabledOnSsid(WifiConfiguration config)7827     private boolean isMacRandomizationForceDisabledOnSsid(WifiConfiguration config) {
7828         Set<String> unsupportedSsids = new ArraySet<>(mContext.getResources().getStringArray(
7829                 R.array.config_wifiForceDisableMacRandomizationSsidList));
7830         Set<String> unsupportedPrefixes = mWifiGlobals.getMacRandomizationUnsupportedSsidPrefixes();
7831         boolean isUnsupportedByPrefix =
7832                 unsupportedPrefixes.stream().anyMatch(ssid -> config.SSID.startsWith(ssid));
7833         return isUnsupportedByPrefix || unsupportedSsids.contains(config.SSID);
7834     }
7835 
setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config)7836     private void setConfigurationsPriorToIpClientProvisioning(WifiConfiguration config) {
7837         mIpClient.setHttpProxy(config.getHttpProxy());
7838         if (!TextUtils.isEmpty(mContext.getResources().getString(
7839                 R.string.config_wifi_tcp_buffers))) {
7840             mIpClient.setTcpBufferSizes(mContext.getResources().getString(
7841                     R.string.config_wifi_tcp_buffers));
7842         }
7843     }
7844 
startIpClient(WifiConfiguration config, boolean isFilsConnection)7845     private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) {
7846         if (mIpClient == null || config == null) {
7847             return false;
7848         }
7849 
7850         final boolean isUsingStaticIp =
7851                 (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
7852         final boolean isUsingMacRandomization =
7853                 config.macRandomizationSetting
7854                         != WifiConfiguration.RANDOMIZATION_NONE
7855                         && mWifiGlobals.isConnectedMacRandomizationEnabled();
7856         final List<byte[]> ouis = getOuiInternal(config);
7857         final List<android.net.DhcpOption> options =
7858                 mWifiConfigManager.getCustomDhcpOptions(WifiSsid.fromString(config.SSID), ouis);
7859         if (mVerboseLoggingEnabled) {
7860             final String key = config.getProfileKey();
7861             log("startIpClient netId=" + Integer.toString(mLastNetworkId)
7862                     + " " + key + " "
7863                     + " roam=" + mIsAutoRoaming
7864                     + " static=" + isUsingStaticIp
7865                     + " randomMac=" + isUsingMacRandomization
7866                     + " isFilsConnection=" + isFilsConnection);
7867         }
7868 
7869         final MacAddress currentBssid = getCurrentBssidInternalMacAddress();
7870         final String l2Key = mLastL2KeyAndGroupHint != null
7871                 ? mLastL2KeyAndGroupHint.first : null;
7872         final String groupHint = mLastL2KeyAndGroupHint != null
7873                 ? mLastL2KeyAndGroupHint.second : null;
7874         final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint,
7875                 currentBssid);
7876 
7877         if (isFilsConnection) {
7878             stopIpClient();
7879             if (isUsingStaticIp) {
7880                 mWifiNative.flushAllHlp(mInterfaceName);
7881                 return false;
7882             }
7883             setConfigurationsPriorToIpClientProvisioning(config);
7884             final ProvisioningConfiguration.Builder prov =
7885                     new ProvisioningConfiguration.Builder()
7886                     .withPreDhcpAction()
7887                     .withPreconnection()
7888                     .withDisplayName(config.SSID)
7889                     .withLayer2Information(layer2Info);
7890             if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)
7891                     || isPrimary()) {
7892                 // unclear if the native layer will return the correct non-capabilities if APF is
7893                 // not supported on secondary interfaces.
7894                 prov.withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName));
7895             }
7896             if (isUsingMacRandomization) {
7897                 // Use EUI64 address generation for link-local IPv6 addresses.
7898                 prov.withRandomMacAddress();
7899             }
7900             prov.withDhcpOptions(convertToInternalDhcpOptions(options));
7901             mIpClient.startProvisioning(prov.build());
7902         } else {
7903             sendNetworkChangeBroadcast(DetailedState.OBTAINING_IPADDR);
7904             // We must clear the config BSSID, as the wifi chipset may decide to roam
7905             // from this point on and having the BSSID specified in the network block would
7906             // cause the roam to fail and the device to disconnect.
7907             clearTargetBssid("ObtainingIpAddress");
7908 
7909             // Stop IpClient in case we're switching from DHCP to static
7910             // configuration or vice versa.
7911             //
7912             // When we transition from static configuration to DHCP in
7913             // particular, we must tell ConnectivityService that we're
7914             // disconnected, because DHCP might take a long time during which
7915             // connectivity APIs such as getActiveNetworkInfo should not return
7916             // CONNECTED.
7917             stopDhcpSetup();
7918             setConfigurationsPriorToIpClientProvisioning(config);
7919             ScanResult scanResult = getScanResultInternal(config);
7920 
7921             final ProvisioningConfiguration.Builder prov;
7922             ProvisioningConfiguration.ScanResultInfo scanResultInfo = null;
7923             if (scanResult != null) {
7924                 final List<ScanResultInfo.InformationElement> ies =
7925                         new ArrayList<ScanResultInfo.InformationElement>();
7926                 for (ScanResult.InformationElement ie : scanResult.getInformationElements()) {
7927                     ScanResultInfo.InformationElement scanResultInfoIe =
7928                             new ScanResultInfo.InformationElement(ie.getId(), ie.getBytes());
7929                     ies.add(scanResultInfoIe);
7930                 }
7931                 scanResultInfo = new ProvisioningConfiguration.ScanResultInfo(scanResult.SSID,
7932                         scanResult.BSSID, ies);
7933             }
7934             final Network network = (mNetworkAgent != null) ? mNetworkAgent.getNetwork() : null;
7935             if (!isUsingStaticIp) {
7936                 prov = new ProvisioningConfiguration.Builder()
7937                     .withPreDhcpAction()
7938                     .withNetwork(network)
7939                     .withDisplayName(config.SSID)
7940                     .withScanResultInfo(scanResultInfo)
7941                     .withLayer2Information(layer2Info);
7942             } else {
7943                 StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration();
7944                 prov = new ProvisioningConfiguration.Builder()
7945                         .withStaticConfiguration(staticIpConfig)
7946                         .withNetwork(network)
7947                         .withDisplayName(config.SSID)
7948                         .withLayer2Information(layer2Info);
7949             }
7950             if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)
7951                     || isPrimary()) {
7952                 // unclear if the native layer will return the correct non-capabilities if APF is
7953                 // not supported on secondary interfaces.
7954                 prov.withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName));
7955             }
7956             if (isUsingMacRandomization) {
7957                 // Use EUI64 address generation for link-local IPv6 addresses.
7958                 prov.withRandomMacAddress();
7959             }
7960             prov.withDhcpOptions(convertToInternalDhcpOptions(options));
7961             mIpClient.startProvisioning(prov.build());
7962         }
7963 
7964         return true;
7965     }
7966 
getOuiInternal(WifiConfiguration config)7967     private List<byte[]> getOuiInternal(WifiConfiguration config) {
7968         List<byte[]> ouis = new ArrayList<>();
7969         ScanResult scanResult = getScanResultInternal(config);
7970         if (scanResult == null) {
7971             return ouis;
7972         }
7973         List<InformationElementUtil.Vsa> vsas = InformationElementUtil.getVendorSpecificIE(
7974                 scanResult.informationElements);
7975         for (InformationElementUtil.Vsa vsa : vsas) {
7976             byte[] oui = vsa.oui;
7977             if (oui != null) {
7978                 ouis.add(oui);
7979             }
7980         }
7981         return ouis;
7982     }
7983 
getScanResultInternal(WifiConfiguration config)7984     private ScanResult getScanResultInternal(WifiConfiguration config) {
7985         ScanDetailCache scanDetailCache =
7986                 mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
7987         ScanResult scanResult = null;
7988         if (mLastBssid != null) {
7989             if (scanDetailCache != null) {
7990                 scanResult = scanDetailCache.getScanResult(mLastBssid);
7991             }
7992             // The cached scan result of connected network would be null at the first
7993             // connection, try to check full scan result list again to look up matched
7994             // scan result associated to the current BSSID.
7995             if (scanResult == null) {
7996                 scanResult = mScanRequestProxy.getScanResult(mLastBssid);
7997             }
7998         }
7999         return scanResult;
8000     }
8001 
8002     @Override
setWifiConnectedNetworkScorer(IBinder binder, IWifiConnectedNetworkScorer scorer)8003     public boolean setWifiConnectedNetworkScorer(IBinder binder,
8004             IWifiConnectedNetworkScorer scorer) {
8005         return mWifiScoreReport.setWifiConnectedNetworkScorer(binder, scorer);
8006     }
8007 
8008     @Override
clearWifiConnectedNetworkScorer()8009     public void clearWifiConnectedNetworkScorer() {
8010         mWifiScoreReport.clearWifiConnectedNetworkScorer();
8011     }
8012 
8013     @Override
onNetworkSwitchAccepted(int targetNetworkId, String targetBssid)8014     public void onNetworkSwitchAccepted(int targetNetworkId, String targetBssid) {
8015         mWifiScoreReport.onNetworkSwitchAccepted(targetNetworkId, targetBssid);
8016     }
8017 
8018     @Override
onNetworkSwitchRejected(int targetNetworkId, String targetBssid)8019     public void onNetworkSwitchRejected(int targetNetworkId, String targetBssid) {
8020         mWifiScoreReport.onNetworkSwitchRejected(targetNetworkId, targetBssid);
8021     }
8022 
8023     @Override
sendMessageToClientModeImpl(Message msg)8024     public void sendMessageToClientModeImpl(Message msg) {
8025         sendMessage(msg);
8026     }
8027 
8028     @Override
getId()8029     public long getId() {
8030         return mId;
8031     }
8032 
8033     @Override
dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args)8034     public void dumpWifiScoreReport(FileDescriptor fd, PrintWriter pw, String[] args) {
8035         mWifiScoreReport.dump(fd, pw, args);
8036     }
8037 
8038     /**
8039      * Notifies changes in data connectivity of the default data SIM.
8040      */
8041     @Override
onCellularConnectivityChanged(@ifiDataStall.CellularDataStatusCode int status)8042     public void onCellularConnectivityChanged(@WifiDataStall.CellularDataStatusCode int status) {
8043         mWifiConfigManager.onCellularConnectivityChanged(status);
8044         // do a scan if no cell data and currently not connect to wifi
8045         if (status == WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE
8046                 && getConnectedWifiConfigurationInternal() == null) {
8047             if (mContext.getResources().getBoolean(
8048                     R.bool.config_wifiScanOnCellularDataLossEnabled)) {
8049                 mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
8050             }
8051         }
8052     }
8053 
8054     @Override
setMboCellularDataStatus(boolean available)8055     public void setMboCellularDataStatus(boolean available) {
8056         mWifiNative.setMboCellularDataStatus(mInterfaceName, available);
8057     }
8058 
8059     @Override
getRoamingCapabilities()8060     public WifiNative.RoamingCapabilities getRoamingCapabilities() {
8061         return mWifiNative.getRoamingCapabilities(mInterfaceName);
8062     }
8063 
8064     @Override
configureRoaming(WifiNative.RoamingConfig config)8065     public boolean configureRoaming(WifiNative.RoamingConfig config) {
8066         return mWifiNative.configureRoaming(mInterfaceName, config);
8067     }
8068 
8069     @Override
enableRoaming(boolean enabled)8070     public boolean enableRoaming(boolean enabled) {
8071         int status = mWifiNative.enableFirmwareRoaming(
8072                 mInterfaceName, enabled
8073                         ? WifiNative.ENABLE_FIRMWARE_ROAMING
8074                         : WifiNative.DISABLE_FIRMWARE_ROAMING);
8075         return status == WifiNative.SET_FIRMWARE_ROAMING_SUCCESS;
8076     }
8077 
8078     @Override
setCountryCode(String countryCode)8079     public boolean setCountryCode(String countryCode) {
8080         return mWifiNative.setStaCountryCode(mInterfaceName, countryCode);
8081     }
8082 
8083     @Override
getTxPktFates()8084     public List<TxFateReport> getTxPktFates() {
8085         return mWifiNative.getTxPktFates(mInterfaceName);
8086     }
8087 
8088     @Override
getRxPktFates()8089     public List<RxFateReport> getRxPktFates() {
8090         return mWifiNative.getRxPktFates(mInterfaceName);
8091     }
8092 
8093     @Override
setShouldReduceNetworkScore(boolean shouldReduceNetworkScore)8094     public void setShouldReduceNetworkScore(boolean shouldReduceNetworkScore) {
8095         mWifiScoreReport.setShouldReduceNetworkScore(shouldReduceNetworkScore);
8096     }
8097 
updateApfCapabilitiesOnRoleChangedToPrimary()8098     private void updateApfCapabilitiesOnRoleChangedToPrimary() {
8099         // If packet filter is supported on both connections, ignore since we would have already
8100         // specified the APF during the ipClient provisioning.
8101         if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)) {
8102             return;
8103         }
8104         if (mIpClient != null) {
8105             Log.i(TAG, "Role changed to primary - Update APF capabilities in IpClient");
8106             mIpClient.updateApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName));
8107         }
8108     }
8109 
8110     /**
8111      * Invoked by parent ConcreteClientModeManager whenever a role change occurs.
8112      */
onRoleChanged()8113     public void onRoleChanged() {
8114         ClientRole role = mClientModeManager.getRole();
8115         if (role == ROLE_CLIENT_PRIMARY) {
8116             updateApfCapabilitiesOnRoleChangedToPrimary();
8117             if (mScreenOn) {
8118                 // Start RSSI polling for the new primary network to enable scoring.
8119                 enableRssiPolling(true);
8120             }
8121         } else {
8122             if (mScreenOn && !isSecondaryInternet()) {
8123                 // Stop RSSI polling (if enabled) for the secondary network.
8124                 enableRssiPolling(false);
8125             }
8126         }
8127         WifiConfiguration connectedNetwork = getConnectedWifiConfiguration();
8128         if (connectedNetwork != null) {
8129             updateWifiInfoWhenConnected(connectedNetwork);
8130             // Update capabilities after a role change.
8131             updateCapabilities(connectedNetwork);
8132         }
8133         mWifiScoreReport.onRoleChanged(role);
8134     }
8135 
addPasspointInfoToLinkProperties(LinkProperties linkProperties)8136     private void addPasspointInfoToLinkProperties(LinkProperties linkProperties) {
8137         // CaptivePortalData.Builder.setVenueFriendlyName API not available on R
8138         if (!SdkLevel.isAtLeastS()) {
8139             return;
8140         }
8141         WifiConfiguration currentNetwork = getConnectedWifiConfigurationInternal();
8142         if (currentNetwork == null || !currentNetwork.isPasspoint()) {
8143             return;
8144         }
8145         ScanResult scanResult = mScanRequestProxy.getScanResult(mLastBssid);
8146 
8147         if (scanResult == null) {
8148             return;
8149         }
8150         URL venueUrl = mPasspointManager.getVenueUrl(scanResult);
8151 
8152         // Update the friendly name to populate the notification
8153         CaptivePortalData.Builder captivePortalDataBuilder = new CaptivePortalData.Builder()
8154                 .setVenueFriendlyName(currentNetwork.providerFriendlyName);
8155 
8156         // Update the Venue URL if available
8157         if (venueUrl != null) {
8158             captivePortalDataBuilder.setVenueInfoUrl(Uri.parse(venueUrl.toString()),
8159                     CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT);
8160         }
8161 
8162         // Update the T&C URL if available. The network is captive if T&C URL is available
8163         if (mTermsAndConditionsUrl != null) {
8164             captivePortalDataBuilder.setUserPortalUrl(
8165                     Uri.parse(mTermsAndConditionsUrl.toString()),
8166                     CaptivePortalData.CAPTIVE_PORTAL_DATA_SOURCE_PASSPOINT).setCaptive(true);
8167         }
8168 
8169         linkProperties.setCaptivePortalData(captivePortalDataBuilder.build());
8170     }
8171 
8172     private boolean mHasQuit = false;
8173 
8174     @Override
onQuitting()8175     protected void onQuitting() {
8176         mHasQuit = true;
8177         mClientModeManager.onClientModeImplQuit();
8178     }
8179 
8180     /** Returns true if the ClientModeImpl has fully stopped, false otherwise. */
hasQuit()8181     public boolean hasQuit() {
8182         return mHasQuit;
8183     }
8184 
8185     /**
8186      * WifiVcnNetworkPolicyChangeListener tracks VCN-defined Network policies for a
8187      * WifiNetworkAgent. These policies are used to restart Networks or update their
8188      * NetworkCapabilities.
8189      */
8190     @SuppressLint("NewApi")
8191     private class WifiVcnNetworkPolicyChangeListener
8192             implements VcnManager.VcnNetworkPolicyChangeListener {
8193         @Override
onPolicyChanged()8194         public void onPolicyChanged() {
8195             if (mNetworkAgent == null) {
8196                 return;
8197             }
8198             // Update the NetworkAgent's NetworkCapabilities which will merge the current
8199             // capabilities with VcnManagementService's underlying Network policy.
8200             Log.i(getTag(), "VCN policy changed, updating NetworkCapabilities.");
8201             updateCapabilities();
8202         }
8203     }
8204 
8205     /**
8206      * Updates the default gateway mac address of the connected network config and updates the
8207      * linked networks resulting from the new default gateway.
8208      */
retrieveConnectedNetworkDefaultGateway()8209     private boolean retrieveConnectedNetworkDefaultGateway() {
8210         WifiConfiguration currentConfig = getConnectedWifiConfiguration();
8211         if (currentConfig == null) {
8212             logi("can't fetch config of current network id " + mLastNetworkId);
8213             return false;
8214         }
8215 
8216         // Find IPv4 default gateway.
8217         if (mLinkProperties == null) {
8218             logi("cannot retrieve default gateway from null link properties");
8219             return false;
8220         }
8221         String gatewayIPv4 = null;
8222         for (RouteInfo routeInfo : mLinkProperties.getRoutes()) {
8223             if (routeInfo.isDefaultRoute()
8224                     && routeInfo.getDestination().getAddress() instanceof Inet4Address
8225                     && routeInfo.hasGateway()) {
8226                 gatewayIPv4 = routeInfo.getGateway().getHostAddress();
8227                 break;
8228             }
8229         }
8230 
8231         if (TextUtils.isEmpty(gatewayIPv4)) {
8232             logi("default gateway ipv4 is null");
8233             return false;
8234         }
8235 
8236         String gatewayMac = macAddressFromRoute(gatewayIPv4);
8237         if (TextUtils.isEmpty(gatewayMac)) {
8238             logi("default gateway mac fetch failed for ipv4 addr = " + gatewayIPv4);
8239             return false;
8240         }
8241 
8242         if (mVerboseLoggingEnabled) {
8243             logi("Default Gateway MAC address of " + mLastBssid + " from routes is : "
8244                     + gatewayMac);
8245         }
8246         if (!mWifiConfigManager.setNetworkDefaultGwMacAddress(mLastNetworkId, gatewayMac)) {
8247             logi("default gateway mac set failed for " + currentConfig.getKey() + " network");
8248             return false;
8249         }
8250 
8251         return mWifiConfigManager.saveToStore(true);
8252     }
8253 
8254     /**
8255      * Links the supplied config to all matching saved configs and updates the WifiBlocklistMonitor
8256      * SSID allowlist with the linked networks.
8257      */
updateLinkedNetworks(@onNull WifiConfiguration config)8258     private void updateLinkedNetworks(@NonNull WifiConfiguration config) {
8259         if (!isPrimary()) {
8260             return;
8261         }
8262         if (!mContext.getResources().getBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming)) {
8263             return;
8264         }
8265 
8266         SecurityParams params = mWifiNative.getCurrentNetworkSecurityParams(mInterfaceName);
8267         if (params == null) return;
8268 
8269         WifiConfiguration tmpConfigForCurrentSecurityParams = new WifiConfiguration();
8270         tmpConfigForCurrentSecurityParams.setSecurityParams(params);
8271         if (!WifiConfigurationUtil.isConfigLinkable(tmpConfigForCurrentSecurityParams)) return;
8272 
8273         // Don't set SSID allowlist if we're connected to a network with Fast BSS Transition.
8274         ScanDetailCache scanDetailCache = mWifiConfigManager.getScanDetailCacheForNetwork(
8275                 config.networkId);
8276         if (scanDetailCache == null) {
8277             Log.i(TAG, "Do not update linked networks - no ScanDetailCache found for netId: "
8278                     + config.networkId);
8279             return;
8280         }
8281         ScanResult matchingScanResult = scanDetailCache.getScanResult(mLastBssid);
8282         if (matchingScanResult == null) {
8283             Log.i(TAG, "Do not update linked networks - no matching ScanResult found for BSSID: "
8284                     + mLastBssid);
8285             return;
8286         }
8287         String caps = matchingScanResult.capabilities;
8288         if (caps.contains("FT/PSK") || caps.contains("FT/SAE")) {
8289             Log.i(TAG, "Do not update linked networks - current connection is FT-PSK/FT-SAE");
8290             return;
8291         }
8292 
8293         mWifiConfigManager.updateLinkedNetworks(config.networkId);
8294         Map<String, WifiConfiguration> linkedNetworks = mWifiConfigManager
8295                 .getLinkedNetworksWithoutMasking(config.networkId);
8296 
8297         if (!mWifiNative.updateLinkedNetworks(mInterfaceName, config.networkId, linkedNetworks)) {
8298             return;
8299         }
8300         // Update internal configs once the connection requests are accepted.
8301         linkedNetworks.values().forEach(linkedConfig ->
8302                 mWifiConfigManager.setNetworkLastUsedSecurityParams(
8303                         linkedConfig.networkId, params));
8304 
8305         List<String> allowlistSsids = new ArrayList<>(linkedNetworks.values().stream()
8306                 .filter(linkedConfig -> linkedConfig.allowAutojoin)
8307                 .map(linkedConfig -> linkedConfig.SSID)
8308                 .collect(Collectors.toList()));
8309         if (allowlistSsids.size() > 0) {
8310             allowlistSsids.add(config.SSID);
8311         }
8312         mWifiBlocklistMonitor.setAllowlistSsids(config.SSID, allowlistSsids);
8313         mWifiBlocklistMonitor.updateFirmwareRoamingConfiguration(new ArraySet<>(allowlistSsids));
8314     }
8315 
checkAndHandleLinkedNetworkRoaming(String associatedBssid)8316     private boolean checkAndHandleLinkedNetworkRoaming(String associatedBssid) {
8317         if (!mContext.getResources().getBoolean(R.bool.config_wifiEnableLinkedNetworkRoaming)) {
8318             return false;
8319         }
8320 
8321         ScanResult scanResult = mScanRequestProxy.getScanResult(associatedBssid);
8322         if (scanResult == null) {
8323             return false;
8324         }
8325 
8326         WifiConfiguration config = mWifiConfigManager
8327                 .getSavedNetworkForScanResult(scanResult);
8328         if (config == null || !config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)
8329                 || mLastNetworkId == config.networkId) {
8330             return false;
8331         }
8332 
8333         mIsLinkedNetworkRoaming = true;
8334         setTargetBssid(config, associatedBssid);
8335         mTargetNetworkId = config.networkId;
8336         mTargetWifiConfiguration = config;
8337         mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
8338         sendNetworkChangeBroadcast(DetailedState.CONNECTING);
8339         mWifiInfo.setFrequency(scanResult.frequency);
8340         mWifiInfo.setBSSID(associatedBssid);
8341         updateCurrentConnectionInfo();
8342         return true;
8343     }
8344 
8345     @RequiresApi(Build.VERSION_CODES.S)
8346     private @WifiConfiguration.RecentFailureReason int
mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason( @boOceConstants.MboAssocDisallowedReasonCode int reasonCode)8347             mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason(
8348             @MboOceConstants.MboAssocDisallowedReasonCode int reasonCode) {
8349         switch (reasonCode) {
8350             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_MAX_NUM_STA_ASSOCIATED:
8351                 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_MAX_NUM_STA_ASSOCIATED;
8352             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AIR_INTERFACE_OVERLOADED:
8353                 return WifiConfiguration
8354                         .RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AIR_INTERFACE_OVERLOADED;
8355             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AUTH_SERVER_OVERLOADED:
8356                 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_AUTH_SERVER_OVERLOADED;
8357             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_INSUFFICIENT_RSSI:
8358                 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_INSUFFICIENT_RSSI;
8359             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_UNSPECIFIED:
8360             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED_0:
8361             case MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED:
8362             default:
8363                 return WifiConfiguration.RECENT_FAILURE_MBO_ASSOC_DISALLOWED_UNSPECIFIED;
8364         }
8365     }
8366 
8367     /**
8368      * To set association rejection status in wifi config.
8369      * @param netId The network ID.
8370      * @param assocRejectEventInfo Association rejection information.
8371      */
setAssociationRejectionStatusInConfig(int netId, AssocRejectEventInfo assocRejectEventInfo)8372     private void setAssociationRejectionStatusInConfig(int netId,
8373             AssocRejectEventInfo assocRejectEventInfo) {
8374         int statusCode = assocRejectEventInfo.statusCode;
8375         @WifiConfiguration.RecentFailureReason int reason;
8376 
8377         switch (statusCode) {
8378             case StaIfaceStatusCode.AP_UNABLE_TO_HANDLE_NEW_STA:
8379                 reason = WifiConfiguration.RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA;
8380                 break;
8381             case StaIfaceStatusCode.ASSOC_REJECTED_TEMPORARILY:
8382                 reason = WifiConfiguration.RECENT_FAILURE_REFUSED_TEMPORARILY;
8383                 break;
8384             case StaIfaceStatusCode.DENIED_POOR_CHANNEL_CONDITIONS:
8385                 reason = WifiConfiguration.RECENT_FAILURE_POOR_CHANNEL_CONDITIONS;
8386                 break;
8387             default:
8388                 // do nothing
8389                 return;
8390         }
8391 
8392         if (SdkLevel.isAtLeastS()) {
8393             if (assocRejectEventInfo.mboAssocDisallowedInfo != null) {
8394                 reason = mboAssocDisallowedReasonCodeToWifiConfigurationRecentFailureReason(
8395                         assocRejectEventInfo.mboAssocDisallowedInfo.mReasonCode);
8396             } else if (assocRejectEventInfo.oceRssiBasedAssocRejectInfo != null) {
8397                 reason = WifiConfiguration.RECENT_FAILURE_OCE_RSSI_BASED_ASSOCIATION_REJECTION;
8398             }
8399         }
8400 
8401         mWifiConfigManager.setRecentFailureAssociationStatus(netId, reason);
8402 
8403     }
8404 
checkIfNeedDisconnectSecondaryWifi()8405     private void checkIfNeedDisconnectSecondaryWifi() {
8406         if (!isPrimary()) {
8407             return;
8408         }
8409         if (isConnected()) {
8410             ConcreteClientModeManager ccmm =
8411                     mWifiInjector.getActiveModeWarden().getClientModeManagerInRole(
8412                             ROLE_CLIENT_SECONDARY_LONG_LIVED);
8413             if (ccmm != null && ccmm.isConnected() && ccmm.isSecondaryInternet()) {
8414                 WifiInfo secondaryWifiInfo = ccmm.getConnectionInfo();
8415                 if (secondaryWifiInfo == null) return;
8416                 if ((secondaryWifiInfo.is5GHz() && mWifiInfo.is5GHz())
8417                         || (secondaryWifiInfo.is6GHz() && mWifiInfo.is6GHz())
8418                         || (secondaryWifiInfo.is24GHz() && mWifiInfo.is24GHz())) {
8419                     if (mVerboseLoggingEnabled) {
8420                         Log.d(TAG, "The master wifi and secondary wifi are at the same band,"
8421                                 + " disconnect the secondary wifi");
8422                     }
8423                     ccmm.disconnect();
8424                 }
8425             }
8426         }
8427     }
8428 
setSelectedRcoiForPasspoint(WifiConfiguration config)8429     private void setSelectedRcoiForPasspoint(WifiConfiguration config) {
8430         // Only relevant for Passpoint providers with roaming consortium subscriptions
8431         if (config.isPasspoint() && config.roamingConsortiumIds != null
8432                 && config.roamingConsortiumIds.length > 0) {
8433             long selectedRcoi = mPasspointManager.getSelectedRcoiForNetwork(
8434                     config.getPasspointUniqueId(), config.SSID);
8435             if (selectedRcoi != 0) {
8436                 config.enterpriseConfig.setSelectedRcoi(selectedRcoi);
8437             }
8438         }
8439     }
8440 
updateCurrentConnectionInfo()8441     private void updateCurrentConnectionInfo() {
8442         if (isPrimary()) {
8443             mWifiInjector.getActiveModeWarden().updateCurrentConnectionInfo();
8444         }
8445     }
8446 }
8447