Snap for 11296156 from d53919e1e4057be97c2702e1b9a4cc79ce97357e to mainline-tzdata5-release

Change-Id: I596d1e0afbfec61ad4bfb7c472ad039aecffeb05
diff --git a/framework/java/android/net/wifi/SoftApCapability.java b/framework/java/android/net/wifi/SoftApCapability.java
index 58a760c..64d7d41 100644
--- a/framework/java/android/net/wifi/SoftApCapability.java
+++ b/framework/java/android/net/wifi/SoftApCapability.java
@@ -234,6 +234,20 @@
     }
 
     /**
+     * Set SoftAp Capabilities
+     * @param value Boolean to set value 0 or 1
+     * @param features @HotspotFeatures represents which feature to access
+     * @hide
+     */
+    public void setSupportedFeatures(boolean value, @HotspotFeatures long features) {
+        if (value) {
+            mSupportedFeatures |= features;
+        } else {
+            mSupportedFeatures &= ~features;
+        }
+    }
+
+    /**
      * Set supported channel list in target band type.
      *
      * @param band One of the following band types:
diff --git a/framework/java/android/net/wifi/SoftApConfiguration.java b/framework/java/android/net/wifi/SoftApConfiguration.java
index 3de0735..e52a2d2 100644
--- a/framework/java/android/net/wifi/SoftApConfiguration.java
+++ b/framework/java/android/net/wifi/SoftApConfiguration.java
@@ -1018,14 +1018,6 @@
     }
 
     /**
-     * @see #isIeee80211beEnabled()
-     * @hide
-     */
-    public boolean isIeee80211beEnabledInternal() {
-        return mIeee80211beEnabled;
-    }
-
-    /**
      * Returns whether or not the Soft AP is configured to enable 802.11be.
      * This is an indication that if the device support 802.11be AP then to enable or disable
      * that feature. If the device does not support 802.11be AP then this flag is ignored.
@@ -1038,7 +1030,7 @@
         if (!SdkLevel.isAtLeastT()) {
             throw new UnsupportedOperationException();
         }
-        return isIeee80211beEnabledInternal();
+        return mIeee80211beEnabled;
     }
 
     /**
diff --git a/framework/java/android/net/wifi/WifiConfiguration.java b/framework/java/android/net/wifi/WifiConfiguration.java
index ded4ac5..e0c1128 100644
--- a/framework/java/android/net/wifi/WifiConfiguration.java
+++ b/framework/java/android/net/wifi/WifiConfiguration.java
@@ -1192,9 +1192,8 @@
 
     /**
      * Four WEP keys. For each of the four values, provide either an ASCII
-     * string enclosed in double quotation marks (e.g., {@code "abcdef"}),
-     * a string of hex digits (e.g., {@code 0102030405}), or an empty string
-     * (e.g., {@code ""}).
+     * string enclosed in double quotation marks (e.g., {@code "abcdef"})
+     * or a string of hex digits (e.g., {@code 0102030405}).
      * <p/>
      * When the value of one of these keys is read, the actual key is
      * not returned, just a "*" if the key has a value, or the null
@@ -2131,7 +2130,8 @@
                 DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR,
                 DISABLED_NETWORK_NOT_FOUND,
                 DISABLED_CONSECUTIVE_FAILURES,
-                DISABLED_UNWANTED_LOW_RSSI})
+                DISABLED_UNWANTED_LOW_RSSI,
+                DISABLED_REPEATED_NUD_FAILURES})
         public @interface NetworkSelectionDisableReason {}
 
         // Quality Network disabled reasons
@@ -2188,10 +2188,15 @@
          */
         public static final int DISABLED_UNWANTED_LOW_RSSI = 14;
         /**
+         * This network is temporarily disabled due to repeated IP reachability failures.
+         * @hide
+         */
+        public static final int DISABLED_REPEATED_NUD_FAILURES = 15;
+        /**
          * All other disable reasons should be strictly less than this value.
          * @hide
          */
-        public static final int NETWORK_SELECTION_DISABLED_MAX = 15;
+        public static final int NETWORK_SELECTION_DISABLED_MAX = 16;
 
         /**
          * Get an integer that is equal to the maximum integer value of all the
@@ -2369,6 +2374,10 @@
                     new DisableReasonInfo("NETWORK_SELECTION_DISABLED_UNWANTED_LOW_RSSI",
                             1,
                             30 * 1000));
+            reasons.append(DISABLED_REPEATED_NUD_FAILURES,
+                    new DisableReasonInfo("NETWORK_SELECTION_DISABLED_REPEATED_NUD_FAILURES",
+                            1,
+                            15 * 60 * 1000));
             return reasons;
         }
 
diff --git a/service/ServiceWifiResources/res/values-eu/strings.xml b/service/ServiceWifiResources/res/values-eu/strings.xml
index c1463a4..c4f0377 100644
--- a/service/ServiceWifiResources/res/values-eu/strings.xml
+++ b/service/ServiceWifiResources/res/values-eu/strings.xml
@@ -40,10 +40,10 @@
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="9211241189147807136">"Konektatzen bazara, baliteke <xliff:g id="CARRIERNAME">%s</xliff:g> operadorearen wifi-sareek zure SIM txartelarekin lotutako identifikatzaile esklusiboa atzitzea edo partekatzea. Horrela, baliteke zure gailuaren kokapenaren jarraipena egiteko aukera izatea."</string>
     <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="2168947026413431603">"Konektatu"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="5156881939985876066">"Ez konektatu"</string>
-    <string name="wifi_wakeup_onboarding_title" msgid="3868826648004934540">"Wi‑Fi konexioa automatikoki aktibatuko da"</string>
+    <string name="wifi_wakeup_onboarding_title" msgid="3868826648004934540">"Wifi-konexioa automatikoki aktibatuko da"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="5705886295837387430">"Gordeta daukazun kalitate handiko sare batetik gertu zaudenean"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="6209706680391785825">"Ez aktibatu berriro"</string>
-    <string name="wifi_wakeup_enabled_title" msgid="5043486751612595850">"Automatikoki aktibatu da Wi‑Fi konexioa"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="5043486751612595850">"Automatikoki aktibatu da wifi-konexioa"</string>
     <string name="wifi_wakeup_enabled_content" msgid="3911262526267025882">"Gordetako sare honetatik gertu zaude: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_watchdog_network_disabled" msgid="5769226742956006362">"Ezin izan da wifi-sarera konektatu"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="1725243835135539125">" SSIDak Interneteko konexio txarra du."</string>
diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml
index 55910a6..472c191 100644
--- a/service/ServiceWifiResources/res/values/config.xml
+++ b/service/ServiceWifiResources/res/values/config.xml
@@ -370,10 +370,12 @@
     <!-- Indicates that AP mode MAC randomization is supported on this device -->
     <bool translatable="false" name="config_wifi_ap_mac_randomization_supported">true</bool>
 
-    <!-- Indicates that bridged AP mode is supported on this device -->
+    <!-- Indicates that bridged AP mode is supported on this device provided that
+     the device interface combination allows for it -->
     <bool translatable="false" name="config_wifiBridgedSoftApSupported">false</bool>
 
-    <!-- Indicates that STA + bridged AP concurrency mode is supported on this device -->
+    <!-- Indicates that STA + bridged AP concurrency mode is supported on this device provided
+     that the device interface combination allows for it-->
     <bool translatable="false" name="config_wifiStaWithBridgedSoftApConcurrencySupported">false</bool>
 
     <!-- Indicates that dynamic country code update in AP mode is supported on this device -->
@@ -599,6 +601,12 @@
     <integer translatable="false" name="config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs"> -1 </integer>
     <integer translatable="false" name="config_wifiDisableReasonConsecutiveFailuresDurationMs"> 300000 </integer>
 
+    <!-- Configuration for disabling a network due to repeated NUD failures -->
+    <!-- The number of NUD failures that need to happen to trigger blocking -->
+    <integer translatable="false" name="config_wifiDisableReasonRepeatedNudFailuresThreshold"> 5 </integer>
+    <!-- The NUD failures need to happen within this time window or else the counter will be reset -->
+    <integer translatable="false" name="config_wifiDisableReasonRepeatedNudFailuresWindowMs"> 60000 </integer>
+
     <!-- List of constants that indicate the number of consecutive failures per type needed to block a BSSID.
     A blocked BSSID will not be considered in network selection and firmware roaming.-->
     <integer translatable="false" name="config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold"> 1 </integer>
diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml
index f4d5d08..337c708 100644
--- a/service/ServiceWifiResources/res/values/overlayable.xml
+++ b/service/ServiceWifiResources/res/values/overlayable.xml
@@ -177,6 +177,8 @@
           <item type="integer" name="config_wifiDisableReasonByWrongPasswordDurationMs" />
           <item type="integer" name="config_wifiDisableReasonAuthenticationNoSubscriptionDurationMs" />
           <item type="integer" name="config_wifiDisableReasonConsecutiveFailuresDurationMs" />
+          <item type="integer" name="config_wifiDisableReasonRepeatedNudFailuresThreshold" />
+          <item type="integer" name="config_wifiDisableReasonRepeatedNudFailuresWindowMs" />
 
           <item type="integer" name="config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold" />
           <item type="integer" name="config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold" />
diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java
index 22bc460..7abf1a5 100644
--- a/service/java/com/android/server/wifi/ActiveModeWarden.java
+++ b/service/java/com/android/server/wifi/ActiveModeWarden.java
@@ -2714,12 +2714,12 @@
             additionalFeatureSet |= WifiManager.WIFI_FEATURE_AP_RAND_MAC;
         }
 
-        if (ApConfigUtil.isBridgedModeSupported(mContext)) {
+        if (ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)) {
             // The bridged mode requires the kernel network modules support.
             // It doesn't relate the vendor HAL, set if overlay enables it.
             additionalFeatureSet |= WifiManager.WIFI_FEATURE_BRIDGED_AP;
         }
-        if (ApConfigUtil.isStaWithBridgedModeSupported(mContext)) {
+        if (ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative)) {
             // The bridged mode requires the kernel network modules support.
             // It doesn't relate the vendor HAL, set if overlay enables it.
             additionalFeatureSet |= WifiManager.WIFI_FEATURE_STA_BRIDGED_AP;
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index eb12b2e..43db35c 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -357,6 +357,9 @@
     // This is is used to track the number of TDLS peers enabled in driver via enableTdls()
     private Set<String> mEnabledTdlsPeers = new ArraySet<>();
 
+    // Tracks the last NUD failure timestamp, and number of failures.
+    private Pair<Long, Integer> mNudFailureCounter = new Pair<>(0L, 0);
+
     /**
      * Method to clear {@link #mTargetBssid} and reset the current connected network's
      * bssid in wpa_supplicant after a roam/connect attempt.
@@ -1938,7 +1941,7 @@
      */
     public boolean enableTdls(String remoteMacAddress, boolean enable) {
         boolean ret;
-        if (!canEnableTdls()) {
+        if (enable && !canEnableTdls()) {
             return false;
         }
         ret = mWifiNative.startTdls(mInterfaceName, remoteMacAddress, enable);
@@ -3454,6 +3457,7 @@
         mLastSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         mCurrentConnectionDetectedCaptivePortal = false;
         mLastSimBasedConnectionCarrierName = null;
+        mNudFailureCounter = new Pair<>(0L, 0);
         checkAbnormalDisconnectionAndTakeBugReport();
         mWifiScoreCard.resetConnectionState(mInterfaceName);
         updateLayer2Information();
@@ -3967,6 +3971,21 @@
             handleIpReachabilityLost(lossReason);
             return;
         }
+        final long curTime = mClock.getElapsedSinceBootMillis();
+        if (curTime - mNudFailureCounter.first <= mWifiGlobals.getRepeatedNudFailuresWindowMs()) {
+            mNudFailureCounter = new Pair<>(curTime, mNudFailureCounter.second + 1);
+        } else {
+            mNudFailureCounter = new Pair<>(curTime, 1);
+        }
+        if (mNudFailureCounter.second >= mWifiGlobals.getRepeatedNudFailuresThreshold()) {
+            // Disable and disconnect due to repeated NUD failures within limited time window.
+            mWifiConfigManager.updateNetworkSelectionStatus(config.networkId,
+                    WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES);
+            handleIpReachabilityLost(lossReason);
+            mNudFailureCounter = new Pair<>(0L, 0);
+            return;
+        }
+
         final NetworkAgentConfig naConfig = getNetworkAgentConfigInternal(config);
         final NetworkCapabilities nc = getCapabilities(
                 getConnectedWifiConfigurationInternal(), getConnectedBssidInternal());
@@ -6567,6 +6586,7 @@
                     }
                     else {
                         mRssiMonitor.setShortPollRssiInterval();
+                        removeMessages(CMD_RSSI_POLL);
                     }
                     break;
                 }
@@ -8053,6 +8073,7 @@
                             .withPreDhcpAction()
                             .withPreconnection()
                             .withDisplayName(config.SSID)
+                            .withCreatorUid(config.creatorUid)
                             .withLayer2Information(layer2Info)
                             .withProvisioningTimeoutMs(PROVISIONING_TIMEOUT_FILS_CONNECTION_MS);
             if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)
@@ -8106,6 +8127,7 @@
                     .withNetwork(network)
                     .withDisplayName(config.SSID)
                     .withScanResultInfo(scanResultInfo)
+                    .withCreatorUid(config.creatorUid)
                     .withLayer2Information(layer2Info);
             } else {
                 StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration();
@@ -8113,6 +8135,7 @@
                         .withStaticConfiguration(staticIpConfig)
                         .withNetwork(network)
                         .withDisplayName(config.SSID)
+                        .withCreatorUid(config.creatorUid)
                         .withLayer2Information(layer2Info);
             }
             if (mContext.getResources().getBoolean(R.bool.config_wifiEnableApfOnNonPrimarySta)
diff --git a/service/java/com/android/server/wifi/HostapdHalAidlImp.java b/service/java/com/android/server/wifi/HostapdHalAidlImp.java
index 5875c41..c34035f 100644
--- a/service/java/com/android/server/wifi/HostapdHalAidlImp.java
+++ b/service/java/com/android/server/wifi/HostapdHalAidlImp.java
@@ -896,11 +896,9 @@
                 R.bool.config_wifiSoftapHeMuBeamformerSupported);
         hwModeParams.enableHeTargetWakeTime = mContext.getResources().getBoolean(
                 R.bool.config_wifiSoftapHeTwtSupported);
-        hwModeParams.enable80211BE = ApConfigUtil.isIeee80211beSupported(mContext);
-        //Update 80211be support with the configuration.
-        hwModeParams.enable80211BE &= config.isIeee80211beEnabledInternal();
 
         if (SdkLevel.isAtLeastT()) {
+            hwModeParams.enable80211BE = config.isIeee80211beEnabled();
             hwModeParams.maximumChannelBandwidth =
                     mapSoftApInfoBandwidthToHal(config.getMaxChannelBandwidth());
         } else {
diff --git a/service/java/com/android/server/wifi/PmkCacheManager.java b/service/java/com/android/server/wifi/PmkCacheManager.java
index a952870..adcd549 100644
--- a/service/java/com/android/server/wifi/PmkCacheManager.java
+++ b/service/java/com/android/server/wifi/PmkCacheManager.java
@@ -22,6 +22,7 @@
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
@@ -39,6 +40,10 @@
     private final Handler mEventHandler;
 
     private boolean mVerboseLoggingEnabled = false;
+
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
     private SparseArray<List<PmkCacheStoreData>> mPmkCacheEntries = new SparseArray<>();
 
     public PmkCacheManager(Clock clock, Handler eventHandler) {
@@ -58,63 +63,71 @@
      */
     public boolean add(MacAddress macAddress, int networkId, MacAddress bssid,
             long expirationTimeInSec, ArrayList<Byte> serializedEntry) {
-        if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
-        if (macAddress == null) {
-            Log.w(TAG, "Omit PMK cache due to no valid MAC address");
-            return false;
-        }
-        if (null == serializedEntry) {
-            Log.w(TAG, "Omit PMK cache due to null entry.");
-            return false;
-        }
-        final long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
-        if (elapseTimeInSecond >= expirationTimeInSec) {
-            Log.w(TAG, "Omit expired PMK cache.");
-            return false;
-        }
+        synchronized (mLock) {
+            if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
+            if (macAddress == null) {
+                Log.w(TAG, "Omit PMK cache due to no valid MAC address");
+                return false;
+            }
+            if (null == serializedEntry) {
+                Log.w(TAG, "Omit PMK cache due to null entry.");
+                return false;
+            }
+            final long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
+            if (elapseTimeInSecond >= expirationTimeInSec) {
+                Log.w(TAG, "Omit expired PMK cache.");
+                return false;
+            }
 
-        PmkCacheStoreData newStoreData =
-                new PmkCacheStoreData(macAddress, bssid, serializedEntry, expirationTimeInSec);
-        List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
-        if (pmkDataList == null) {
-            pmkDataList = new ArrayList<>();
-            mPmkCacheEntries.put(networkId, pmkDataList);
-        } else {
-            if (bssid != null) {
-                // Remove the stored PMK cache if the PMK cache is changed for an existing BSSID.
-                PmkCacheStoreData existStoreData = pmkDataList.stream()
-                        .filter(storeData -> Objects.equals(storeData.bssid, bssid))
-                        .findAny()
-                        .orElse(null);
-                if (null != existStoreData) {
-                    if (Objects.equals(existStoreData, newStoreData)) {
+            PmkCacheStoreData newStoreData =
+                    new PmkCacheStoreData(macAddress, bssid, serializedEntry, expirationTimeInSec);
+            List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
+            if (pmkDataList == null) {
+                pmkDataList = new ArrayList<>();
+                mPmkCacheEntries.put(networkId, pmkDataList);
+            } else {
+                PmkCacheStoreData existStoreData = null;
+                if (bssid != null) {
+                    // Remove the stored PMK cache if the PMK cache is changed for an existing
+                    // BSSID.
+                    for (PmkCacheStoreData storeData : pmkDataList) {
+                        if (Objects.equals(storeData.bssid, bssid)) {
+                            existStoreData = storeData;
+                            break;
+                        }
+                    }
+                    if (null != existStoreData) {
+                        if (Objects.equals(existStoreData, newStoreData)) {
+                            if (mVerboseLoggingEnabled) {
+                                Log.d(TAG, "PMK entry exists for the BSSID, skip it.");
+                            }
+                            return true;
+                        }
+                        pmkDataList.remove(existStoreData);
+                    }
+                } else {
+                    for (PmkCacheStoreData storeData : pmkDataList) {
+                        if (Objects.equals(storeData, newStoreData)) {
+                            existStoreData = storeData;
+                            break;
+                        }
+                    }
+                    if (null != existStoreData) {
                         if (mVerboseLoggingEnabled) {
-                            Log.d(TAG, "PMK entry exists for the BSSID, skip it.");
+                            Log.d(TAG, "PMK entry exists, skip it.");
                         }
                         return true;
                     }
-                    pmkDataList.remove(existStoreData);
-                }
-            } else {
-                PmkCacheStoreData existStoreData = pmkDataList.stream()
-                        .filter(storeData -> Objects.equals(storeData, newStoreData))
-                        .findAny()
-                        .orElse(null);
-                if (null != existStoreData) {
-                    if (mVerboseLoggingEnabled) {
-                        Log.d(TAG, "PMK entry exists, skip it.");
-                    }
-                    return true;
                 }
             }
-        }
 
-        pmkDataList.add(newStoreData);
-        if (mVerboseLoggingEnabled) {
-            Log.d(TAG, "Network " + networkId + " PmkCache Count: " + pmkDataList.size());
+            pmkDataList.add(newStoreData);
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Network " + networkId + " PmkCache Count: " + pmkDataList.size());
+            }
+            updatePmkCacheExpiration();
+            return true;
         }
-        updatePmkCacheExpiration();
-        return true;
     }
 
     /**
@@ -124,12 +137,14 @@
      * @return true when PMK caches are removed; otherwise, false.
      */
     public boolean remove(int networkId) {
-        if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
-        if (!mPmkCacheEntries.contains(networkId)) return false;
+        synchronized (mLock) {
+            if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
+            if (!mPmkCacheEntries.contains(networkId)) return false;
 
-        mPmkCacheEntries.remove(networkId);
-        updatePmkCacheExpiration();
-        return true;
+            mPmkCacheEntries.remove(networkId);
+            updatePmkCacheExpiration();
+            return true;
+        }
     }
 
     /**
@@ -142,16 +157,18 @@
      */
 
     public boolean remove(int networkId, MacAddress curMacAddress) {
-        if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
-        List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
-        if (null == pmkDataList) return false;
+        synchronized (mLock) {
+            if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return false;
+            List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
+            if (null == pmkDataList) return false;
 
-        pmkDataList.removeIf(pmkData -> !Objects.equals(curMacAddress, pmkData.macAddress));
+            pmkDataList.removeIf(pmkData -> !Objects.equals(curMacAddress, pmkData.macAddress));
 
-        if (pmkDataList.size() == 0) {
-            remove(networkId);
+            if (pmkDataList.size() == 0) {
+                remove(networkId);
+            }
+            return true;
         }
-        return true;
     }
 
     /**
@@ -162,18 +179,20 @@
      *         If none of PMK cache is associated with the network ID, return null.
      */
     public List<ArrayList<Byte>> get(int networkId) {
-        List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
-        if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return null;
-        if (null == pmkDataList) return null;
+        synchronized (mLock) {
+            List<PmkCacheStoreData> pmkDataList = mPmkCacheEntries.get(networkId);
+            if (WifiConfiguration.INVALID_NETWORK_ID == networkId) return null;
+            if (null == pmkDataList) return null;
 
-        final long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
-        List<ArrayList<Byte>> dataList = new ArrayList<>();
-        for (PmkCacheStoreData pmkData: pmkDataList) {
-            if (pmkData.isValid(elapseTimeInSecond)) {
-                dataList.add(pmkData.data);
+            final long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
+            List<ArrayList<Byte>> dataList = new ArrayList<>();
+            for (PmkCacheStoreData pmkData : pmkDataList) {
+                if (pmkData.isValid(elapseTimeInSecond)) {
+                    dataList.add(pmkData.data);
+                }
             }
+            return dataList;
         }
-        return dataList;
     }
 
     /**
@@ -185,46 +204,48 @@
 
     @VisibleForTesting
     void updatePmkCacheExpiration() {
-        mEventHandler.removeCallbacksAndMessages(PMK_CACHE_EXPIRATION_ALARM_TAG);
+        synchronized (mLock) {
+            mEventHandler.removeCallbacksAndMessages(PMK_CACHE_EXPIRATION_ALARM_TAG);
 
-        long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
-        long nextUpdateTimeInSecond = Long.MAX_VALUE;
-        if (mVerboseLoggingEnabled) {
-            Log.d(TAG, "Update PMK cache expiration at " + elapseTimeInSecond);
-        }
-
-        List<Integer> emptyStoreDataList = new ArrayList<>();
-        for (int i = 0; i < mPmkCacheEntries.size(); i++) {
-            int networkId = mPmkCacheEntries.keyAt(i);
-            List<PmkCacheStoreData> list = mPmkCacheEntries.get(networkId);
-            list.removeIf(pmkData -> !pmkData.isValid(elapseTimeInSecond));
-            if (list.size() == 0) {
-                emptyStoreDataList.add(networkId);
-                continue;
+            long elapseTimeInSecond = mClock.getElapsedSinceBootMillis() / 1000;
+            long nextUpdateTimeInSecond = Long.MAX_VALUE;
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Update PMK cache expiration at " + elapseTimeInSecond);
             }
-            for (PmkCacheStoreData pmkData: list) {
-                if (nextUpdateTimeInSecond > pmkData.expirationTimeInSec) {
-                    nextUpdateTimeInSecond = pmkData.expirationTimeInSec;
+
+            List<Integer> emptyStoreDataList = new ArrayList<>();
+            for (int i = 0; i < mPmkCacheEntries.size(); i++) {
+                int networkId = mPmkCacheEntries.keyAt(i);
+                List<PmkCacheStoreData> list = mPmkCacheEntries.get(networkId);
+                list.removeIf(pmkData -> !pmkData.isValid(elapseTimeInSecond));
+                if (list.size() == 0) {
+                    emptyStoreDataList.add(networkId);
+                    continue;
+                }
+                for (PmkCacheStoreData pmkData : list) {
+                    if (nextUpdateTimeInSecond > pmkData.expirationTimeInSec) {
+                        nextUpdateTimeInSecond = pmkData.expirationTimeInSec;
+                    }
                 }
             }
-        }
-        emptyStoreDataList.forEach(networkId -> mPmkCacheEntries.remove(networkId));
+            emptyStoreDataList.forEach(networkId -> mPmkCacheEntries.remove(networkId));
 
-        // No need to arrange next update since there is no valid PMK in the cache.
-        if (nextUpdateTimeInSecond == Long.MAX_VALUE) {
-            return;
-        }
+            // No need to arrange next update since there is no valid PMK in the cache.
+            if (nextUpdateTimeInSecond == Long.MAX_VALUE) {
+                return;
+            }
 
-        if (mVerboseLoggingEnabled) {
-            Log.d(TAG, "PMK cache next expiration time: " + nextUpdateTimeInSecond);
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "PMK cache next expiration time: " + nextUpdateTimeInSecond);
+            }
+            long delayedTimeInMs = (nextUpdateTimeInSecond - elapseTimeInSecond) * 1000;
+            mEventHandler.postDelayed(
+                    () -> {
+                        updatePmkCacheExpiration();
+                    },
+                    PMK_CACHE_EXPIRATION_ALARM_TAG,
+                    (delayedTimeInMs > 0) ? delayedTimeInMs : 0);
         }
-        long delayedTimeInMs = (nextUpdateTimeInSecond - elapseTimeInSecond) * 1000;
-        mEventHandler.postDelayed(
-                () -> {
-                    updatePmkCacheExpiration();
-                },
-                PMK_CACHE_EXPIRATION_ALARM_TAG,
-                (delayedTimeInMs > 0) ? delayedTimeInMs : 0);
     }
 
     private static class PmkCacheStoreData {
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index acaa650..fbe50bc 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -1175,7 +1175,8 @@
                             // Checking STA status only when device supports STA + AP concurrency
                             // since STA would be dropped when device doesn't support it.
                             if (cmms.size() != 0 && mWifiNative.isStaApConcurrencySupported()) {
-                                if (ApConfigUtil.isStaWithBridgedModeSupported(mContext)) {
+                                if (ApConfigUtil.isStaWithBridgedModeSupported(mContext,
+                                        mWifiNative)) {
                                     for (ClientModeManager cmm
                                             : mActiveModeWarden.getClientModeManagers()) {
                                         WifiInfo wifiConnectedInfo = cmm.getConnectionInfo();
@@ -1284,11 +1285,15 @@
                             break;
                         }
 
-                        // Only check if it's possible to create single AP, since a DBS request
-                        // already falls back to single AP if we can't create DBS.
-                        if (!mWifiNative.isItPossibleToCreateApIface(mRequestorWs)) {
-                            handleStartSoftApFailure(START_RESULT_FAILURE_INTERFACE_CONFLICT);
-                            break;
+                        if (SdkLevel.isAtLeastT()
+                                && mCurrentSoftApConfiguration.isIeee80211beEnabled()
+                                && !mCurrentSoftApCapability.areFeaturesSupported(
+                                SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE)) {
+                            Log.d(getTag(), "11BE is not supported, removing from configuration");
+                            mCurrentSoftApConfiguration = new SoftApConfiguration
+                                    .Builder(mCurrentSoftApConfiguration)
+                                    .setIeee80211beEnabled(false)
+                                    .build();
                         }
                         mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(
                                 mWifiNativeInterfaceCallback, mRequestorWs,
@@ -1296,7 +1301,13 @@
                                 SoftApManager.this);
                         if (TextUtils.isEmpty(mApInterfaceName)) {
                             Log.e(getTag(), "setup failure when creating ap interface.");
-                            handleStartSoftApFailure(START_RESULT_FAILURE_CREATE_INTERFACE);
+                            // Only check if it's possible to create single AP, since a DBS request
+                            // already falls back to single AP if we can't create DBS.
+                            if (!mWifiNative.isItPossibleToCreateApIface(mRequestorWs)) {
+                                handleStartSoftApFailure(START_RESULT_FAILURE_INTERFACE_CONFLICT);
+                            } else {
+                                handleStartSoftApFailure(START_RESULT_FAILURE_CREATE_INTERFACE);
+                            }
                             break;
                         }
                         mSoftApNotifier.dismissSoftApShutdownTimeoutExpiredNotification();
@@ -2223,9 +2234,9 @@
                 getRole(),
                 band1,
                 band2,
-                ApConfigUtil.isBridgedModeSupported(mContext),
+                ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative),
                 mWifiNative.isStaApConcurrencySupported(),
-                ApConfigUtil.isStaWithBridgedModeSupported(mContext),
+                ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative),
                 getCurrentStaFreqMhz(),
                 securityType);
     }
@@ -2250,7 +2261,7 @@
                 band,
                 isBridgedMode(),
                 mWifiNative.isStaApConcurrencySupported(),
-                ApConfigUtil.isStaWithBridgedModeSupported(mContext),
+                ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative),
                 getCurrentStaFreqMhz(),
                 mDefaultShutdownTimeoutMillis > 0,
                 -1,
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
index af82aa0..15cf9a9 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java
@@ -329,11 +329,17 @@
             WifiConfiguration curConfiguration =
                     mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
             if (curConfiguration != null) {
+                // In case of PSK networks the disconnection event in the middle of key exchange
+                // happens due to PSK mismatch. But filter out the de-authentication/disassociation
+                // frame from AP with known reason codes which are not related to PSK mismatch from
+                // reporting wrong password error.
                 if (mStateBeforeDisconnect == StaIfaceCallbackState.FOURWAY_HANDSHAKE
                         && (WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration)
-                        || WifiConfigurationUtil.isConfigForWapiPskNetwork(curConfiguration))
-                        && (!locallyGenerated || reasonCode
-                            != StaIfaceReasonCode.IE_IN_4WAY_DIFFERS)) {
+                                || WifiConfigurationUtil.isConfigForWapiPskNetwork(
+                                        curConfiguration))
+                        && (!locallyGenerated
+                                || (reasonCode != StaIfaceReasonCode.IE_IN_4WAY_DIFFERS
+                                        && reasonCode != StaIfaceReasonCode.DISASSOC_AP_BUSY))) {
                     mWifiMonitor.broadcastAuthenticationFailureEvent(
                             mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1,
                             mCurrentSsid, MacAddress.fromBytes(bssid));
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
index 3673d7b..3a50f66 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java
@@ -287,10 +287,17 @@
             WifiConfiguration curConfiguration =
                     mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
             if (curConfiguration != null) {
+                // In case of PSK networks the disconnection event in the middle of key exchange
+                // happens due to PSK mismatch. But filter out the de-authentication/disassociation
+                // frame from AP with known reason codes which are not related to PSK mismatch from
+                // reporting wrong password error.
                 if (mStateBeforeDisconnect == State.FOURWAY_HANDSHAKE
                         && (WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration)
-                        || WifiConfigurationUtil.isConfigForWapiPskNetwork(curConfiguration))
-                        && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
+                                || WifiConfigurationUtil.isConfigForWapiPskNetwork(
+                                        curConfiguration))
+                        && (!locallyGenerated
+                                || (reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS
+                                        && reasonCode != ReasonCode.DISASSOC_AP_BUSY))) {
                     mWifiMonitor.broadcastAuthenticationFailureEvent(
                             mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1,
                             mCurrentSsid, MacAddress.fromBytes(bssid));
diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java
index 33d43f0..f17c6db 100644
--- a/service/java/com/android/server/wifi/WifiApConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiApConfigStore.java
@@ -85,6 +85,7 @@
     private final MacAddressUtil mMacAddressUtil;
     private final WifiConfigManager mWifiConfigManager;
     private final ActiveModeWarden mActiveModeWarden;
+    private final WifiNative mWifiNative;
     private boolean mHasNewDataToSerialize = false;
     private boolean mForceApChannel = false;
     private int mForcedApBand;
@@ -135,7 +136,7 @@
         mWifiConfigManager = wifiConfigManager;
         mActiveModeWarden = activeModeWarden;
         mWifiMetrics = wifiMetrics;
-
+        mWifiNative = wifiInjector.getWifiNative();
         // Register store data listener
         wifiConfigStore.registerStoreData(
                 wifiInjector.makeSoftApStoreData(new SoftApStoreDataSource()));
@@ -215,7 +216,7 @@
     public synchronized SoftApConfiguration upgradeSoftApConfiguration(
             @NonNull SoftApConfiguration config) {
         SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config);
-        if (SdkLevel.isAtLeastS() && ApConfigUtil.isBridgedModeSupported(mContext)
+        if (SdkLevel.isAtLeastS() && ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)
                 && config.getBands().length == 1 && mContext.getResources().getBoolean(
                         R.bool.config_wifiSoftapAutoUpgradeToBridgedConfigWhenSupported)) {
             int[] dual_bands = new int[] {
@@ -290,7 +291,7 @@
         }
 
         if (SdkLevel.isAtLeastS() && config.getBands().length > 1) {
-            if (!ApConfigUtil.isBridgedModeSupported(mContext)
+            if (!ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)
                     || !isBandsSupported(config.getBands(), mContext)) {
                 int newSingleApBand = 0;
                 for (int targetBand : config.getBands()) {
@@ -418,7 +419,7 @@
 
         // It is new overlay configuration, it should always false in R. Add SdkLevel.isAtLeastS for
         // lint check
-        if (ApConfigUtil.isBridgedModeSupported(mContext)) {
+        if (ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)) {
             if (SdkLevel.isAtLeastS()) {
                 int[] dual_bands = new int[] {
                         SoftApConfiguration.BAND_2GHZ,
@@ -589,11 +590,12 @@
      *
      * @param apConfig {@link SoftApConfiguration} to use for softap mode
      * @param isPrivileged indicate the caller can pass some fields check or not
+     * @param wifiNative to use native API to get iface combinations.
      * @return boolean true if the provided config meets the minimum set of details, false
      * otherwise.
      */
     static boolean validateApWifiConfiguration(@NonNull SoftApConfiguration apConfig,
-            boolean isPrivileged, Context context) {
+            boolean isPrivileged, Context context, WifiNative wifiNative) {
         // first check the SSID
         WifiSsid ssid = apConfig.getWifiSsid();
         if (ssid == null || ssid.getBytes().length == 0) {
@@ -670,7 +672,7 @@
 
         if (SdkLevel.isAtLeastT()
                 && authType == SECURITY_TYPE_WPA3_OWE_TRANSITION) {
-            if (!ApConfigUtil.isBridgedModeSupported(context)) {
+            if (!ApConfigUtil.isBridgedModeSupported(context, wifiNative)) {
                 Log.d(TAG, "softap owe transition needs bridge mode support");
                 return false;
             } else if (apConfig.getBands().length > 1) {
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index c2c4800..93263ff 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -1106,6 +1106,20 @@
         }
     }
 
+    private static @WifiEnterpriseConfig.TofuConnectionState int mergeTofuConnectionState(
+            WifiConfiguration internalConfig, WifiConfiguration externalConfig) {
+        // Prioritize the internal config if it has reached a post-connection state.
+        int internalTofuState = internalConfig.enterpriseConfig.getTofuConnectionState();
+        if (internalTofuState == WifiEnterpriseConfig.TOFU_STATE_CONFIGURE_ROOT_CA
+                || internalTofuState == WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING) {
+            return internalTofuState;
+        }
+        // Else assign a pre-connection state based on the latest external config.
+        return externalConfig.enterpriseConfig.isTrustOnFirstUseEnabled()
+                ? WifiEnterpriseConfig.TOFU_STATE_ENABLED_PRE_CONNECTION
+                : WifiEnterpriseConfig.TOFU_STATE_NOT_ENABLED;
+    }
+
     /**
      * Copy over public elements from an external WifiConfiguration object to the internal
      * configuration object if element has been set in the provided external WifiConfiguration.
@@ -1199,10 +1213,18 @@
         }
 
         internalConfig.allowAutojoin = externalConfig.allowAutojoin;
-        // Copy over the |WifiEnterpriseConfig| parameters if set.
+        // Copy over the |WifiEnterpriseConfig| parameters if set. For fields which should
+        // only be set by the framework, cache the internal config's value and restore.
         if (externalConfig.enterpriseConfig != null) {
+            boolean userApproveNoCaCertInternal =
+                    internalConfig.enterpriseConfig.isUserApproveNoCaCert();
+            int tofuDialogStateInternal = internalConfig.enterpriseConfig.getTofuDialogState();
+            int tofuConnectionState = mergeTofuConnectionState(internalConfig, externalConfig);
             internalConfig.enterpriseConfig.copyFromExternal(
                     externalConfig.enterpriseConfig, PASSWORD_MASK);
+            internalConfig.enterpriseConfig.setUserApproveNoCaCert(userApproveNoCaCertInternal);
+            internalConfig.enterpriseConfig.setTofuDialogState(tofuDialogStateInternal);
+            internalConfig.enterpriseConfig.setTofuConnectionState(tofuConnectionState);
         }
 
         // Copy over any metered information.
diff --git a/service/java/com/android/server/wifi/WifiDialogManager.java b/service/java/com/android/server/wifi/WifiDialogManager.java
index 6c35e60..db5d93d 100644
--- a/service/java/com/android/server/wifi/WifiDialogManager.java
+++ b/service/java/com/android/server/wifi/WifiDialogManager.java
@@ -89,14 +89,7 @@
                 if (mVerboseLoggingEnabled) {
                     Log.v(TAG, "Received action: " + action);
                 }
-                if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                    // Change all window types to TYPE_APPLICATION_OVERLAY to prevent the dialogs
-                    // from appearing over the lock screen when the screen turns on again.
-                    for (LegacySimpleDialogHandle dialogHandle : mActiveLegacySimpleDialogs) {
-                        dialogHandle.changeWindowType(
-                                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
-                    }
-                } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
+                if (Intent.ACTION_USER_PRESENT.equals(action)) {
                     // Change all window types to TYPE_KEYGUARD_DIALOG to show the dialogs over the
                     // QuickSettings after the screen is unlocked.
                     for (LegacySimpleDialogHandle dialogHandle : mActiveLegacySimpleDialogs) {
@@ -134,12 +127,11 @@
     public WifiDialogManager(
             @NonNull WifiContext context,
             @NonNull WifiThreadRunner wifiThreadRunner,
-            @NonNull FrameworkFacade frameworkFacade) {
+            @NonNull FrameworkFacade frameworkFacade, WifiInjector wifiInjector) {
         mContext = context;
         mWifiThreadRunner = wifiThreadRunner;
         mFrameworkFacade = frameworkFacade;
         IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_USER_PRESENT);
         intentFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         int flags = 0;
@@ -147,6 +139,34 @@
             flags = Context.RECEIVER_EXPORTED;
         }
         mContext.registerReceiver(mBroadcastReceiver, intentFilter, flags);
+        wifiInjector.getWifiDeviceStateChangeManager()
+                .registerStateChangeCallback(
+                        new WifiDeviceStateChangeManager.StateChangeCallback() {
+                            @Override
+                            public void onScreenStateChanged(boolean screenOn) {
+                                handleScreenStateChanged(screenOn);
+                            }
+                        });
+    }
+
+    private void handleScreenStateChanged(boolean screenOn) {
+        // Change all window types to TYPE_APPLICATION_OVERLAY to
+        // prevent the dialogs from appearing over the lock screen when
+        // the screen turns on again.
+        if (!screenOn) {
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "onScreenStateChanged: screen off");
+            }
+            // Change all window types to TYPE_APPLICATION_OVERLAY to
+            // prevent the dialogs from appearing over the lock screen when
+            // the screen turns on again.
+            for (LegacySimpleDialogHandle dialogHandle :
+                    mActiveLegacySimpleDialogs) {
+                dialogHandle.changeWindowType(
+                        WindowManager.LayoutParams
+                                .TYPE_APPLICATION_OVERLAY);
+            }
+        }
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/WifiGlobals.java b/service/java/com/android/server/wifi/WifiGlobals.java
index 232cf8b..1fa95d0 100644
--- a/service/java/com/android/server/wifi/WifiGlobals.java
+++ b/service/java/com/android/server/wifi/WifiGlobals.java
@@ -69,6 +69,8 @@
     private final int mClientRssiMonitorHysteresisDb;
     private boolean mDisableFirmwareRoamingInIdleMode = false;
     private final boolean mIsSupportMultiInternetDual5G;
+    private final int mRepeatedNudFailuresThreshold;
+    private final int mRepeatedNudFailuresWindowMs;
     private final boolean mAdjustPollRssiIntervalEnabled;
     private final boolean mWifiInterfaceAddedSelfRecoveryEnabled;
     private final int mNetworkNotFoundEventThreshold;
@@ -131,6 +133,10 @@
                 .getBoolean(R.bool.config_wifiDisableFirmwareRoamingInIdleMode);
         mIsSupportMultiInternetDual5G = mContext.getResources().getBoolean(
                 R.bool.config_wifiAllowMultiInternetConnectDual5GFrequency);
+        mRepeatedNudFailuresThreshold = mContext.getResources()
+                .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresThreshold);
+        mRepeatedNudFailuresWindowMs = mContext.getResources()
+                .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresWindowMs);
         mWifiInterfaceAddedSelfRecoveryEnabled = mContext.getResources().getBoolean(
                 R.bool.config_wifiInterfaceAddedSelfRecoveryEnabled);
         mDisableUnwantedNetworkOnLowRssi = mContext.getResources().getBoolean(
@@ -306,6 +312,20 @@
     }
 
     /**
+     * Get number of repeated NUD failures needed to disable a network.
+     */
+    public int getRepeatedNudFailuresThreshold() {
+        return mRepeatedNudFailuresThreshold;
+    }
+
+    /**
+     * Get the time window in millis to count for repeated NUD failures.
+     */
+    public int getRepeatedNudFailuresWindowMs() {
+        return mRepeatedNudFailuresWindowMs;
+    }
+
+    /**
      * Helper method to check if the device may not connect to the configuration
      * due to deprecated security type
      */
@@ -534,6 +554,8 @@
         pw.println("mIsWepDeprecated=" + mIsWepDeprecated);
         pw.println("mIsWpaPersonalDeprecated=" + mIsWpaPersonalDeprecated);
         pw.println("mDisableFirmwareRoamingInIdleMode=" + mDisableFirmwareRoamingInIdleMode);
+        pw.println("mRepeatedNudFailuresThreshold=" + mRepeatedNudFailuresThreshold);
+        pw.println("mRepeatedNudFailuresWindowMs=" + mRepeatedNudFailuresWindowMs);
         pw.println("mCarrierSpecificEapFailureConfigMapPerCarrierId mapping below:");
         for (int i = 0; i < mCarrierSpecificEapFailureConfigMapPerCarrierId.size(); i++) {
             int carrierId = mCarrierSpecificEapFailureConfigMapPerCarrierId.keyAt(i);
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index dc7a639..22f962c 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -309,7 +309,8 @@
         mSoftApBackupRestore = new SoftApBackupRestore(mContext, mSettingsMigrationDataHolder);
         mWifiStateTracker = new WifiStateTracker(mBatteryStats);
         mWifiThreadRunner = new WifiThreadRunner(wifiHandler);
-        mWifiDialogManager = new WifiDialogManager(mContext, mWifiThreadRunner, mFrameworkFacade);
+        mWifiDialogManager = new WifiDialogManager(mContext, mWifiThreadRunner, mFrameworkFacade,
+                this);
         mSsidTranslator = new SsidTranslator(mContext, wifiHandler);
         mWifiP2pServiceHandlerThread = new HandlerThread("WifiP2pService");
         mWifiP2pServiceHandlerThread.start();
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index d16f763..0908ff3 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -4557,6 +4557,15 @@
             if (iface.phyCapabilities == null) {
                 iface.phyCapabilities = mWifiCondManager.getDeviceWiphyCapabilities(ifaceName);
             }
+            if (iface.phyCapabilities != null
+                    && iface.phyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)
+                    != mWifiInjector.getSettingsConfigStore()
+                    .get(WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED)) {
+                mWifiInjector.getSettingsConfigStore().put(
+                        WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED,
+                        iface.phyCapabilities.isWifiStandardSupported(
+                        ScanResult.WIFI_STANDARD_11BE));
+            }
             return iface.phyCapabilities;
         }
     }
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 31fb17c..a22a5a8 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -1623,7 +1623,7 @@
         int uid = Binder.getCallingUid();
         boolean privileged = isSettingsOrSuw(Binder.getCallingPid(), uid);
         return WifiApConfigStore.validateApWifiConfiguration(
-                config, privileged, mContext);
+                config, privileged, mContext, mWifiNative);
     }
 
     /**
@@ -1782,7 +1782,7 @@
         SoftApConfiguration softApConfig = apConfig.getSoftApConfiguration();
         if (softApConfig != null
                 && (!WifiApConfigStore.validateApWifiConfiguration(
-                    softApConfig, privileged, mContext))) {
+                    softApConfig, privileged, mContext, mWifiNative))) {
             Log.e(TAG, "Invalid SoftApConfiguration");
             return false;
         }
@@ -2047,6 +2047,8 @@
             synchronized (mLock) {
                 if (mSoftApCapability == null) {
                     mSoftApCapability = ApConfigUtil.updateCapabilityFromResource(mContext);
+                    mSoftApCapability = ApConfigUtil.updateCapabilityFromConfigStore(
+                            mSoftApCapability, mWifiInjector.getSettingsConfigStore());
                     // Default country code
                     mSoftApCapability = updateSoftApCapabilityWithAvailableChannelList(
                             mSoftApCapability, mCountryCode.getCountryCode());
@@ -2900,7 +2902,7 @@
         SoftApConfiguration softApConfig = ApConfigUtil.fromWifiConfiguration(wifiConfig);
         if (softApConfig == null) return false;
         if (!WifiApConfigStore.validateApWifiConfiguration(
-                softApConfig, false, mContext)) {
+                softApConfig, false, mContext, mWifiNative)) {
             Log.e(TAG, "Invalid WifiConfiguration");
             return false;
         }
@@ -2928,7 +2930,8 @@
         }
         mLog.info("setSoftApConfiguration uid=%").c(uid).flush();
         if (softApConfig == null) return false;
-        if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext)) {
+        if (WifiApConfigStore.validateApWifiConfiguration(softApConfig, privileged, mContext,
+                mWifiNative)) {
             mWifiApConfigStore.setApConfiguration(softApConfig);
             // Send the message for AP config update after the save is done.
             mActiveModeWarden.updateSoftApConfiguration(softApConfig);
@@ -3079,7 +3082,11 @@
     }
 
     @Override
-    public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) {
+    public void getWifiActivityEnergyInfoAsync(@NonNull IOnWifiActivityEnergyInfoListener
+            listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener should not be null");
+        }
         enforceAccessPermission();
         if (mVerboseLoggingEnabled) {
             mLog.info("getWifiActivityEnergyInfoAsync uid=%")
@@ -5334,6 +5341,8 @@
                 pw.println();
                 mWifiConfigManager.dump(fd, pw, args);
                 pw.println();
+                pw.println("WifiApConfigStore config: " + mWifiApConfigStore.getApConfiguration());
+                pw.println();
                 mPasspointManager.dump(pw);
                 pw.println();
                 mWifiInjector.getWifiDiagnostics().captureBugReportData(
diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
index 27ae1f8..73756c9 100644
--- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java
@@ -182,6 +182,12 @@
     public static final Key<Integer> SUPPLICANT_HAL_AIDL_SERVICE_VERSION =
             new Key<>("supplicant_hal_aidl_service_version", -1);
 
+    /**
+     * Store wiphy capability for 11be support.
+     */
+    public static final Key<Boolean> WIFI_WIPHY_11BE_SUPPORTED =
+            new Key<>("wifi_wiphy_11be_supported", true);
+
     /******** Wifi shared pref keys ***************/
 
     private final Context mContext;
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 7375927..96ed2d3 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -2190,6 +2190,123 @@
             setInitialState(mWaitState);
         }
 
+        @Override
+        protected String getWhatToString(int what) {
+            return switch (what) {
+                case COMMAND_TYPE_CONNECT -> "COMMAND_TYPE_CONNECT";
+                case COMMAND_TYPE_DISCONNECT -> "COMMAND_TYPE_DISCONNECT";
+                case COMMAND_TYPE_TERMINATE_SESSION -> "COMMAND_TYPE_TERMINATE_SESSION";
+                case COMMAND_TYPE_PUBLISH -> "COMMAND_TYPE_PUBLISH";
+                case COMMAND_TYPE_UPDATE_PUBLISH -> "COMMAND_TYPE_UPDATE_PUBLISH";
+                case COMMAND_TYPE_SUBSCRIBE -> "COMMAND_TYPE_SUBSCRIBE";
+                case COMMAND_TYPE_UPDATE_SUBSCRIBE -> "COMMAND_TYPE_UPDATE_SUBSCRIBE";
+                case COMMAND_TYPE_ENQUEUE_SEND_MESSAGE -> "COMMAND_TYPE_ENQUEUE_SEND_MESSAGE";
+                case COMMAND_TYPE_ENABLE_USAGE -> "COMMAND_TYPE_ENABLE_USAGE";
+                case COMMAND_TYPE_DISABLE_USAGE -> "COMMAND_TYPE_DISABLE_USAGE";
+                case COMMAND_TYPE_GET_CAPABILITIES -> "COMMAND_TYPE_GET_CAPABILITIES";
+                case COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES
+                        -> "COMMAND_TYPE_DELETE_ALL_DATA_PATH_INTERFACES";
+                case COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE
+                        -> "COMMAND_TYPE_CREATE_DATA_PATH_INTERFACE";
+                case COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE
+                        -> "COMMAND_TYPE_DELETE_DATA_PATH_INTERFACE";
+                case COMMAND_TYPE_INITIATE_DATA_PATH_SETUP
+                        -> "COMMAND_TYPE_INITIATE_DATA_PATH_SETUP";
+                case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST
+                        -> "COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST";
+                case COMMAND_TYPE_END_DATA_PATH -> "COMMAND_TYPE_END_DATA_PATH";
+                case COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE -> "COMMAND_TYPE_TRANSMIT_NEXT_MESSAGE";
+                case COMMAND_TYPE_RECONFIGURE -> "COMMAND_TYPE_RECONFIGURE";
+                case COMMAND_TYPE_DELAYED_INITIALIZATION -> "COMMAND_TYPE_DELAYED_INITIALIZATION";
+                case COMMAND_TYPE_GET_AWARE -> "COMMAND_TYPE_GET_AWARE";
+                case COMMAND_TYPE_RELEASE_AWARE -> "COMMAND_TYPE_RELEASE_AWARE";
+                case COMMAND_TYPE_DISABLE -> "COMMAND_TYPE_DISABLE";
+                case COMMAND_TYPE_INITIATE_PAIRING_REQUEST
+                        -> "COMMAND_TYPE_INITIATE_PAIRING_REQUEST";
+                case COMMAND_TYPE_RESPONSE_PAIRING_REQUEST
+                        -> "COMMAND_TYPE_RESPONSE_PAIRING_REQUEST";
+                case COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST
+                        -> "COMMAND_TYPE_INITIATE_BOOTSTRAPPING_REQUEST";
+                case COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST
+                        -> "COMMAND_TYPE_RESPONSE_BOOTSTRAPPING_REQUEST";
+                case COMMAND_TYPE_SUSPEND_SESSION -> "COMMAND_TYPE_SUSPEND_SESSION";
+                case COMMAND_TYPE_RESUME_SESSION -> "COMMAND_TYPE_RESUME_SESSION";
+                case COMMAND_TYPE_END_PAIRING -> "COMMAND_TYPE_END_PAIRING";
+
+                case RESPONSE_TYPE_ON_CONFIG_SUCCESS -> "RESPONSE_TYPE_ON_CONFIG_SUCCESS";
+                case RESPONSE_TYPE_ON_CONFIG_FAIL -> "RESPONSE_TYPE_ON_CONFIG_FAIL";
+                case RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS
+                        -> "RESPONSE_TYPE_ON_SESSION_CONFIG_SUCCESS";
+                case RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL -> "RESPONSE_TYPE_ON_SESSION_CONFIG_FAIL";
+                case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS
+                        -> "RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_SUCCESS";
+                case RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL
+                        -> "RESPONSE_TYPE_ON_MESSAGE_SEND_QUEUED_FAIL";
+                case RESPONSE_TYPE_ON_CAPABILITIES_UPDATED
+                        -> "RESPONSE_TYPE_ON_CAPABILITIES_UPDATED";
+                case RESPONSE_TYPE_ON_CREATE_INTERFACE -> "RESPONSE_TYPE_ON_CREATE_INTERFACE";
+                case RESPONSE_TYPE_ON_DELETE_INTERFACE -> "RESPONSE_TYPE_ON_DELETE_INTERFACE";
+                case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS
+                        -> "RESPONSE_TYPE_ON_INITIATE_DATA_PATH_SUCCESS";
+                case RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL
+                        -> "RESPONSE_TYPE_ON_INITIATE_DATA_PATH_FAIL";
+                case RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST
+                        -> "RESPONSE_TYPE_ON_RESPOND_TO_DATA_PATH_SETUP_REQUEST";
+                case RESPONSE_TYPE_ON_END_DATA_PATH -> "RESPONSE_TYPE_ON_END_DATA_PATH";
+                case RESPONSE_TYPE_ON_DISABLE -> "RESPONSE_TYPE_ON_DISABLE";
+                case RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS
+                        -> "RESPONSE_TYPE_ON_INITIATE_PAIRING_SUCCESS";
+                case RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL
+                        -> "RESPONSE_TYPE_ON_INITIATE_PAIRING_FAIL";
+                case RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS
+                        -> "RESPONSE_TYPE_ON_RESPONSE_PAIRING_SUCCESS";
+                case RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL
+                        -> "RESPONSE_TYPE_ON_RESPONSE_PAIRING_FAIL";
+                case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS
+                        -> "RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_SUCCESS";
+                case RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL
+                        -> "RESPONSE_TYPE_ON_INITIATE_BOOTSTRAPPING_FAIL";
+                case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS
+                        -> "RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_SUCCESS";
+                case RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL
+                        -> "RESPONSE_TYPE_ON_RESPONSE_BOOTSTRAPPING_FAIL";
+                case RESPONSE_TYPE_ON_SUSPEND -> "RESPONSE_TYPE_ON_SUSPEND";
+                case RESPONSE_TYPE_ON_RESUME -> "RESPONSE_TYPE_ON_RESUME";
+                case RESPONSE_TYPE_ON_END_PAIRING -> "RESPONSE_TYPE_ON_END_PAIRING";
+
+                case NOTIFICATION_TYPE_INTERFACE_CHANGE -> "NOTIFICATION_TYPE_INTERFACE_CHANGE";
+                case NOTIFICATION_TYPE_CLUSTER_CHANGE -> "NOTIFICATION_TYPE_CLUSTER_CHANGE";
+                case NOTIFICATION_TYPE_MATCH -> "NOTIFICATION_TYPE_MATCH";
+                case NOTIFICATION_TYPE_SESSION_TERMINATED -> "NOTIFICATION_TYPE_SESSION_TERMINATED";
+                case NOTIFICATION_TYPE_MESSAGE_RECEIVED -> "NOTIFICATION_TYPE_MESSAGE_RECEIVED";
+                case NOTIFICATION_TYPE_AWARE_DOWN -> "NOTIFICATION_TYPE_AWARE_DOWN";
+                case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS
+                        -> "NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS";
+                case NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL
+                        -> "NOTIFICATION_TYPE_ON_MESSAGE_SEND_FAIL";
+                case NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST
+                        -> "NOTIFICATION_TYPE_ON_DATA_PATH_REQUEST";
+                case NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM
+                        -> "NOTIFICATION_TYPE_ON_DATA_PATH_CONFIRM";
+                case NOTIFICATION_TYPE_ON_DATA_PATH_END -> "NOTIFICATION_TYPE_ON_DATA_PATH_END";
+                case NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE
+                        -> "NOTIFICATION_TYPE_ON_DATA_PATH_SCHED_UPDATE";
+                case NOTIFICATION_TYPE_MATCH_EXPIRED -> "NOTIFICATION_TYPE_MATCH_EXPIRED";
+                case NOTIFICATION_TYPE_ON_PAIRING_REQUEST -> "NOTIFICATION_TYPE_ON_PAIRING_REQUEST";
+                case NOTIFICATION_TYPE_ON_PAIRING_CONFIRM -> "NOTIFICATION_TYPE_ON_PAIRING_CONFIRM";
+                case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST
+                        -> "NOTIFICATION_TYPE_ON_BOOTSTRAPPING_REQUEST";
+                case NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM
+                        -> "NOTIFICATION_TYPE_ON_BOOTSTRAPPING_CONFIRM";
+                case NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED
+                        -> "NOTIFICATION_TYPE_ON_SUSPENSION_MODE_CHANGED";
+                default -> {
+                    Log.wtf(TAG, "unknown message what: " + what);
+                    yield "what:" + what;
+                }
+            };
+        }
+
         public void onAwareDownCleanupSendQueueState() {
             mSendQueueBlocked = false;
             mHostQueuedSendMessages.clear();
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java b/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java
index 0ae1bf7..b2d2ea7 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pMetrics.java
@@ -190,24 +190,8 @@
                 } else {
                     sb.append(StringUtil.calendarToString(c));
                 }
-                sb.append(", connectionType=");
-                switch (event.connectionType) {
-                    case P2pConnectionEvent.CONNECTION_FRESH:
-                        sb.append("FRESH");
-                        break;
-                    case P2pConnectionEvent.CONNECTION_REINVOKE:
-                        sb.append("REINVOKE");
-                        break;
-                    case P2pConnectionEvent.CONNECTION_LOCAL:
-                        sb.append("LOCAL");
-                        break;
-                    case P2pConnectionEvent.CONNECTION_FAST:
-                        sb.append("FAST");
-                        break;
-                    default:
-                        sb.append("UNKNOWN");
-                        break;
-                }
+                sb.append(", connectionType=").append(
+                        getconnectionTypeToString(event.connectionType));
                 sb.append(", wpsMethod=");
                 switch (event.wpsMethod) {
                     case P2pConnectionEvent.WPS_NA:
@@ -231,19 +215,7 @@
                 }
                 sb.append(", durationTakenToConnectMillis=");
                 sb.append(event.durationTakenToConnectMillis);
-                sb.append(", groupRole=");
-                switch (event.groupRole) {
-                    case GroupEvent.GROUP_OWNER:
-                        sb.append("OWNER");
-                        break;
-                    case GroupEvent.GROUP_CLIENT:
-                        sb.append("CLIENT");
-                        break;
-                    default:
-                        sb.append("UNKNOWN DURING CONNECT");
-                        break;
-                }
-
+                sb.append(", groupRole=").append(getGroupRoleToString(event.groupRole));
                 sb.append(", tryCount=");
                 sb.append(event.tryCount);
                 sb.append(", inviteToNeg=");
@@ -258,40 +230,9 @@
                 sb.append(event.staFrequencyMhz);
                 sb.append(", uid=");
                 sb.append(event.uid);
-                sb.append(", connectivityLevelFailureCode=");
-                switch (event.connectivityLevelFailureCode) {
-                    case P2pConnectionEvent.CLF_NONE:
-                        sb.append("NONE");
-                        break;
-                    case P2pConnectionEvent.CLF_TIMEOUT:
-                        sb.append("TIMEOUT");
-                        break;
-                    case P2pConnectionEvent.CLF_CANCEL:
-                        sb.append("CANCEL");
-                        break;
-                    case P2pConnectionEvent.CLF_PROV_DISC_FAIL:
-                        sb.append("PROV_DISC_FAIL");
-                        break;
-                    case P2pConnectionEvent.CLF_INVITATION_FAIL:
-                        sb.append("INVITATION_FAIL");
-                        break;
-                    case P2pConnectionEvent.CLF_USER_REJECT:
-                        sb.append("USER_REJECT");
-                        break;
-                    case P2pConnectionEvent.CLF_NEW_CONNECTION_ATTEMPT:
-                        sb.append("NEW_CONNECTION_ATTEMPT");
-                        break;
-                    case P2pConnectionEvent.CLF_GROUP_REMOVED:
-                        sb.append("GROUP_REMOVED");
-                        break;
-                    case P2pConnectionEvent.CLF_CREATE_GROUP_FAILED:
-                        sb.append("CREATE_GROUP_FAILED");
-                        break;
-                    case P2pConnectionEvent.CLF_UNKNOWN:
-                    default:
-                        sb.append("UNKNOWN");
-                        break;
-                }
+                sb.append(", connectivityLevelFailureCode=").append(
+                        getConnectivityLevelFailureCodeToString(
+                                event.connectivityLevelFailureCode));
                 if (event == mCurrentConnectionEvent) {
                     sb.append(" CURRENTLY OPEN EVENT");
                 }
@@ -342,6 +283,58 @@
         }
     }
 
+    private String getconnectionTypeToString(int connectionType) {
+        switch (connectionType) {
+            case P2pConnectionEvent.CONNECTION_FRESH:
+                return "FRESH";
+            case P2pConnectionEvent.CONNECTION_REINVOKE:
+                return "REINVOKE";
+            case P2pConnectionEvent.CONNECTION_LOCAL:
+                return "LOCAL";
+            case P2pConnectionEvent.CONNECTION_FAST:
+                return "FAST";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
+    private String getGroupRoleToString(int groupRole) {
+        switch (groupRole) {
+            case GroupEvent.GROUP_OWNER:
+                return "OWNER";
+            case GroupEvent.GROUP_CLIENT:
+                return "CLIENT";
+            default:
+                return "UNKNOWN DURING CONNECT";
+        }
+    }
+
+    private String getConnectivityLevelFailureCodeToString(int connectivityLevelFailureCode) {
+        switch (connectivityLevelFailureCode) {
+            case P2pConnectionEvent.CLF_NONE:
+                return "NONE";
+            case P2pConnectionEvent.CLF_TIMEOUT:
+                return "TIMEOUT";
+            case P2pConnectionEvent.CLF_CANCEL:
+                return "CANCEL";
+            case P2pConnectionEvent.CLF_PROV_DISC_FAIL:
+                return "PROV_DISC_FAIL";
+            case P2pConnectionEvent.CLF_INVITATION_FAIL:
+                return "INVITATION_FAIL";
+            case P2pConnectionEvent.CLF_USER_REJECT:
+                return "USER_REJECT";
+            case P2pConnectionEvent.CLF_NEW_CONNECTION_ATTEMPT:
+                return "NEW_CONNECTION_ATTEMPT";
+            case P2pConnectionEvent.CLF_GROUP_REMOVED:
+                return "GROUP_REMOVED";
+            case P2pConnectionEvent.CLF_CREATE_GROUP_FAILED:
+                return "CREATE_GROUP_FAILED";
+            case P2pConnectionEvent.CLF_UNKNOWN:
+            default:
+                return "UNKNOWN";
+        }
+    }
+
     /** Increment total number of peer scans */
     public void incrementPeerScans() {
         synchronized (mLock) {
@@ -392,6 +385,24 @@
     public void startConnectionEvent(int connectionType, WifiP2pConfig config, int groupRole,
             int uid) {
         synchronized (mLock) {
+            StringBuilder stringBuilder = new StringBuilder("Start connection event");
+            if (mCurrentConnectionEvent == null) {
+                stringBuilder.append(", mCurrentConnectionEvent:null");
+            } else {
+                stringBuilder.append(", curConnectionType:")
+                        .append(getconnectionTypeToString(mCurrentConnectionEvent.connectionType))
+                        .append(", curGroupRole:")
+                        .append(getGroupRoleToString(mCurrentConnectionEvent.groupRole))
+                        .append(", curUid:").append(mCurrentConnectionEvent.uid)
+                        .append(", curConnectivityLevelFailureCode:")
+                        .append(getConnectivityLevelFailureCodeToString(
+                                mCurrentConnectionEvent.connectivityLevelFailureCode));
+            }
+            stringBuilder.append(", startConnectionType:")
+                    .append(getconnectionTypeToString(connectionType))
+                    .append(", startGroupRole:").append(getGroupRoleToString(groupRole))
+                    .append(", startUid:").append(uid);
+            Log.d(TAG, stringBuilder.toString());
             // handle overlapping connection event first.
             if (mCurrentConnectionEvent != null) {
                 endConnectionEvent(P2pConnectionEvent.CLF_NEW_CONNECTION_ATTEMPT);
@@ -443,6 +454,23 @@
      */
     public void endConnectionEvent(int failure) {
         synchronized (mLock) {
+            StringBuilder stringBuilder = new StringBuilder("End connection event");
+            if (mCurrentConnectionEvent == null) {
+                stringBuilder.append(", mCurrentConnectionEvent:null");
+            } else {
+                stringBuilder.append(", curConnectionType:")
+                        .append(getconnectionTypeToString(mCurrentConnectionEvent.connectionType))
+                        .append(", curGroupRole:")
+                        .append(getGroupRoleToString(mCurrentConnectionEvent.groupRole))
+                        .append(", curUid:")
+                        .append(mCurrentConnectionEvent.uid)
+                        .append(", curConnectivityLevelFailureCode:")
+                        .append(getConnectivityLevelFailureCodeToString(
+                                mCurrentConnectionEvent.connectivityLevelFailureCode));
+            }
+            stringBuilder.append(", endConnectivityLevelFailureCode:")
+                    .append(getConnectivityLevelFailureCodeToString(failure));
+            Log.d(TAG, stringBuilder.toString());
             if (mCurrentConnectionEvent == null) {
                 // Reinvoking a group with invitation will be handled in supplicant.
                 // There won't be a connection starting event in framework.
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index f16e1e2..a1beea4 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -154,6 +154,7 @@
 import java.nio.charset.CodingErrorAction;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -252,7 +253,7 @@
             android.Manifest.permission.ACCESS_WIFI_STATE
     };
 
-    private static final String[] RECEIVER_PERMISSIONS_FOR_TETHERING = {
+    private static final String[] RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK = {
             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
     };
 
@@ -3675,7 +3676,7 @@
                                 P2pConnectionEvent.CLF_CANCEL);
                         // Notify the peer about the rejection.
                         int delay = 0;
-                        if (mSavedPeerConfig != null) {
+                        if (!TextUtils.isEmpty(mSavedPeerConfig.deviceAddress)) {
                             mWifiNative.p2pStopFind();
                             delay = sendP2pRejection();
                         }
@@ -3685,7 +3686,7 @@
                                         P2P_REJECTION_RESUME_AFTER_DELAY,
                                         ++sP2pRejectionResumeAfterDelayIndex,
                                         WifiP2pManager.CANCEL_CONNECT,
-                                        message),
+                                        Message.obtain(message)),
                                 delay);
                         break;
                     case WifiP2pMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:
@@ -3729,7 +3730,7 @@
                         if (mVerboseLoggingEnabled) {
                             logd("User rejected negotiation " + mSavedPeerConfig);
                         }
-                        if (mSavedPeerConfig != null) {
+                        if (!TextUtils.isEmpty(mSavedPeerConfig.deviceAddress)) {
                             WifiP2pDevice dev = fetchCurrentDeviceDetails(mSavedPeerConfig);
                             boolean join = (dev != null && dev.isGroupOwner())
                                     || mJoinExistingGroup;
@@ -4041,7 +4042,10 @@
                             // As a result, P2P sends a unicast intent to tether service to trigger
                             // the whole flow before entering GroupCreatedState.
                             setWifiP2pInfoOnGroupFormation(null);
-                            if (!sendP2pTetherRequestBroadcast()) {
+                            boolean isSendSuccessful = SdkLevel.isAtLeastU()
+                                    ? sendP2pTetherRequestBroadcastPostU()
+                                    : sendP2pTetherRequestBroadcastPreU();
+                            if (!isSendSuccessful) {
                                 loge("Cannot start tethering, remove " + mGroup);
                                 mWifiNative.p2pGroupRemove(mGroup.getInterface());
                             }
@@ -4798,7 +4802,7 @@
                 sendP2pConnectionChangedBroadcast();
                 if (!SdkLevel.isAtLeastU()) {
                     // Ensure tethering service to stop tethering.
-                    sendP2pTetherRequestBroadcast();
+                    sendP2pTetherRequestBroadcastPreU();
                 }
             }
         }
@@ -5040,10 +5044,13 @@
             if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast");
             Intent intent = getP2pConnectionChangedIntent();
             if (SdkLevel.isAtLeastU()) {
-                // First send direct foreground broadcast to Tethering package
-                sendP2pTetherRequestBroadcast();
-                // Then send the same broadcast to remaining apps excluding Tethering package
-                sendBroadcastWithExcludedPermissions(intent, RECEIVER_PERMISSIONS_FOR_TETHERING);
+                // First send direct foreground broadcast to Tethering package and system service
+                // with same android.permission.MAINLINE_NETWORK_STACK
+                sendBroadcastWithMainlineNetworkStackPermissionPostU();
+                // Then send the same broadcast to remaining apps without
+                // android.permission.MAINLINE_NETWORK_STACK
+                sendBroadcastWithExcludedPermissions(intent,
+                        RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK);
             } else {
                 sendBroadcastWithExcludedPermissions(intent, null);
             }
@@ -5123,32 +5130,47 @@
             return null;
         }
 
-        private boolean sendP2pTetherRequestBroadcast() {
-            String tetheringServicePackage = findTetheringServicePackage();
-            if (TextUtils.isEmpty(tetheringServicePackage)) return false;
-            Log.i(TAG, "sending p2p tether request broadcast to "
-                    + tetheringServicePackage);
-
+        private boolean sendP2pTetherRequestBroadcastPreU() {
             String[] receiverPermissionsForTetheringRequest = {
                     android.Manifest.permission.TETHER_PRIVILEGED
             };
-            if (SdkLevel.isAtLeastU()) {
-                receiverPermissionsForTetheringRequest = RECEIVER_PERMISSIONS_FOR_TETHERING;
-            }
-            Intent intent = getP2pConnectionChangedIntent();
-            intent.setPackage(tetheringServicePackage);
-            if (SdkLevel.isAtLeastU()) {
-                // Adding the flag to allow recipient to run at foreground priority with a shorter
-                // timeout interval.
-                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-            }
+            return sendP2pTetherRequestBroadcastCommon(receiverPermissionsForTetheringRequest,
+                    false, 0);
+        }
 
+        private boolean sendP2pTetherRequestBroadcastPostU() {
+            return sendP2pTetherRequestBroadcastCommon(RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK,
+                    true, Intent.FLAG_RECEIVER_FOREGROUND);
+        }
+
+        private boolean sendP2pTetherRequestBroadcastCommon(String[] permissions,
+                boolean setAdditionalFlags, int flags) {
+            String tetheringServicePackage = findTetheringServicePackage();
+            if (TextUtils.isEmpty(tetheringServicePackage)) return false;
+            Log.i(TAG, "sending p2p tether request broadcast to " + tetheringServicePackage
+                    + " with permission " + Arrays.toString(permissions));
+            Intent intent = getP2pConnectionChangedIntent();
+            if (setAdditionalFlags) {
+                intent.addFlags(flags);
+            }
+            intent.setPackage(tetheringServicePackage);
             Context context = mContext.createContextAsUser(UserHandle.ALL, 0);
-            context.sendBroadcastWithMultiplePermissions(
-                    intent, receiverPermissionsForTetheringRequest);
+            context.sendBroadcastWithMultiplePermissions(intent, permissions);
             return true;
         }
 
+        private void sendBroadcastWithMainlineNetworkStackPermissionPostU() {
+            String[] receiverPermissions = RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK;
+            Intent intent = getP2pConnectionChangedIntent();
+            // Adding the flag to allow recipient to run at foreground priority with a shorter
+            // timeout interval.
+            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            Log.i(TAG, "sending p2p connection changed broadcast with permission "
+                    + Arrays.toString(receiverPermissions));
+            Context context = mContext.createContextAsUser(UserHandle.ALL, 0);
+            context.sendBroadcastWithMultiplePermissions(intent, receiverPermissions);
+        }
+
         private void sendP2pPersistentGroupsChangedBroadcast() {
             if (mVerboseLoggingEnabled) logd("sending p2p persistent groups changed broadcast");
             Intent intent = new Intent(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED);
@@ -6903,6 +6925,11 @@
                 return false;
             }
 
+            if (TextUtils.isEmpty(mSavedPeerConfig.deviceAddress)) {
+                logd("Saved peer address is empty");
+                return false;
+            }
+
             if (!devAddr.equals(MacAddress.fromString(mSavedPeerConfig.deviceAddress))) {
                 logd("Saved peer address is different from " + devAddr);
                 return false;
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 8b5b8e1..96c2984 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -29,6 +29,9 @@
 import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_WPA3_OWE_TRANSITION;
 import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_WPA3_SAE;
 
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -52,6 +55,7 @@
 import com.android.modules.utils.build.SdkLevel;
 import com.android.server.wifi.SoftApManager;
 import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.WifiSettingsConfigStore;
 import com.android.server.wifi.coex.CoexManager;
 import com.android.wifi.resources.R;
 
@@ -1001,6 +1005,27 @@
     }
 
     /**
+     * Helper function to update SoftApCapability instance based on config store.
+     *
+     * @param capability the original softApCapability
+     * @param configStore where we stored the Capability after first time fetch from driver.
+     * @return SoftApCapability which updated from the config store.
+     */
+    @NonNull
+    public static SoftApCapability updateCapabilityFromConfigStore(
+            SoftApCapability capability,
+            WifiSettingsConfigStore configStore) {
+        if (capability == null) {
+            return null;
+        }
+        if (capability.areFeaturesSupported(SOFTAP_FEATURE_IEEE80211_BE)) {
+            capability.setSupportedFeatures(isIeee80211beEnabledInConfig(configStore),
+                    SOFTAP_FEATURE_IEEE80211_BE);
+        }
+        return capability;
+    }
+
+    /**
      * Helper function to get device support 802.11 AX on Soft AP or not
      *
      * @param context the caller context used to get value from resource file.
@@ -1023,6 +1048,18 @@
     }
 
     /**
+     * Helper function to check Config supports 802.11 BE on Soft AP or not
+     *
+     * @param configStore to check the support from WifiSettingsConfigStore
+     * @return true if supported, false otherwise.
+     */
+    public static boolean isIeee80211beEnabledInConfig(
+            WifiSettingsConfigStore configStore) {
+        return configStore.get(
+                    WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED);
+    }
+
+    /**
      * Helper function to get device support AP MAC randomization or not.
      *
      * @param context the caller context used to get value from resource file.
@@ -1037,22 +1074,33 @@
      * Helper function to get HAL support bridged AP or not.
      *
      * @param context the caller context used to get value from resource file.
+     * @param wifiNative to get the Iface combination from device.
      * @return true if supported, false otherwise.
      */
-    public static boolean isBridgedModeSupported(@NonNull Context context) {
+    public static boolean isBridgedModeSupported(
+            @NonNull Context context, @NonNull WifiNative wifiNative) {
         return SdkLevel.isAtLeastS() && context.getResources().getBoolean(
-                    R.bool.config_wifiBridgedSoftApSupported);
+                    R.bool.config_wifiBridgedSoftApSupported)
+                    && wifiNative.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                        }});
     }
 
     /**
      * Helper function to get HAL support STA + bridged AP or not.
      *
      * @param context the caller context used to get value from resource file.
+     * @param wifiNative to get the Iface combination from device.
      * @return true if supported, false otherwise.
      */
-    public static boolean isStaWithBridgedModeSupported(@NonNull Context context) {
+    public static boolean isStaWithBridgedModeSupported(
+            @NonNull Context context, @NonNull WifiNative wifiNative) {
         return SdkLevel.isAtLeastS() && context.getResources().getBoolean(
-                    R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported);
+                    R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)
+                    && wifiNative.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                            put(HDM_CREATE_IFACE_STA, 1);
+                        }});
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java
index 47da81f..52a8704 100644
--- a/service/java/com/android/server/wifi/util/XmlUtil.java
+++ b/service/java/com/android/server/wifi/util/XmlUtil.java
@@ -424,7 +424,7 @@
             EncryptedData[] encryptedDataArray = new EncryptedData[len];
             for (int i = 0; i < len; i++) {
                 if (wepKeys[i] == null) {
-                    encryptedDataArray[i] = new EncryptedData(null, null);
+                    encryptedDataArray[i] = new EncryptedData(new byte[0], new byte[0]);
                 } else {
                     encryptedDataArray[i] = encryptionUtil.encrypt(wepKeys[i].getBytes());
                     if (encryptedDataArray[i] == null) {
@@ -735,7 +735,12 @@
             List<String> wepKeyList = new ArrayList<>();
             final List<EncryptedData> encryptedDataList =
                     XmlUtil.EncryptedDataXmlUtil.parseListFromXml(in, outerTagDepth);
+            EncryptedData emptyData = new EncryptedData(new byte[0], new byte[0]);
             for (int i = 0; i < encryptedDataList.size(); i++) {
+                if (encryptedDataList.get(i).equals(emptyData)) {
+                    wepKeyList.add(null);
+                    continue;
+                }
                 byte[] passphraseBytes = encryptionUtil.decrypt(encryptedDataList.get(i));
                 if (passphraseBytes == null) {
                     Log.wtf(TAG, "Decryption of passphraseBytes failed");
diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index e3361c9..46051d8 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -684,6 +684,7 @@
 
         when(mWifiGlobals.getPollRssiIntervalMillis()).thenReturn(3000);
         when(mWifiGlobals.getIpReachabilityDisconnectEnabled()).thenReturn(true);
+        when(mWifiGlobals.getRepeatedNudFailuresThreshold()).thenReturn(Integer.MAX_VALUE);
 
         when(mFrameworkFacade.getIntegerSetting(mContext,
                 Settings.Global.WIFI_FREQUENCY_BAND,
@@ -7397,6 +7398,57 @@
         verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
     }
 
+    /**
+     * Verify that when HandleRssiOrganicKernelFailuresEnabled, multiple IP reachability failures
+     * within a specified time window will lead to disconnect and network disabled.
+     */
+    @Test
+    public void testRepeatedIpReachabilityFailureDisableNetwork() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastU());
+        when(mDeviceConfigFacade.isHandleRssiOrganicKernelFailuresEnabled()).thenReturn(true);
+        int failureThreshold = 5;
+        int failureWindowMs = 60000;
+        when(mWifiGlobals.getRepeatedNudFailuresThreshold()).thenReturn(failureThreshold);
+        when(mWifiGlobals.getRepeatedNudFailuresWindowMs()).thenReturn(failureWindowMs);
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
+
+        connect();
+        expectRegisterNetworkAgent((agentConfig) -> { }, (cap) -> { });
+        reset(mWifiNetworkAgent);
+
+        for (int i = 0; i < failureThreshold; i++) {
+            // increment time outside the failure window. Failure counter should never add up and
+            // thus not trigger blocking.
+            when(mClock.getElapsedSinceBootMillis()).thenReturn(
+                    (long) (i + 1) * (failureWindowMs + 1));
+            verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
+            verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
+                    eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
+            ReachabilityLossInfoParcelable lossInfo =
+                    new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ORGANIC);
+            mIpClientCallback.onReachabilityFailure(lossInfo);
+            mLooper.dispatchAll();
+        }
+
+        // Now trigger NUD failure within the failure window and verify the network is blocked.
+        for (int i = 0; i < failureThreshold - 1; i++) {
+            when(mClock.getElapsedSinceBootMillis()).thenReturn(
+                    (long) (i + failureThreshold + 1) * (failureWindowMs));
+            verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME);
+            verify(mWifiConfigManager, never()).updateNetworkSelectionStatus(anyInt(),
+                    eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
+            ReachabilityLossInfoParcelable lossInfo =
+                    new ReachabilityLossInfoParcelable("", ReachabilityLossReason.ORGANIC);
+            mIpClientCallback.onReachabilityFailure(lossInfo);
+            mLooper.dispatchAll();
+        }
+
+        // Should disconnect and block network after the last iteration.
+        verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
+                eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_REPEATED_NUD_FAILURES));
+        verify(mWifiNative).disconnect(WIFI_IFACE_NAME);
+    }
+
     @Test
     public void testIpReachabilityFailureOrganic_enableHandleRssiOrganicKernelFailuresFlag()
             throws Exception {
@@ -10444,18 +10496,19 @@
     @Test
     public void testEnableTdls() throws Exception {
         connect();
-        when(mWifiNative.getMaxSupportedConcurrentTdlsSessions(WIFI_IFACE_NAME)).thenReturn(5);
+        when(mWifiNative.getMaxSupportedConcurrentTdlsSessions(WIFI_IFACE_NAME)).thenReturn(1);
         when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME))
                 .thenReturn(WifiManager.WIFI_FEATURE_TDLS);
         when(mWifiNative.startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR), anyBoolean()))
                 .thenReturn(true);
-        assertEquals(5, mCmi.getMaxSupportedConcurrentTdlsSessions());
+        assertEquals(1, mCmi.getMaxSupportedConcurrentTdlsSessions());
         assertTrue(mCmi.isTdlsOperationCurrentlyAvailable());
-        mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, true);
+        assertTrue(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, true));
         assertEquals(1, mCmi.getNumberOfEnabledTdlsSessions());
         verify(mWifiNative).startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR),
                 eq(true));
-        mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, false);
+        assertFalse(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, true));
+        assertTrue(mCmi.enableTdls(TEST_TDLS_PEER_ADDR_STR, false));
         verify(mWifiNative).startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR),
                 eq(false));
         assertEquals(0, mCmi.getNumberOfEnabledTdlsSessions());
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
index 3d7ca24..20cef21 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java
@@ -31,6 +31,8 @@
 
 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY;
 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED;
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
 import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -80,6 +82,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.LocalLog;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import androidx.test.filters.SmallTest;
@@ -161,6 +164,9 @@
     private static final int[] TEST_SUPPORTED_24G_CHANNELS = new int[] {1, 2};
     private static final int[] TEST_SUPPORTED_5G_CHANNELS = new int[] {36, 149};
 
+    private boolean mApBridgeIfaceCobinationSupported = true;
+    private boolean mApBridgeWithStaIfaceCobinationSupported = true;
+
     private TestLooper mLooper;
     private TestAlarmManager mAlarmManager;
     private SoftApInfo mTestSoftApInfo; // Use for single Ap mode test case
@@ -347,6 +353,22 @@
                 .thenReturn(ALLOWED_6G_FREQS);
         when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_60_GHZ))
                 .thenReturn(ALLOWED_60G_FREQS);
+        when(mWifiNative.canDeviceSupportCreateTypeCombo(any()))
+                .thenAnswer(answer -> {
+                    SparseArray<Integer> combo = answer.getArgument(0);
+                    if (combo.contentEquals(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                        }})) {
+                        return mApBridgeIfaceCobinationSupported;
+                    }
+                    if (combo.contentEquals(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                            put(HDM_CREATE_IFACE_STA, 1);
+                        }})) {
+                        return mApBridgeWithStaIfaceCobinationSupported;
+                    }
+                    return false;
+                });
         when(mWifiNative.getApFactoryMacAddress(any())).thenReturn(TEST_INTERFACE_MAC_ADDRESS);
         when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenAnswer(
                 (invocation) -> invocation.getArgument(1));
@@ -391,7 +413,8 @@
                 | SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT
                 | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD
                 | SoftApCapability.SOFTAP_FEATURE_WPA3_SAE
-                | SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION;
+                | SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION
+                | SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE;
         mTestSoftApCapability = new SoftApCapability(testSoftApFeature);
         mTestSoftApCapability.setMaxSupportedClients(10);
         mTestSoftApCapability.setSupportedChannelList(
@@ -617,6 +640,8 @@
     @Test
     public void testStartSoftApNotPossibleToCreateApInterfaceIncrementsMetrics()
             throws Exception {
+        when(mWifiNative.setupInterfaceForSoftApMode(
+                    any(), any(), anyInt(), anyBoolean(), any())).thenReturn(null);
         when(mWifiNative.isItPossibleToCreateApIface(any())).thenReturn(false);
         Builder configBuilder = new SoftApConfiguration.Builder();
         configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
@@ -625,6 +650,7 @@
                 IFACE_IP_MODE_LOCAL_ONLY, configBuilder.build(),
                 mTestSoftApCapability, TEST_COUNTRY_CODE);
         mSoftApManager = createSoftApManager(apConfig, ROLE_SOFTAP_TETHERED);
+        verify(mWifiNative).isItPossibleToCreateApIface(any());
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
         verify(mListener).onStartFailure(mSoftApManager);
@@ -664,6 +690,7 @@
         mSoftApManager = createSoftApManager(nullApConfig, ROLE_SOFTAP_TETHERED);
         verify(mCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED,
                 WifiManager.SAP_START_FAILURE_GENERAL);
+        verify(mWifiNative).isItPossibleToCreateApIface(any());
         verify(mListener).onStartFailure(mSoftApManager);
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         if (SdkLevel.isAtLeastSv2()) {
@@ -2394,10 +2421,17 @@
                 randomizedBssidConfig = randomizedBssidConfigBuilder.build();
                 when(mWifiApConfigStore.randomizeBssidIfUnset(any(), any())).thenReturn(
                         randomizedBssidConfig);
-                expectedConfig = new SoftApConfiguration.Builder(randomizedBssidConfig)
-                        .build();
+
+                expectedConfig = randomizedBssidConfig;
             } else {
-                expectedConfig = new SoftApConfiguration.Builder(config)
+                expectedConfig = config;
+            }
+            if (SdkLevel.isAtLeastT()
+                    && expectedConfig.isIeee80211beEnabled()
+                    && !softApConfig.getCapability().areFeaturesSupported(
+                            SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE)) {
+                expectedConfig = new SoftApConfiguration.Builder(expectedConfig)
+                        .setIeee80211beEnabled(false)
                         .build();
             }
         }
@@ -2432,7 +2466,6 @@
                     mWifiNativeInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE),
                     eq(expectedConfig.getBand()), eq(expectedConfig.getBands().length > 1),
                     eq(mSoftApManager));
-
             // Simulate user approval
             ArgumentCaptor<StateMachine> stateMachineCaptor =
                     ArgumentCaptor.forClass(StateMachine.class);
@@ -2446,6 +2479,9 @@
             stateMachineCaptor.getValue().sendMessage(Message.obtain(messageCaptor.getValue()));
             mLooper.dispatchAll();
         }
+        // isItPossibleToCreateApIface should never happen in normal case since it may fail in
+        // normal use case
+        verify(mWifiNative, never()).isItPossibleToCreateApIface(any());
         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mFakeSoftApNotifier).dismissSoftApShutdownTimeoutExpiredNotification();
         order.verify(mWifiNative).setupInterfaceForSoftApMode(
@@ -2511,8 +2547,7 @@
         verify(mListener).onStarted(mSoftApManager);
         verify(mWifiMetrics).addSoftApUpChangedEvent(true, softApConfig.getTargetMode(),
                 TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLIS, expectedConfig.getBands().length > 1);
-        verify(mWifiMetrics).updateSoftApConfiguration(config == null
-                ? randomizedBssidConfig : expectedConfig, softApConfig.getTargetMode(),
+        verify(mWifiMetrics).updateSoftApConfiguration(expectedConfig, softApConfig.getTargetMode(),
                 expectedConfig.getBands().length > 1);
         verify(mWifiMetrics)
                 .updateSoftApCapability(
@@ -3722,7 +3757,7 @@
     }
 
     @Test
-    public void testFallbackToSingleModeDueToStaExistButStaWithBridgedApNotSupported()
+    public void testFallbackToSingleModeDueToStaExistButStaWithBridgedApNotSupportedByOverlay()
             throws Exception {
         assumeTrue(SdkLevel.isAtLeastS());
         when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported))
@@ -3740,6 +3775,25 @@
     }
 
     @Test
+    public void testFallbackToSingleModeDueToStaExistButStaWithBridgedApNotSupportedByDriver()
+            throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported))
+                .thenReturn(true);
+        mApBridgeWithStaIfaceCobinationSupported = false;
+        Builder configBuilder = new SoftApConfiguration.Builder(
+                generateBridgedModeSoftApConfig(null));
+
+        SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(),
+                mTestSoftApCapability, TEST_COUNTRY_CODE);
+        // Reset band to 2.4G | 5G to generate expected configuration since it should fallback to
+        // single AP mode
+        configBuilder.setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ);
+        startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false);
+    }
+
+    @Test
     public void testFallbackToSingleModeDueToUnableToCreateBridgedAp()
             throws Exception {
         assumeTrue(SdkLevel.isAtLeastS());
@@ -3866,5 +3920,24 @@
         startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false);
     }
 
+    /**
+     * Tests that 11BE is set to disabled in the SoftApConfiguration if it isn't supported by
+     * SoftApCapability.
+     */
+    @Test
+    public void testStartSoftApRemoves11BEIfNotSupported() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastT());
+        mTestSoftApCapability.setSupportedFeatures(false,
+                SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE);
+        Builder configBuilder = new SoftApConfiguration.Builder();
+        configBuilder.setBand(SoftApConfiguration.BAND_2GHZ);
+        configBuilder.setSsid(TEST_SSID);
+        configBuilder.setIeee80211beEnabled(true);
+        SoftApModeConfiguration apConfig = new SoftApModeConfiguration(
+                WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(),
+                mTestSoftApCapability, TEST_COUNTRY_CODE);
+        SoftApConfiguration expectedConfig = configBuilder.setIeee80211beEnabled(false).build();
+        startSoftApAndVerifyEnabled(apConfig, expectedConfig, false);
+    }
 }
 
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
index e3f0695..da6d2b7 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java
@@ -1349,6 +1349,30 @@
     }
 
     /**
+     * Tests the handling of incorrect network password for AP_BUSY error code
+     *
+     * If the disconnect reason is "NO_MORE_STAS - Disassociated because AP is unable
+     * to handle all currently associated STAs", do not call it a password mismatch.
+     */
+    @Test
+    public void testApBusy() throws Exception {
+        executeAndValidateInitializationSequence();
+        assertNotNull(mISupplicantStaIfaceCallback);
+
+        int reasonCode = StaIfaceReasonCode.DISASSOC_AP_BUSY;
+
+        mISupplicantStaIfaceCallback.onStateChanged(
+                StaIfaceCallbackState.FOURWAY_HANDSHAKE,
+                NativeUtil.macAddressToByteArray(BSSID),
+                SUPPLICANT_NETWORK_ID,
+                NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false);
+        mISupplicantStaIfaceCallback.onDisconnected(
+                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
+        verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(any(), anyInt(),
+                anyInt(), any(), any());
+    }
+
+    /**
      * Tests the handling of eap failure during disconnect.
      */
     @Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
index 7f01d7b..16bcdf0 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java
@@ -1586,6 +1586,30 @@
     }
 
     /**
+     * Tests the handling of incorrect network password for AP_BUSY error code
+     *
+     * If the disconnect reason is "NO_MORE_STAS - Disassociated because AP is unable
+     * to handle all currently associated STAs", do not call it a password mismatch.
+     */
+    @Test
+    public void testApBusy() throws Exception {
+        executeAndValidateInitializationSequence();
+        assertNotNull(mISupplicantStaIfaceCallback);
+
+        int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.DISASSOC_AP_BUSY;
+
+        mISupplicantStaIfaceCallback.onStateChanged(
+                ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE,
+                NativeUtil.macAddressToByteArray(BSSID),
+                SUPPLICANT_NETWORK_ID,
+                NativeUtil.decodeSsid(SUPPLICANT_SSID));
+        mISupplicantStaIfaceCallback.onDisconnected(
+                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
+        verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(any(), anyInt(),
+                anyInt(), any(), any());
+    }
+
+    /**
      * Tests the handling of eap failure during disconnect.
      */
     @Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
index 66e3f8a..4e91710 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java
@@ -22,6 +22,8 @@
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION;
 
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertArrayEquals;
@@ -50,6 +52,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.test.TestLooper;
+import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
 
@@ -97,6 +100,7 @@
 
     @Mock private Context mContext;
     @Mock private WifiInjector mWifiInjector;
+    @Mock private WifiNative mWifiNative;
     @Mock private WifiMetrics mWifiMetrics;
     private TestLooper mLooper;
     private Handler mHandler;
@@ -141,8 +145,20 @@
 
         mRandom = new Random();
         when(mWifiInjector.getMacAddressUtil()).thenReturn(mMacAddressUtil);
+        when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
         when(mMacAddressUtil.calculatePersistentMacForSap(any(), anyInt()))
                 .thenReturn(TEST_RANDOMIZED_MAC);
+        when(mWifiNative.canDeviceSupportCreateTypeCombo(any()))
+                .thenAnswer(answer -> {
+                    SparseArray<Integer> combo = answer.getArgument(0);
+                    if (combo.contentEquals(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                        }})) {
+                        return true;
+                    }
+                    return false;
+                });
+
         mResources.setBoolean(R.bool.config_wifi_ap_mac_randomization_supported, true);
         mResources.setBoolean(
                 R.bool.config_wifiSoftapAutoAppendLowerBandsToBandConfigurationEnabled, true);
@@ -527,7 +543,8 @@
         // Default, new feature doesn't supported
         WifiApConfigStore store = createWifiApConfigStore();
         SoftApConfiguration config = store.getApConfiguration();
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -543,7 +560,8 @@
                 SoftApConfiguration.BAND_2GHZ);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -562,9 +580,9 @@
                 .generateLocalOnlyHotspotConfig(mContext, null, mSoftApCapability);
         verifyDefaultLocalOnlyApConfig(config, TEST_DEFAULT_HOTSPOT_SSID,
                 SoftApConfiguration.BAND_5GHZ);
-
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -583,7 +601,8 @@
                 SoftApConfiguration.BAND_2GHZ);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -607,7 +626,8 @@
                 .build();
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(updatedConfig, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(updatedConfig, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -626,7 +646,8 @@
                 SoftApConfiguration.BAND_2GHZ);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     @Test
@@ -786,12 +807,12 @@
         configBuilder.setSsid(null);
         // Invalid due to null SSID.
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
         // SSID is set, so the config is now valid.
         configBuilder.setSsid("ssid");
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
     }
 
     /**
@@ -806,23 +827,23 @@
         // OPEN
         configBuilder.setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN);
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
         // WPA2
         configBuilder.setPassphrase("somepassword", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
         // WPA3 SAE (should succeed)
         configBuilder.setPassphrase("somepassword", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
         // WPA3 SAE-Transition
         configBuilder.setPassphrase("somepassword",
                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
         if (SdkLevel.isAtLeastT()) {
             // WPA3 OWE-Transition
@@ -830,7 +851,7 @@
                 configBuilder.setPassphrase(null,
                         SoftApConfiguration.SECURITY_TYPE_WPA3_OWE_TRANSITION);
                 assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                        configBuilder.build(), true, mContext));
+                        configBuilder.build(), true, mContext, mWifiNative));
             }
         }
     }
@@ -847,7 +868,7 @@
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(
                 new SoftApConfiguration.Builder()
                 .setSsid(TEST_DEFAULT_HOTSPOT_SSID)
-                .build(), true, mContext));
+                .build(), true, mContext, mWifiNative));
     }
 
     /**
@@ -869,7 +890,7 @@
                 generateRandomString(mRandom.nextInt(maxLen - minLen) + minLen),
                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
     }
 
     @Test
@@ -883,7 +904,7 @@
                 generateRandomString(maxLen + 1),
                 SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
 
     }
 
@@ -903,11 +924,11 @@
                 "測試測試測試測試",
                 SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
         // Disable ascii encodable check
         mResources.setBoolean(R.bool.config_wifiSoftapPassphraseAsciiEncodableCheck, false);
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(
-                configBuilder.build(), true, mContext));
+                configBuilder.build(), true, mContext, mWifiNative));
     }
 
 
@@ -936,7 +957,8 @@
                 SoftApConfiguration.BAND_2GHZ, true);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
     }
 
@@ -954,7 +976,8 @@
                 SoftApConfiguration.BAND_2GHZ, true, true);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -973,7 +996,8 @@
                 SoftApConfiguration.BAND_2GHZ, true, false);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     /**
@@ -997,7 +1021,8 @@
                 SoftApConfiguration.BAND_2GHZ, true, false);
 
         // verify that the config passes the validateApWifiConfiguration check
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
 
@@ -1186,7 +1211,7 @@
             configBuilder.setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE);
         }
         assertFalse(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(),
-                false, mContext));
+                false, mContext, mWifiNative));
     }
 
     /**
@@ -1202,7 +1227,7 @@
             configBuilder.setMacRandomizationSetting(SoftApConfiguration.RANDOMIZATION_NONE);
         }
         assertTrue(WifiApConfigStore.validateApWifiConfiguration(configBuilder.build(),
-                true, mContext));
+                true, mContext, mWifiNative));
     }
 
     @Test
@@ -1211,38 +1236,47 @@
         SoftApConfiguration config = new SoftApConfiguration.Builder(store.getApConfiguration())
                 .setBand(mBand25660G).build();
         // Default is all bands supported.
-        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertTrue(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         mResources.setBoolean(R.bool.config_wifi24ghzSupport, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifiSoftap24ghzSupported, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifi5ghzSupport, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifiSoftap5ghzSupported, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifi6ghzSupport, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifiSoftap6ghzSupported, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifi60ghzSupport, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
 
         setupAllBandsSupported();
         mResources.setBoolean(R.bool.config_wifiSoftap60ghzSupported, false);
-        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext));
+        assertFalse(WifiApConfigStore.validateApWifiConfiguration(config, true, mContext,
+                mWifiNative));
     }
 
     @Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 74e4d5e..99ea3f7 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -1924,6 +1924,101 @@
     }
 
     /**
+     * Verify that the protected WifiEnterpriseConfig fields are set correctly.
+     */
+    @Test
+    public void testWifiEnterpriseConfigProtectedFields() {
+        // Add an external config. Expect the internal config to have the default values.
+        WifiConfiguration externalConfig = WifiConfigurationTestUtil.createEapNetwork();
+        externalConfig.enterpriseConfig.setUserApproveNoCaCert(true);
+        externalConfig.enterpriseConfig.setTofuDialogState(
+                WifiEnterpriseConfig.TOFU_DIALOG_STATE_ACCEPTED);
+
+        NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(externalConfig);
+        WifiConfiguration internalConfig = mWifiConfigManager.getConfiguredNetwork(
+                result.getNetworkId());
+        assertFalse(internalConfig.enterpriseConfig.isUserApproveNoCaCert());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_DIALOG_STATE_UNSPECIFIED,
+                internalConfig.enterpriseConfig.getTofuDialogState());
+
+        // Update using an external config. Expect internal config to retain the default values.
+        result = verifyUpdateNetworkToWifiConfigManager(externalConfig);
+        internalConfig = mWifiConfigManager.getConfiguredNetwork(
+                result.getNetworkId());
+        assertFalse(internalConfig.enterpriseConfig.isUserApproveNoCaCert());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_DIALOG_STATE_UNSPECIFIED,
+                internalConfig.enterpriseConfig.getTofuDialogState());
+
+        // If the internal config's values are updated by the framework, merging
+        // with an external config should not overwrite the internal values.
+        mWifiConfigManager.setUserApproveNoCaCert(externalConfig.networkId, true);
+        mWifiConfigManager.setTofuDialogApproved(externalConfig.networkId, true);
+        externalConfig.enterpriseConfig.setUserApproveNoCaCert(false);
+        externalConfig.enterpriseConfig.setTofuDialogApproved(false);
+
+        result = verifyUpdateNetworkToWifiConfigManager(externalConfig);
+        internalConfig = mWifiConfigManager.getConfiguredNetwork(
+                result.getNetworkId());
+        assertTrue(internalConfig.enterpriseConfig.isUserApproveNoCaCert());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_DIALOG_STATE_ACCEPTED,
+                internalConfig.enterpriseConfig.getTofuDialogState());
+    }
+
+    /**
+     * Verify that the TOFU connection state is set correctly when an Enterprise config is added or
+     * updated.
+     */
+    @Test
+    public void testEnterpriseConfigTofuStateMerge() {
+        long featureSet = WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
+        when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet);
+
+        // If the configuration has never connected, the merged TOFU connection state
+        // should be set based on the latest external configuration.
+        WifiConfiguration config =
+                prepareTofuEapConfig(
+                        WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE);
+        config.enterpriseConfig.enableTrustOnFirstUse(false);
+        NetworkUpdateResult result = addNetworkToWifiConfigManager(config);
+        WifiConfiguration internalConfig =
+                mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_STATE_NOT_ENABLED,
+                internalConfig.enterpriseConfig.getTofuConnectionState());
+
+        // Enabling TOFU in the external config should lead to the Enabled Pre-Connection state.
+        config.enterpriseConfig.enableTrustOnFirstUse(true);
+        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
+        result = updateNetworkToWifiConfigManager(config);
+        internalConfig = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_STATE_ENABLED_PRE_CONNECTION,
+                internalConfig.enterpriseConfig.getTofuConnectionState());
+
+        // Invalid post-connection values in the external config should be ignored,
+        // since external configs should not be setting their own TOFU connection state.
+        config.enterpriseConfig.setTofuConnectionState(
+                WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING);
+        result = updateNetworkToWifiConfigManager(config);
+        internalConfig = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_STATE_ENABLED_PRE_CONNECTION,
+                internalConfig.enterpriseConfig.getTofuConnectionState());
+
+        // Post-connection states in the internal config should always persist.
+        mWifiConfigManager.setTofuPostConnectionState(
+                result.getNetworkId(), WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING);
+        result = updateNetworkToWifiConfigManager(config);
+        internalConfig = mWifiConfigManager.getConfiguredNetwork(result.getNetworkId());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING,
+                internalConfig.enterpriseConfig.getTofuConnectionState());
+    }
+
+    /**
      * Verifies the modification of a single network using
      * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} by passing in nulls
      * in all the publicly exposed fields.
@@ -7270,6 +7365,36 @@
     }
 
     /**
+     * Verify that the protected WifiEnterpriseConfig fields are loaded correctly
+     * from the XML store.
+     */
+    @Test
+    public void testLoadEnterpriseConfigProtectedFields() throws Exception {
+        WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork();
+        config.enterpriseConfig.setUserApproveNoCaCert(true);
+        config.enterpriseConfig.setTofuDialogState(WifiEnterpriseConfig.TOFU_DIALOG_STATE_ACCEPTED);
+        config.enterpriseConfig.setTofuConnectionState(
+                WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING);
+        List<WifiConfiguration> storedConfigs = Arrays.asList(config);
+
+        // Setup xml storage
+        setupStoreDataForRead(storedConfigs, Arrays.asList());
+        assertTrue(mWifiConfigManager.loadFromStore());
+        verify(mWifiConfigStore).read();
+
+        List<WifiConfiguration> retrievedNetworks =
+                mWifiConfigManager.getConfiguredNetworksWithPasswords();
+        assertEquals(1, retrievedNetworks.size());
+        assertTrue(retrievedNetworks.get(0).enterpriseConfig.isUserApproveNoCaCert());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_DIALOG_STATE_ACCEPTED,
+                retrievedNetworks.get(0).enterpriseConfig.getTofuDialogState());
+        assertEquals(
+                WifiEnterpriseConfig.TOFU_STATE_CERT_PINNING,
+                retrievedNetworks.get(0).enterpriseConfig.getTofuConnectionState());
+    }
+
+    /**
      * Verify that updating an existing config to a incompatible type works well.
      */
     @Test
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
index 42f9c6a..0abc488 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationTestUtil.java
@@ -77,6 +77,9 @@
     public static final String[] TEST_WEP_KEYS =
             {"\"WifiTestWep12\"", "\"WifiTestWep34\"",
                     "45342312ab", "45342312ab45342312ab34ac12"};
+    public static final String[] TEST_WEP_KEYS_WITH_NULL = {
+        "\"WifiTestWep12\"", "\"WifiTestWep34\"", "45342312ab45342312ab34ac12", null
+    };
     public static final String TEST_EAP_PASSWORD = "WifiConfigurationTestUtilEapPassword";
     public static final int TEST_WEP_TX_KEY_INDEX = 1;
     public static final String TEST_FQDN = "WifiConfigurationTestUtilFQDN";
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
index dc837eb..794629c 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDialogManagerTest.java
@@ -61,6 +61,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -84,6 +85,9 @@
     @Mock Resources mResources;
     @Mock PowerManager mPowerManager;
     @Mock ActivityManager mActivityManager;
+    @Mock WifiInjector mWifiInjector;
+    @Mock WifiDeviceStateChangeManager mWifiDeviceStateChangeManager;
+    @Captor ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverArgumentCaptor;
     private WifiDialogManager mDialogManager;
 
     @Before
@@ -94,11 +98,15 @@
         when(mWifiContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
         when(mWifiContext.getResources()).thenReturn(mResources);
         when(mPowerManager.isInteractive()).thenReturn(true);
+        when(mWifiInjector.getWifiDeviceStateChangeManager())
+                .thenReturn(mWifiDeviceStateChangeManager);
         doThrow(SecurityException.class).when(mWifiContext).startActivityAsUser(any(), any(),
                 any());
         mDialogManager =
-                new WifiDialogManager(mWifiContext, mWifiThreadRunner, mFrameworkFacade);
+                new WifiDialogManager(mWifiContext, mWifiThreadRunner, mFrameworkFacade, mWifiInjector);
         mDialogManager.enableVerboseLogging(true);
+        verify(mWifiContext).registerReceiver(mBroadcastReceiverArgumentCaptor.capture(), any(),
+                eq(SdkLevel.isAtLeastT() ? Context.RECEIVER_EXPORTED : 0));
     }
 
     private void dispatchMockWifiThreadRunner(WifiThreadRunner wifiThreadRunner) {
@@ -754,11 +762,7 @@
 
         // ACTION_CLOSE_SYSTEM_DIALOGS with EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI should be
         // ignored.
-        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = ArgumentCaptor.forClass(
-                BroadcastReceiver.class);
-        verify(mWifiContext).registerReceiver(broadcastReceiverCaptor.capture(), any(),
-                eq(SdkLevel.isAtLeastT() ? Context.RECEIVER_EXPORTED : 0));
-        broadcastReceiverCaptor.getValue().onReceive(mWifiContext,
+        mBroadcastReceiverArgumentCaptor.getValue().onReceive(mWifiContext,
                 new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
                         .putExtra(WifiManager.EXTRA_CLOSE_SYSTEM_DIALOGS_EXCEPT_WIFI, true));
         dispatchMockWifiThreadRunner(mWifiThreadRunner);
@@ -767,7 +771,7 @@
 
         // ACTION_CLOSE_SYSTEM_DIALOGS due to screen off should be ignored.
         when(mPowerManager.isInteractive()).thenReturn(false);
-        broadcastReceiverCaptor.getValue().onReceive(mWifiContext,
+        mBroadcastReceiverArgumentCaptor.getValue().onReceive(mWifiContext,
                 new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
         dispatchMockWifiThreadRunner(mWifiThreadRunner);
 
@@ -775,7 +779,7 @@
 
         // ACTION_CLOSE_SYSTEM_DIALOGS while screen on should cancel the dialog.
         when(mPowerManager.isInteractive()).thenReturn(true);
-        broadcastReceiverCaptor.getValue().onReceive(mWifiContext,
+        mBroadcastReceiverArgumentCaptor.getValue().onReceive(mWifiContext,
                 new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
         dispatchMockWifiThreadRunner(mWifiThreadRunner);
 
@@ -811,15 +815,13 @@
         launchDialogSynchronous(dialogHandle, TIMEOUT_MILLIS, mWifiThreadRunner);
         verify(window).setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
 
-        // Receive ACTION_SCREEN_OFF.
+        // Receive screen off event.
         when(dialog.isShowing()).thenReturn(true);
-        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor = ArgumentCaptor.forClass(
-                BroadcastReceiver.class);
-        verify(mWifiContext).registerReceiver(broadcastReceiverCaptor.capture(), any(),
-                eq(SdkLevel.isAtLeastT() ? Context.RECEIVER_EXPORTED : 0));
-        broadcastReceiverCaptor.getValue().onReceive(mWifiContext,
-                new Intent(Intent.ACTION_SCREEN_OFF));
-        dispatchMockWifiThreadRunner(mWifiThreadRunner);
+        ArgumentCaptor<WifiDeviceStateChangeManager.StateChangeCallback> callbackArgumentCaptor =
+                ArgumentCaptor.forClass(WifiDeviceStateChangeManager.StateChangeCallback.class);
+        verify(mWifiDeviceStateChangeManager).registerStateChangeCallback(
+                callbackArgumentCaptor.capture());
+        callbackArgumentCaptor.getValue().onScreenStateChanged(false);
 
         // Verify dialog was dismissed and relaunched with window type TYPE_APPLICATION_OVERLAY.
         verify(dialog, never()).cancel();
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 7f2be4b..98fe4b5 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -8693,6 +8693,16 @@
         validateWifiActivityEnergyInfo(infoCaptor.getValue());
     }
 
+    /**
+     * Tests that {@link WifiServiceImpl#getWifiActivityEnergyInfoAsync} throws exception when
+     * listener is null
+     */
+    @Test
+    public void getWifiActivityEnergyInfoWithNullListener() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> mWifiServiceImpl.getWifiActivityEnergyInfoAsync(null));
+    }
+
     @Test
     public void testCarrierConfigChangeUpdateSoftApCapability() throws Exception {
         lenient().when(SubscriptionManager.getActiveDataSubscriptionId())
diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
index 546da0c..88e869a 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
@@ -172,6 +172,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -7013,6 +7014,27 @@
                 WpsInfo.PBC, WifiP2pManager.CONNECTION_REQUEST_ACCEPT);
     }
 
+    /** Verify the failure scenario for setConnectionRequestResult without a saved peer config. */
+    @Test
+    public void testSetConnectionRequestResultFailureWithoutSavedPeerConfig() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt()))
+                .thenReturn(true);
+        when(mWifiPermissionsUtil.checkNearbyDevicesPermission(any(), anyBoolean(), any()))
+                .thenReturn(true);
+        Binder binder = new Binder();
+        mockEnterGroupCreatedState();
+        sendSetConnectionRequestResultMsg(
+                mClientMessenger,
+                MacAddress.fromString(mTestWifiP2pDevice.deviceAddress),
+                WifiP2pManager.CONNECTION_REQUEST_ACCEPT,
+                binder);
+        ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+        verify(mClientHandler).sendMessage(messageCaptor.capture());
+        List<Message> messages = messageCaptor.getAllValues();
+        assertEquals(WifiP2pManager.SET_CONNECTION_REQUEST_RESULT_FAILED, messages.get(0).what);
+    }
+
     /**
      * Verify that deferring pin to the framework works normally.
      */
@@ -7630,4 +7652,130 @@
         verify(mWifiNative, never()).configureEapolIpAddressAllocationParams(anyInt(),
                 anyInt(), anyInt(), anyInt());
     }
+
+    @Test
+    public void testSendP2pConnectionChangedBroadcast() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastT());
+        when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true);
+        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        ArgumentCaptor<String[]> permissionCaptor = ArgumentCaptor.forClass(String[].class);
+        String[] receiverPermissions;
+        int flags = Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT;
+
+        // mock p2p enabled
+        forceP2pEnabled(mClient1);
+        if (!SdkLevel.isAtLeastU()) {
+            receiverPermissions = new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,
+                    android.Manifest.permission.ACCESS_WIFI_STATE};
+            verify(mContext).sendBroadcastWithMultiplePermissions(argThat((Intent intent) -> {
+                WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+                WifiP2pGroup p2pGroup = intent.getParcelableExtra(
+                        WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+                assert p2pInfo != null;
+                return intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)
+                        && intent.getFlags() == Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                        && Objects.isNull(intent.getPackage())
+                        && !p2pInfo.groupFormed && Objects.isNull(p2pGroup);
+            }), permissionCaptor.capture());
+            assertEquals(receiverPermissions, permissionCaptor.getValue());
+        } else {
+            receiverPermissions = new String[]{NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK};
+            flags |= Intent.FLAG_RECEIVER_FOREGROUND;
+            verify(mContext).sendBroadcastWithMultiplePermissions(intentCaptor.capture(),
+                    permissionCaptor.capture());
+            Intent intent = intentCaptor.getValue();
+            assertEquals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION, intent.getAction());
+            assertEquals(flags, intent.getFlags());
+            WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+            WifiP2pGroup p2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+            assert p2pInfo != null;
+            assertFalse(p2pInfo.groupFormed);
+            assertFalse(p2pInfo.isGroupOwner);
+            assertNull(p2pGroup);
+            assertEquals(receiverPermissions, permissionCaptor.getValue());
+        }
+
+        // mock group started
+        WifiP2pGroup group = new WifiP2pGroup();
+        group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT);
+        group.setNetworkName("DIRECT-xy-NEW");
+        group.setOwner(new WifiP2pDevice("thisDeviceMac"));
+        group.setIsGroupOwner(true);
+        group.setInterface(IFACE_NAME_P2P);
+        sendGroupStartedMsg(group);
+        simulateTetherReady();
+
+        // reassign captor again, otherwise captor.getAllValues() will include previous values
+        intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        permissionCaptor = ArgumentCaptor.forClass(String[].class);
+        if (!SdkLevel.isAtLeastU()) {
+            // there are other broadcasts from sendThisDeviceChangedBroadcast() called by
+            // updateThisDevice()
+            verify(mContext, times(6)).sendBroadcastWithMultiplePermissions(intentCaptor.capture(),
+                    permissionCaptor.capture());
+        } else {
+            verify(mContext, times(3)).sendBroadcastWithMultiplePermissions(intentCaptor.capture(),
+                    permissionCaptor.capture());
+        }
+        ArrayList<Intent> intentArrayList = new ArrayList<>();
+        ArrayList<String[]> permissionArrayList = new ArrayList<>();
+        for (int i = 0; i < intentCaptor.getAllValues().size(); i++) {
+            Intent intent = intentCaptor.getAllValues().get(i);
+            if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
+                intentArrayList.add(intent);
+                permissionArrayList.add(permissionCaptor.getAllValues().get(i));
+            }
+        }
+        assertEquals(3, intentArrayList.size());
+        /* Total three WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION broadcasts are as follows.
+         * ----------------------------------------------------------------------------------------
+         * State    p2pInfo.groupFormed    p2pGroup    intent.permission intent.flag intent.package
+         * ----------------------------------------------------------------------------------------
+         * PreU:
+         * P2pEnabledState      :false  null         RECEIVER_PERMISSIONS_FOR_BROADCAST(location ON)
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+         *         null
+         * GroupCreatingState   :false p2pGroup.isGo RECEIVER_PERMISSIONS_FOR_BROADCAST(location ON)
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+         *         null
+         * GroupNegotiationState:true  p2pGroup.isGo android.Manifest.permission.TETHER_PRIVILEGED
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+         *         com.android.networkstack.tethering
+         *
+         * PostU:
+         * P2pEnabledState      : false  null           android.permission.MAINLINE_NETWORK_STACK
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT|Intent.FLAG_RECEIVER_FOREGROUND
+         *         null
+         * GroupCreatingState   : false  p2pGroup.isGo  android.permission.MAINLINE_NETWORK_STACK
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT|Intent.FLAG_RECEIVER_FOREGROUND
+         *         null
+         * GroupNegotiationState: true   p2pGroup.isGo  android.permission.MAINLINE_NETWORK_STACK
+         *         Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT|Intent.FLAG_RECEIVER_FOREGROUND
+         *         com.android.networkstack.tethering
+         */
+        Intent intent = intentArrayList.get(1);
+        assertEquals(flags, intent.getFlags());
+        assertNull(intent.getPackage());
+        WifiP2pInfo p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+        assert p2pInfo != null;
+        assertFalse(p2pInfo.groupFormed);
+        WifiP2pGroup p2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+        assert p2pGroup != null;
+        assertTrue(p2pGroup.isGroupOwner());
+        assertEquals(receiverPermissions, permissionArrayList.get(1));
+
+        intent = intentArrayList.get(2);
+        assertEquals(flags, intent.getFlags());
+        assertNotNull(intent.getPackage());
+        p2pInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
+        assert p2pInfo != null;
+        assertTrue(p2pInfo.groupFormed);
+        p2pGroup = intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
+        assert p2pGroup != null;
+        assertTrue(p2pGroup.isGroupOwner());
+        if (!SdkLevel.isAtLeastU()) {
+            receiverPermissions = new String[]{android.Manifest.permission.TETHER_PRIVILEGED};
+        }
+        assertEquals(receiverPermissions, permissionArrayList.get(2));
+    }
 }
diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
index fc393d3..40f1c53 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wifi.util;
 
+import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_IEEE80211_BE;
+
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE;
+import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -23,6 +28,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -41,6 +47,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiScanner;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import androidx.test.filters.SmallTest;
@@ -49,6 +56,7 @@
 import com.android.server.wifi.SoftApManager;
 import com.android.server.wifi.WifiBaseTest;
 import com.android.server.wifi.WifiNative;
+import com.android.server.wifi.WifiSettingsConfigStore;
 import com.android.server.wifi.coex.CoexManager;
 import com.android.wifi.resources.R;
 
@@ -155,7 +163,10 @@
     @Mock Resources mResources;
     @Mock WifiNative mWifiNative;
     @Mock CoexManager mCoexManager;
+    @Mock WifiSettingsConfigStore mConfigStore;
     private SoftApCapability mCapability;
+    private boolean mApBridgeIfaceCobinationSupported = false;
+    private boolean mApBridgeWithStaIfaceCobinationSupported = false;
     /**
      * Setup test.
      */
@@ -169,11 +180,93 @@
         mCapability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, ALLOWED_2G_CHANS);
         mCapability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, ALLOWED_5G_CHANS);
         mCapability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, ALLOWED_60G_CHANS);
+        when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true);
         when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true);
         when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true);
         when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true);
+        when(mResources.getBoolean(R.bool.config_wifiBridgedSoftApSupported)).thenReturn(true);
+        when(mResources.getBoolean(
+                R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)).thenReturn(true);
         when(mWifiNative.getUsableChannels(anyInt(), anyInt(), anyInt())).thenReturn(null);
+        when(mConfigStore.get(
+                WifiSettingsConfigStore.WIFI_WIPHY_11BE_SUPPORTED)).thenReturn(false);
+        when(mWifiNative.canDeviceSupportCreateTypeCombo(any()))
+                .thenAnswer(answer -> {
+                    SparseArray<Integer> combo = answer.getArgument(0);
+                    if (combo.contentEquals(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                        }})) {
+                        return mApBridgeIfaceCobinationSupported;
+                    }
+                    if (combo.contentEquals(new SparseArray<Integer>() {{
+                            put(HDM_CREATE_IFACE_AP_BRIDGE, 1);
+                            put(HDM_CREATE_IFACE_STA, 1);
+                        }})) {
+                        return mApBridgeWithStaIfaceCobinationSupported;
+                    }
+                    return false;
+                });
+    }
+
+    /**
+     * Verify Bridge AP support when Iface combination for AP bridge is allowed.
+     */
+    @Test
+    public void testIsBridgeApSupportedWhenIfaceCombinationForBridgeIsEnabled() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        mApBridgeIfaceCobinationSupported = true;
+        assertTrue("Bridge AP is not supported even when Combination is allowed.",
+                ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative));
+    }
+
+    /**
+     * Verify Bridge AP support when Iface combination for AP bridge is not allowed.
+     */
+    @Test
+    public void testIsBridgeApSupportedWhenIfaceCombinationForBridgeIsDisabled() throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        mApBridgeIfaceCobinationSupported = false;
+        assertFalse("Bridge AP is supported even when Combination is not allowed.",
+                ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative));
+    }
+
+    /**
+     * Verify Bridge AP + STA support when Iface combination for AP bridge with Sta is allowed.
+     */
+    @Test
+    public void testIsBridgeApWithStaSupportedWhenIfaceCombinationForStaBridgeApIsEnabled()
+            throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        mApBridgeWithStaIfaceCobinationSupported = true;
+        assertTrue("Bridge AP with Sta is not supported even when Combination is allowed.",
+                ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative));
+    }
+
+    /**
+     * Verify Bridge AP + STA support when Iface combination for AP bridge with Sta is not allowed.
+     */
+    @Test
+    public void testIsBridgeApWithStaSupportedWhenIfaceCombinationForStaBridgeApIsDisabled()
+            throws Exception {
+        assumeTrue(SdkLevel.isAtLeastS());
+        mApBridgeWithStaIfaceCobinationSupported = false;
+        assertFalse("Bridge AP with Sta is supported even when Combination is not allowed.",
+                ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative));
+    }
+
+    /**
+     * Verify Bridge AP not supported for pre-S.
+     */
+    @Test
+    public void testIsBridgeApSupportedReturnsFalseForPreS() throws Exception {
+        assumeTrue(!SdkLevel.isAtLeastS());
+        mApBridgeIfaceCobinationSupported = true;
+        mApBridgeWithStaIfaceCobinationSupported = true;
+        assertFalse("Bridge AP is supported even for pre-S platform.",
+                ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative));
+        assertFalse("Bridge AP with Sta is supported even for pre-S platform.",
+                ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative));
     }
 
     /**
@@ -731,7 +824,6 @@
     public void updateApChannelConfigWithAcsDisabledOemConfigured() throws Exception {
         Builder configBuilder = new SoftApConfiguration.Builder();
         configBuilder.setBand(SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_2GHZ);
-        when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getString(R.string.config_wifiSoftap2gChannelList))
                 .thenReturn("6");
         when(mResources.getString(R.string.config_wifiSoftap5gChannelList))
@@ -791,7 +883,6 @@
         int test_max_client = 10;
         capability.setMaxSupportedClients(test_max_client);
 
-        when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getInteger(R.integer.config_wifiHardwareSoftapMaxClientCount))
                 .thenReturn(test_max_client);
         when(mResources.getBoolean(R.bool.config_wifi_softap_acs_supported))
@@ -812,6 +903,23 @@
                 capability);
     }
 
+
+    /**
+     * Verify updating capability from config store.
+     * Force 11BE capa to be true and then try to set it to false
+     * using updateCapabilityFromConfigStore
+     * assert if capability still has 11BE enabled.
+     */
+    @Test
+    public void testSoftApCapabilityInitWithWifiConfiguration() throws Exception {
+        long features = 0;
+        // Forcefully make 11BE as true in capability
+        features |= SOFTAP_FEATURE_IEEE80211_BE;
+        SoftApCapability capability = new SoftApCapability(features);
+        ApConfigUtil.updateCapabilityFromConfigStore(capability, mConfigStore);
+        assertFalse(capability.areFeaturesSupported(SOFTAP_FEATURE_IEEE80211_BE));
+    }
+
     @Test
     public void testConvertInvalidWifiConfigurationToSoftApConfiguration() throws Exception {
         WifiConfiguration wifiConfig = new WifiConfiguration();
@@ -982,7 +1090,6 @@
     public void testUpdateBandInConfigOnFindingUnavailableChannels() throws Exception {
         SoftApConfiguration config;
         SoftApCapability testSoftApCapability = new SoftApCapability(0);
-        when(mContext.getResources()).thenReturn(mResources);
 
         if (SdkLevel.isAtLeastS()) {
             // 6GHz channels not available - {2GHz|6GHz, 5GHz} => {2GHz, 5GHz}
diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java
index 79d9cce..c6c876e 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java
@@ -143,7 +143,9 @@
             throws IOException, XmlPullParserException {
         mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class);
         WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
+        wepNetwork.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS_WITH_NULL;
         for (int i = 0; i < wepNetwork.wepKeys.length; i++) {
+            if (wepNetwork.wepKeys[i] == null) continue;
             EncryptedData encryptedData = new EncryptedData(new byte[]{(byte) i},
                     new byte[]{(byte) i});
             when(mWifiConfigStoreEncryptionUtil.encrypt(wepNetwork.wepKeys[i].getBytes()))
@@ -163,7 +165,9 @@
             throws IOException, XmlPullParserException {
         mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class);
         WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
+        wepNetwork.wepKeys = WifiConfigurationTestUtil.TEST_WEP_KEYS_WITH_NULL;
         for (int i = 0; i < wepNetwork.wepKeys.length; i++) {
+            if (wepNetwork.wepKeys[i] == null) continue;
             when(mWifiConfigStoreEncryptionUtil.encrypt(wepNetwork.wepKeys[i].getBytes()))
                     .thenReturn(null);
         }