Merge "WifiNetworkConfigBuilder: Split into 2 separate builders"
diff --git a/api/current.txt b/api/current.txt
index e7018d2..fa147db 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28949,6 +28949,7 @@
   }
 
   public abstract class NetworkSpecifier {
+    ctor public NetworkSpecifier();
   }
 
   public class ParseException extends java.lang.RuntimeException {
@@ -29972,24 +29973,25 @@
     method @Deprecated public abstract void onSucceeded();
   }
 
-  public class WifiNetworkConfigBuilder {
-    ctor public WifiNetworkConfigBuilder();
-    method public android.net.NetworkSpecifier buildNetworkSpecifier();
-    method public android.net.wifi.WifiNetworkSuggestion buildNetworkSuggestion();
-    method public android.net.wifi.WifiNetworkConfigBuilder setBssid(@NonNull android.net.MacAddress);
-    method public android.net.wifi.WifiNetworkConfigBuilder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
-    method public android.net.wifi.WifiNetworkConfigBuilder setIsAppInteractionRequired();
-    method public android.net.wifi.WifiNetworkConfigBuilder setIsEnhancedOpen();
-    method public android.net.wifi.WifiNetworkConfigBuilder setIsHiddenSsid();
-    method public android.net.wifi.WifiNetworkConfigBuilder setIsMetered();
-    method public android.net.wifi.WifiNetworkConfigBuilder setIsUserInteractionRequired();
-    method public android.net.wifi.WifiNetworkConfigBuilder setPriority(int);
-    method public android.net.wifi.WifiNetworkConfigBuilder setSsid(@NonNull String);
-    method public android.net.wifi.WifiNetworkConfigBuilder setSsidPattern(@NonNull android.os.PatternMatcher);
-    method public android.net.wifi.WifiNetworkConfigBuilder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
-    method public android.net.wifi.WifiNetworkConfigBuilder setWpa2Passphrase(@NonNull String);
-    method public android.net.wifi.WifiNetworkConfigBuilder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
-    method public android.net.wifi.WifiNetworkConfigBuilder setWpa3Passphrase(@NonNull String);
+  public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSpecifier> CREATOR;
+  }
+
+  public static class WifiNetworkSpecifier.Builder {
+    ctor public WifiNetworkSpecifier.Builder();
+    method public android.net.NetworkSpecifier build();
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setBssid(@NonNull android.net.MacAddress);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen();
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setIsHiddenSsid();
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setSsid(@NonNull String);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setSsidPattern(@NonNull android.os.PatternMatcher);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2Passphrase(@NonNull String);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+    method public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3Passphrase(@NonNull String);
   }
 
   public final class WifiNetworkSuggestion implements android.os.Parcelable {
@@ -29998,6 +30000,23 @@
     field public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSuggestion> CREATOR;
   }
 
+  public static class WifiNetworkSuggestion.Builder {
+    ctor public WifiNetworkSuggestion.Builder();
+    method public android.net.wifi.WifiNetworkSuggestion build();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setBssid(@NonNull android.net.MacAddress);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedOpen();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired();
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(int);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2Passphrase(@NonNull String);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+    method public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3Passphrase(@NonNull String);
+  }
+
   public class WpsInfo implements android.os.Parcelable {
     ctor public WpsInfo();
     ctor public WpsInfo(android.net.wifi.WpsInfo);
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index fcfb720..2bc3eb5 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -23,7 +23,6 @@
  * subclasses of this class via other APIs.
  */
 public abstract class NetworkSpecifier {
-    /** @hide */
     public NetworkSpecifier() {}
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 96493de..c50e6a7 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -49,8 +49,9 @@
  * A class representing a configured Wi-Fi network, including the
  * security configuration.
  *
- * @deprecated Use {@link WifiNetworkConfigBuilder} to create {@link NetworkSpecifier} and
- * {@link WifiNetworkSuggestion}. This will become a system use only object in the future.
+ * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and
+ * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This will become a
+ * system use only object in the future.
  */
 @Deprecated
 public class WifiConfiguration implements Parcelable {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e5733ed..289f99d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -947,8 +947,8 @@
     /**
      * Directed broadcast intent action indicating that the device has connected to one of the
      * network suggestions provided by the app. This will be sent post connection to a network
-     * which was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} flag
-     * set.
+     * which was created with {@link WifiNetworkSuggestion.Builder#setIsAppInteractionRequired()}
+     * flag set.
      * <p>
      * Note: The broadcast is sent to the app only if it holds
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
@@ -1171,7 +1171,7 @@
      * of {@link WifiConfiguration} objects.
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1323,7 +1323,7 @@
      *         Returns {@code -1} on failure.
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1358,7 +1358,7 @@
      *         existing network.
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1647,8 +1647,8 @@
      * for a detailed explanation of the parameters.
      * When the device decides to connect to one of the provided network suggestions, platform sends
      * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if
-     * the network was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()}
-     * flag set and the app holds
+     * the network was created with {@link WifiNetworkSuggestion.Builder
+     * #setIsAppInteractionRequired()} flag set and the app holds
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
      *<p>
      * NOTE:
@@ -1835,7 +1835,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1879,7 +1879,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1911,7 +1911,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1934,7 +1934,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1958,7 +1958,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
@@ -1982,7 +1982,7 @@
      * @return {@code true} if the operation succeeded
      *
      * @deprecated
-     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * a) See {@link WifiNetworkSpecifier.Builder#build()} for new
      * mechanism to trigger connection to a Wi-Fi network.
      * b) See {@link #addNetworkSuggestions(List)},
      * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index 52ee742..9d87466 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -124,7 +124,7 @@
      */
     public boolean satisfiesNetworkSpecifier(@NonNull WifiNetworkSpecifier ns) {
         // None of these should be null by construction.
-        // {@link WifiNetworkConfigBuilder} enforces non-null in {@link WifiNetworkSpecifier}.
+        // {@link WifiNetworkSpecifier.Builder} enforces non-null in {@link WifiNetworkSpecifier}.
         // {@link WifiNetworkFactory} ensures non-null in {@link WifiNetworkAgentSpecifier}.
         checkNotNull(ns);
         checkNotNull(ns.ssidPatternMatcher);
diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
deleted file mode 100644
index 42d4393..0000000
--- a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import static com.android.internal.util.Preconditions.checkNotNull;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityThread;
-import android.net.MacAddress;
-import android.net.NetworkRequest;
-import android.net.NetworkSpecifier;
-import android.os.PatternMatcher;
-import android.os.Process;
-import android.text.TextUtils;
-import android.util.Pair;
-
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-/**
- * WifiNetworkConfigBuilder to use for creating Wi-Fi network configuration.
- * <li>See {@link #buildNetworkSpecifier()} for creating a network specifier to use in
- * {@link NetworkRequest}.</li>
- * <li>See {@link #buildNetworkSuggestion()} for creating a network suggestion to use in
- * {@link WifiManager#addNetworkSuggestions(List)}.</li>
- */
-public class WifiNetworkConfigBuilder {
-    private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*";
-    private static final String MATCH_EMPTY_SSID_PATTERN_PATH = "";
-    private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN1 =
-            new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
-    private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN2 =
-            new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.BROADCAST_ADDRESS);
-    private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
-            new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
-    private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK =
-            MacAddress.BROADCAST_ADDRESS;
-    private static final int UNASSIGNED_PRIORITY = -1;
-
-    /**
-     * SSID pattern match specified by the app.
-     */
-    private @Nullable PatternMatcher mSsidPatternMatcher;
-    /**
-     * BSSID pattern match specified by the app.
-     * Pair of <BaseAddress, Mask>.
-     */
-    private @Nullable Pair<MacAddress, MacAddress> mBssidPatternMatcher;
-    /**
-     * Whether this is an OWE network or not.
-     */
-    private boolean mIsEnhancedOpen;
-    /**
-     * Pre-shared key for use with WPA-PSK networks.
-     */
-    private @Nullable String mWpa2PskPassphrase;
-    /**
-     * Pre-shared key for use with WPA3-SAE networks.
-     */
-    private @Nullable String mWpa3SaePassphrase;
-    /**
-     * The enterprise configuration details specifying the EAP method,
-     * certificates and other settings associated with the WPA-EAP networks.
-     */
-    private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
-    /**
-     * The enterprise configuration details specifying the EAP method,
-     * certificates and other settings associated with the SuiteB networks.
-     */
-    private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
-    /**
-     * This is a network that does not broadcast its SSID, so an
-     * SSID-specific probe request must be used for scans.
-     */
-    private boolean mIsHiddenSSID;
-    /**
-     * Whether app needs to log in to captive portal to obtain Internet access.
-     */
-    private boolean mIsAppInteractionRequired;
-    /**
-     * Whether user needs to log in to captive portal to obtain Internet access.
-     */
-    private boolean mIsUserInteractionRequired;
-    /**
-     * Whether this network is metered or not.
-     */
-    private boolean mIsMetered;
-    /**
-     * Priority of this network among other network suggestions provided by the app.
-     * The lower the number, the higher the priority (i.e value of 0 = highest priority).
-     */
-    private int mPriority;
-
-    public WifiNetworkConfigBuilder() {
-        mSsidPatternMatcher = null;
-        mBssidPatternMatcher = null;
-        mIsEnhancedOpen = false;
-        mWpa2PskPassphrase = null;
-        mWpa3SaePassphrase = null;
-        mWpa2EnterpriseConfig = null;
-        mWpa3EnterpriseConfig = null;
-        mIsHiddenSSID = false;
-        mIsAppInteractionRequired = false;
-        mIsUserInteractionRequired = false;
-        mIsMetered = false;
-        mPriority = UNASSIGNED_PRIORITY;
-    }
-
-    /**
-     * Set the unicode SSID match pattern to use for filtering networks from scan results.
-     * <p>
-     * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
-     * <li>Overrides any previous value set using {@link #setSsid(String)} or
-     * {@link #setSsidPattern(PatternMatcher)}.</li>
-     *
-     * @param ssidPattern Instance of {@link PatternMatcher} containing the UTF-8 encoded
-     *                    string pattern to use for matching the network's SSID.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setSsidPattern(@NonNull PatternMatcher ssidPattern) {
-        checkNotNull(ssidPattern);
-        mSsidPatternMatcher = ssidPattern;
-        return this;
-    }
-
-    /**
-     * Set the unicode SSID for the network.
-     * <p>
-     * <li>For network requests ({@link NetworkSpecifier}), built using
-     * {@link #buildNetworkSpecifier}, sets the SSID to use for filtering networks from scan
-     * results. Will only match networks whose SSID is identical to the UTF-8 encoding of the
-     * specified value.</li>
-     * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using
-     * {@link #buildNetworkSuggestion()}, sets the SSID for the network.</li>
-     * <li>Overrides any previous value set using {@link #setSsid(String)} or
-     * {@link #setSsidPattern(PatternMatcher)}.</li>
-     *
-     * @param ssid The SSID of the network. It must be valid Unicode.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     * @throws IllegalArgumentException if the SSID is not valid unicode.
-     */
-    public WifiNetworkConfigBuilder setSsid(@NonNull String ssid) {
-        checkNotNull(ssid);
-        final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder();
-        if (!unicodeEncoder.canEncode(ssid)) {
-            throw new IllegalArgumentException("SSID is not a valid unicode string");
-        }
-        mSsidPatternMatcher = new PatternMatcher(ssid, PatternMatcher.PATTERN_LITERAL);
-        return this;
-    }
-
-    /**
-     * Set the BSSID match pattern to use for filtering networks from scan results.
-     * Will match all networks with BSSID which satisfies the following:
-     * {@code BSSID & mask == baseAddress}.
-     * <p>
-     * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
-     * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
-     * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
-     *
-     * @param baseAddress Base address for BSSID pattern.
-     * @param mask Mask for BSSID pattern.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setBssidPattern(
-            @NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
-        checkNotNull(baseAddress, mask);
-        mBssidPatternMatcher = Pair.create(baseAddress, mask);
-        return this;
-    }
-
-    /**
-     * Set the BSSID to use for filtering networks from scan results. Will only match network whose
-     * BSSID is identical to the specified value.
-     * <p>
-     * <li>For network requests ({@link NetworkSpecifier}), built using
-     * {@link #buildNetworkSpecifier}, sets the BSSID to use for filtering networks from scan
-     * results. Will only match networks whose BSSID is identical to specified value.</li>
-     * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using
-     * {@link #buildNetworkSuggestion()}, sets a specific BSSID for the network suggestion.
-     * If set, only the specified BSSID with the specified SSID will be considered for connection.
-     * If not set, all BSSIDs with the specified SSID will be considered for connection.</li>
-     * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
-     * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
-     *
-     * @param bssid BSSID of the network.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setBssid(@NonNull MacAddress bssid) {
-        checkNotNull(bssid);
-        mBssidPatternMatcher = Pair.create(bssid, MATCH_EXACT_BSSID_PATTERN_MASK);
-        return this;
-    }
-
-    /**
-     * Specifies whether this represents an Enhanced Open (OWE) network.
-     *
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setIsEnhancedOpen() {
-        mIsEnhancedOpen = true;
-        return this;
-    }
-
-    /**
-     * Set the ASCII WPA2 passphrase for this network. Needed for authenticating to
-     * WPA2-PSK networks.
-     *
-     * @param passphrase passphrase of the network.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
-     */
-    public WifiNetworkConfigBuilder setWpa2Passphrase(@NonNull String passphrase) {
-        checkNotNull(passphrase);
-        final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
-        if (!asciiEncoder.canEncode(passphrase)) {
-            throw new IllegalArgumentException("passphrase not ASCII encodable");
-        }
-        mWpa2PskPassphrase = passphrase;
-        return this;
-    }
-
-    /**
-     * Set the ASCII WPA3 passphrase for this network. Needed for authenticating to
-     * WPA3-SAE networks.
-     *
-     * @param passphrase passphrase of the network.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
-     */
-    public WifiNetworkConfigBuilder setWpa3Passphrase(@NonNull String passphrase) {
-        checkNotNull(passphrase);
-        final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
-        if (!asciiEncoder.canEncode(passphrase)) {
-            throw new IllegalArgumentException("passphrase not ASCII encodable");
-        }
-        mWpa3SaePassphrase = passphrase;
-        return this;
-    }
-
-    /**
-     * Set the associated enterprise configuration for this network. Needed for authenticating to
-     * WPA2-EAP networks. See {@link WifiEnterpriseConfig} for description.
-     *
-     * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setWpa2EnterpriseConfig(
-            @NonNull WifiEnterpriseConfig enterpriseConfig) {
-        checkNotNull(enterpriseConfig);
-        mWpa2EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
-        return this;
-    }
-
-    /**
-     * Set the associated enterprise configuration for this network. Needed for authenticating to
-     * WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
-     *
-     * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setWpa3EnterpriseConfig(
-            @NonNull WifiEnterpriseConfig enterpriseConfig) {
-        checkNotNull(enterpriseConfig);
-        mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
-        return this;
-    }
-
-    /**
-     * Specifies whether this represents a hidden network.
-     * <p>
-     * <li>For network requests (see {@link NetworkSpecifier}), built using
-     * {@link #buildNetworkSpecifier}, setting this disallows the usage of
-     * {@link #setSsidPattern(PatternMatcher)} since hidden networks need to be explicitly
-     * probed for.</li>
-     * <li>If not set, defaults to false (i.e not a hidden network).</li>
-     *
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setIsHiddenSsid() {
-        mIsHiddenSSID = true;
-        return this;
-    }
-
-    /**
-     * Specifies whether the app needs to log in to a captive portal to obtain Internet access.
-     * <p>
-     * This will dictate if the directed broadcast
-     * {@link WifiManager#ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} will be sent to the app
-     * after successfully connecting to the network.
-     * Use this for captive portal type networks where the app needs to authenticate the user
-     * before the device can access the network.
-     * <p>
-     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
-     * <li>If not set, defaults to false (i.e no app interaction required).</li>
-     *
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setIsAppInteractionRequired() {
-        mIsAppInteractionRequired = true;
-        return this;
-    }
-
-    /**
-     * Specifies whether the user needs to log in to a captive portal to obtain Internet access.
-     * <p>
-     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
-     * <li>If not set, defaults to false (i.e no user interaction required).</li>
-     *
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setIsUserInteractionRequired() {
-        mIsUserInteractionRequired = true;
-        return this;
-    }
-
-    /**
-     * Specify the priority of this network among other network suggestions provided by the same app
-     * (priorities have no impact on suggestions by different apps). The lower the number, the
-     * higher the priority (i.e value of 0 = highest priority).
-     * <p>
-     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
-     * <li>If not set, defaults to -1 (i.e unassigned priority).</li>
-     *
-     * @param priority Integer number representing the priority among suggestions by the app.
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     * @throws IllegalArgumentException if the priority value is negative.
-     */
-    public WifiNetworkConfigBuilder setPriority(int priority) {
-        if (priority < 0) {
-            throw new IllegalArgumentException("Invalid priority value " + priority);
-        }
-        mPriority = priority;
-        return this;
-    }
-
-    /**
-     * Specifies whether this network is metered.
-     * <p>
-     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
-     * <li>If not set, defaults to false (i.e not metered).</li>
-     *
-     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
-     * method.
-     */
-    public WifiNetworkConfigBuilder setIsMetered() {
-        mIsMetered = true;
-        return this;
-    }
-
-    /**
-     * Set defaults for the various low level credential type fields in the newly created
-     * WifiConfiguration object.
-     *
-     * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
-     * WifiConfiguration)}.
-     *
-     * @param configuration provided WifiConfiguration object.
-     */
-    private static void setDefaultsInWifiConfiguration(@NonNull WifiConfiguration configuration) {
-        configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
-        configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
-        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
-        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
-        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
-    }
-
-    private void setSecurityParamsInWifiConfiguration(@NonNull WifiConfiguration configuration) {
-        if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
-            // WifiConfiguration.preSharedKey needs quotes around ASCII password.
-            configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
-        } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
-            // PMF mandatory for SAE.
-            configuration.requirePMF = true;
-            // WifiConfiguration.preSharedKey needs quotes around ASCII password.
-            configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
-        } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
-            configuration.enterpriseConfig = mWpa2EnterpriseConfig;
-        } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
-            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
-            // TODO (b/113878056): Verify these params once we verify SuiteB configuration.
-            configuration.allowedGroupManagementCiphers.set(
-                    WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
-            configuration.allowedSuiteBCiphers.set(
-                    WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
-            configuration.allowedSuiteBCiphers.set(
-                    WifiConfiguration.SuiteBCipher.ECDHE_RSA);
-            configuration.requirePMF = true;
-            configuration.enterpriseConfig = mWpa3EnterpriseConfig;
-        } else if (mIsEnhancedOpen) { // OWE network
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
-            // PMF mandatory.
-            configuration.requirePMF = true;
-        } else { // Open network
-            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
-        }
-    }
-
-    /**
-     * Helper method to build WifiConfiguration object from the builder.
-     * @return Instance of {@link WifiConfiguration}.
-     */
-    private WifiConfiguration buildWifiConfiguration() {
-        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
-        setDefaultsInWifiConfiguration(wifiConfiguration);
-        // WifiConfiguration.SSID needs quotes around unicode SSID.
-        if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
-            wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
-        }
-        if (mBssidPatternMatcher.second == MATCH_EXACT_BSSID_PATTERN_MASK) {
-            wifiConfiguration.BSSID = mBssidPatternMatcher.first.toString();
-        }
-        setSecurityParamsInWifiConfiguration(wifiConfiguration);
-        wifiConfiguration.hiddenSSID = mIsHiddenSSID;
-        wifiConfiguration.priority = mPriority;
-        wifiConfiguration.meteredOverride =
-                mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
-                           : WifiConfiguration.METERED_OVERRIDE_NONE;
-        return wifiConfiguration;
-    }
-
-    private boolean hasSetAnyPattern() {
-        return mSsidPatternMatcher != null || mBssidPatternMatcher != null;
-    }
-
-    private void setMatchAnyPatternIfUnset() {
-        if (mSsidPatternMatcher == null) {
-            mSsidPatternMatcher = new PatternMatcher(MATCH_ALL_SSID_PATTERN_PATH,
-                    PatternMatcher.PATTERN_SIMPLE_GLOB);
-        }
-        if (mBssidPatternMatcher == null) {
-            mBssidPatternMatcher = MATCH_ALL_BSSID_PATTERN;
-        }
-    }
-
-    private boolean hasSetMatchNonePattern() {
-        if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX
-                && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) {
-            return true;
-        }
-        if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN1)) {
-            return true;
-        }
-        if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN2)) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean hasSetMatchAllPattern() {
-        if ((mSsidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH))
-                && mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) {
-            return true;
-        }
-        return false;
-    }
-
-    private boolean hasSetMatchExactPattern() {
-        // exact ssid match with either match-all bssid or match-exact bssid.
-        if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL
-                && (mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)
-                || mBssidPatternMatcher.second.equals(MATCH_EXACT_BSSID_PATTERN_MASK))) {
-            return true;
-        }
-        return false;
-    }
-
-    private void validateSecurityParams() {
-        int numSecurityTypes = 0;
-        numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
-        numSecurityTypes += !TextUtils.isEmpty(mWpa2PskPassphrase) ? 1 : 0;
-        numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
-        numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
-        numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
-        if (numSecurityTypes > 1) {
-            throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
-                    + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
-                    + " can be invoked for network specifier");
-        }
-    }
-
-    /**
-     * Create a specifier object used to request a Wi-Fi network. The generated
-     * {@link NetworkSpecifier} should be used in
-     * {@link NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} when building
-     * the {@link NetworkRequest}.
-     *<p>
-     * Note: Apps can set a combination of network match params:
-     * <li> SSID Pattern using {@link #setSsidPattern(PatternMatcher)} OR Specific SSID using
-     * {@link #setSsid(String)}. </li>
-     * AND/OR
-     * <li> BSSID Pattern using {@link #setBssidPattern(MacAddress, MacAddress)} OR Specific BSSID
-     * using {@link #setBssid(MacAddress)} </li>
-     * to trigger connection to a network that matches the set params.
-     * The system will find the set of networks matching the request and present the user
-     * with a system dialog which will allow the user to select a specific Wi-Fi network to connect
-     * to or to deny the request.
-     *</p>
-     *
-     * For example:
-     * To connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":
-     * {@code
-     * final NetworkSpecifier specifier =
-     *      new WifiNetworkConfigBuilder()
-     *      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
-     *      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
-     *                       MacAddress.fromString("ff:ff:ff:00:00:00"))
-     *      .buildNetworkSpecifier()
-     * final NetworkRequest request =
-     *      new NetworkRequest.Builder()
-     *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
-     *      .setNetworkSpecifier(specifier)
-     *      .build();
-     * final ConnectivityManager connectivityManager =
-     *      context.getSystemService(Context.CONNECTIVITY_SERVICE);
-     * final NetworkCallback networkCallback = new NetworkCallback() {
-     *      ...
-     *      {@literal @}Override
-     *      void onAvailable(...) {}
-     *      // etc.
-     * };
-     * connectivityManager.requestNetwork(request, networkCallback);
-     * }
-     *
-     * @return Instance of {@link NetworkSpecifier}.
-     * @throws IllegalStateException on invalid params set.
-     */
-    public NetworkSpecifier buildNetworkSpecifier() {
-        if (!hasSetAnyPattern()) {
-            throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/setBssid"
-                    + " should be invoked for specifier");
-        }
-        setMatchAnyPatternIfUnset();
-        if (hasSetMatchNonePattern()) {
-            throw new IllegalStateException("cannot set match-none pattern for specifier");
-        }
-        if (hasSetMatchAllPattern()) {
-            throw new IllegalStateException("cannot set match-all pattern for specifier");
-        }
-        if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) {
-            throw new IllegalStateException("setSsid should also be invoked when "
-                    + "setIsHiddenSsid is invoked for network specifier");
-        }
-        if (mIsAppInteractionRequired || mIsUserInteractionRequired
-                || mPriority != -1 || mIsMetered) {
-            throw new IllegalStateException("none of setIsAppInteractionRequired/"
-                    + "setIsUserInteractionRequired/setPriority/setIsMetered are allowed for "
-                    + "specifier");
-        }
-        validateSecurityParams();
-
-        return new WifiNetworkSpecifier(
-                mSsidPatternMatcher,
-                mBssidPatternMatcher,
-                buildWifiConfiguration(),
-                Process.myUid(),
-                ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
-    }
-
-    /**
-     * Create a network suggestion object use in {@link WifiManager#addNetworkSuggestions(List)}.
-     * See {@link WifiNetworkSuggestion}.
-     *<p>
-     * Note: Apps can set a combination of SSID using {@link #setSsid(String)} and BSSID
-     * using {@link #setBssid(MacAddress)} to provide more fine grained network suggestions to the
-     * platform.
-     * </p>
-     *
-     * For example:
-     * To provide credentials for one open, one WPA2 and one WPA3 network with their
-     * corresponding SSID's:
-     * {@code
-     * final WifiNetworkSuggestion suggestion1 =
-     *      new WifiNetworkConfigBuilder()
-     *      .setSsid("test111111")
-     *      .buildNetworkSuggestion()
-     * final WifiNetworkSuggestion suggestion2 =
-     *      new WifiNetworkConfigBuilder()
-     *      .setSsid("test222222")
-     *      .setWpa2Passphrase("test123456")
-     *      .buildNetworkSuggestion()
-     * final WifiNetworkSuggestion suggestion3 =
-     *      new WifiNetworkConfigBuilder()
-     *      .setSsid("test333333")
-     *      .setWpa3Passphrase("test6789")
-     *      .buildNetworkSuggestion()
-     * final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion> {{
-     *          add(suggestion1);
-     *          add(suggestion2);
-     *          add(suggestion3);
-     *      }};
-     * final WifiManager wifiManager =
-     *      context.getSystemService(Context.WIFI_SERVICE);
-     * wifiManager.addNetworkSuggestions(suggestionsList);
-     * ...
-     * }
-     *
-     * @return Instance of {@link WifiNetworkSuggestion}.
-     * @throws IllegalStateException on invalid params set.
-     */
-    public WifiNetworkSuggestion buildNetworkSuggestion() {
-        if (mSsidPatternMatcher == null) {
-            throw new IllegalStateException("setSsid should be invoked for suggestion");
-        }
-        setMatchAnyPatternIfUnset();
-        if (!hasSetMatchExactPattern()) {
-            throw new IllegalStateException("none of setSsidPattern/setBssidPattern are"
-                    + " allowed for suggestion");
-        }
-        if (hasSetMatchNonePattern()) {
-            throw new IllegalStateException("cannot set match-none for suggestion");
-        }
-        validateSecurityParams();
-
-        return new WifiNetworkSuggestion(
-                buildWifiConfiguration(),
-                mIsAppInteractionRequired,
-                mIsUserInteractionRequired,
-                Process.myUid(),
-                ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
-
-    }
-}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index a5f4675..a69c7a5 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -19,31 +19,466 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityThread;
 import android.net.MacAddress;
 import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.os.Process;
 import android.text.TextUtils;
 import android.util.Pair;
 
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.Objects;
 
 /**
- * Network specifier object used to request a Wi-Fi network. Apps should use the
- * {@link WifiNetworkConfigBuilder} class to create an instance.
- * @hide
+ * Network specifier object used to request a local Wi-Fi network. Apps should use the
+ * {@link WifiNetworkSpecifier.Builder} class to create an instance.
  */
 public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+
+    /**
+     * Builder used to create {@link WifiNetworkSpecifier} objects.
+     */
+    public static class Builder {
+        private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*";
+        private static final String MATCH_EMPTY_SSID_PATTERN_PATH = "";
+        private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN1 =
+                new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
+        private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN2 =
+                new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.BROADCAST_ADDRESS);
+        private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
+                new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+        private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK =
+                MacAddress.BROADCAST_ADDRESS;
+
+        /**
+         * SSID pattern match specified by the app.
+         */
+        private @Nullable PatternMatcher mSsidPatternMatcher;
+        /**
+         * BSSID pattern match specified by the app.
+         * Pair of <BaseAddress, Mask>.
+         */
+        private @Nullable Pair<MacAddress, MacAddress> mBssidPatternMatcher;
+        /**
+         * Whether this is an OWE network or not.
+         */
+        private boolean mIsEnhancedOpen;
+        /**
+         * Pre-shared key for use with WPA-PSK networks.
+         */
+        private @Nullable String mWpa2PskPassphrase;
+        /**
+         * Pre-shared key for use with WPA3-SAE networks.
+         */
+        private @Nullable String mWpa3SaePassphrase;
+        /**
+         * The enterprise configuration details specifying the EAP method,
+         * certificates and other settings associated with the WPA-EAP networks.
+         */
+        private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
+        /**
+         * The enterprise configuration details specifying the EAP method,
+         * certificates and other settings associated with the SuiteB networks.
+         */
+        private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
+        /**
+         * This is a network that does not broadcast its SSID, so an
+         * SSID-specific probe request must be used for scans.
+         */
+        private boolean mIsHiddenSSID;
+
+        public Builder() {
+            mSsidPatternMatcher = null;
+            mBssidPatternMatcher = null;
+            mIsEnhancedOpen = false;
+            mWpa2PskPassphrase = null;
+            mWpa3SaePassphrase = null;
+            mWpa2EnterpriseConfig = null;
+            mWpa3EnterpriseConfig = null;
+            mIsHiddenSSID = false;
+        }
+
+        /**
+         * Set the unicode SSID match pattern to use for filtering networks from scan results.
+         * <p>
+         * <li>Overrides any previous value set using {@link #setSsid(String)} or
+         * {@link #setSsidPattern(PatternMatcher)}.</li>
+         *
+         * @param ssidPattern Instance of {@link PatternMatcher} containing the UTF-8 encoded
+         *                    string pattern to use for matching the network's SSID.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setSsidPattern(@NonNull PatternMatcher ssidPattern) {
+            checkNotNull(ssidPattern);
+            mSsidPatternMatcher = ssidPattern;
+            return this;
+        }
+
+        /**
+         * Set the unicode SSID for the network.
+         * <p>
+         * <li>Sets the SSID to use for filtering networks from scan results. Will only match
+         * networks whose SSID is identical to the UTF-8 encoding of the specified value.</li>
+         * <li>Overrides any previous value set using {@link #setSsid(String)} or
+         * {@link #setSsidPattern(PatternMatcher)}.</li>
+         *
+         * @param ssid The SSID of the network. It must be valid Unicode.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the SSID is not valid unicode.
+         */
+        public Builder setSsid(@NonNull String ssid) {
+            checkNotNull(ssid);
+            final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder();
+            if (!unicodeEncoder.canEncode(ssid)) {
+                throw new IllegalArgumentException("SSID is not a valid unicode string");
+            }
+            mSsidPatternMatcher = new PatternMatcher(ssid, PatternMatcher.PATTERN_LITERAL);
+            return this;
+        }
+
+        /**
+         * Set the BSSID match pattern to use for filtering networks from scan results.
+         * Will match all networks with BSSID which satisfies the following:
+         * {@code BSSID & mask == baseAddress}.
+         * <p>
+         * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
+         * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
+         *
+         * @param baseAddress Base address for BSSID pattern.
+         * @param mask Mask for BSSID pattern.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setBssidPattern(
+                @NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
+            checkNotNull(baseAddress, mask);
+            mBssidPatternMatcher = Pair.create(baseAddress, mask);
+            return this;
+        }
+
+        /**
+         * Set the BSSID to use for filtering networks from scan results. Will only match network
+         * whose BSSID is identical to the specified value.
+         * <p>
+         * <li>Sets the BSSID to use for filtering networks from scan results. Will only match
+         * networks whose BSSID is identical to specified value.</li>
+         * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
+         * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
+         *
+         * @param bssid BSSID of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setBssid(@NonNull MacAddress bssid) {
+            checkNotNull(bssid);
+            mBssidPatternMatcher = Pair.create(bssid, MATCH_EXACT_BSSID_PATTERN_MASK);
+            return this;
+        }
+
+        /**
+         * Specifies whether this represents an Enhanced Open (OWE) network.
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsEnhancedOpen() {
+            mIsEnhancedOpen = true;
+            return this;
+        }
+
+        /**
+         * Set the ASCII WPA2 passphrase for this network. Needed for authenticating to
+         * WPA2-PSK networks.
+         *
+         * @param passphrase passphrase of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+         */
+        public Builder setWpa2Passphrase(@NonNull String passphrase) {
+            checkNotNull(passphrase);
+            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+            if (!asciiEncoder.canEncode(passphrase)) {
+                throw new IllegalArgumentException("passphrase not ASCII encodable");
+            }
+            mWpa2PskPassphrase = passphrase;
+            return this;
+        }
+
+        /**
+         * Set the ASCII WPA3 passphrase for this network. Needed for authenticating to WPA3-SAE
+         * networks.
+         *
+         * @param passphrase passphrase of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+         */
+        public Builder setWpa3Passphrase(@NonNull String passphrase) {
+            checkNotNull(passphrase);
+            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+            if (!asciiEncoder.canEncode(passphrase)) {
+                throw new IllegalArgumentException("passphrase not ASCII encodable");
+            }
+            mWpa3SaePassphrase = passphrase;
+            return this;
+        }
+
+        /**
+         * Set the associated enterprise configuration for this network. Needed for authenticating
+         * to WPA2-EAP networks. See {@link WifiEnterpriseConfig} for description.
+         *
+         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setWpa2EnterpriseConfig(
+                @NonNull WifiEnterpriseConfig enterpriseConfig) {
+            checkNotNull(enterpriseConfig);
+            mWpa2EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+            return this;
+        }
+
+        /**
+         * Set the associated enterprise configuration for this network. Needed for authenticating
+         * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
+         *
+         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setWpa3EnterpriseConfig(
+                @NonNull WifiEnterpriseConfig enterpriseConfig) {
+            checkNotNull(enterpriseConfig);
+            mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+            return this;
+        }
+
+        /**
+         * Specifies whether this represents a hidden network.
+         * <p>
+         * <li>Setting this disallows the usage of {@link #setSsidPattern(PatternMatcher)} since
+         * hidden networks need to be explicitly probed for.</li>
+         * <li>If not set, defaults to false (i.e not a hidden network).</li>
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsHiddenSsid() {
+            mIsHiddenSSID = true;
+            return this;
+        }
+
+
+        /**
+         * Set defaults for the various low level credential type fields in the newly created
+         * WifiConfiguration object.
+         *
+         * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
+         * WifiConfiguration)}.
+         *
+         * @param configuration provided WifiConfiguration object.
+         */
+        private static void setDefaultsInWifiConfiguration(
+                @NonNull WifiConfiguration configuration) {
+            configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+            configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+            configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+        }
+
+        private void setSecurityParamsInWifiConfiguration(
+                @NonNull WifiConfiguration configuration) {
+            if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+                configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
+            } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+                // PMF mandatory for SAE.
+                configuration.requirePMF = true;
+                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+                configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
+            } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                configuration.enterpriseConfig = mWpa2EnterpriseConfig;
+            } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+                configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+                // TODO (b/113878056): Verify these params once we verify SuiteB configuration.
+                configuration.allowedGroupManagementCiphers.set(
+                        WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
+                configuration.allowedSuiteBCiphers.set(
+                        WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
+                configuration.allowedSuiteBCiphers.set(
+                        WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+                configuration.requirePMF = true;
+                configuration.enterpriseConfig = mWpa3EnterpriseConfig;
+            } else if (mIsEnhancedOpen) { // OWE network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
+                // PMF mandatory.
+                configuration.requirePMF = true;
+            } else { // Open network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+            }
+        }
+
+        /**
+         * Helper method to build WifiConfiguration object from the builder.
+         * @return Instance of {@link WifiConfiguration}.
+         */
+        private WifiConfiguration buildWifiConfiguration() {
+            final WifiConfiguration wifiConfiguration = new WifiConfiguration();
+            setDefaultsInWifiConfiguration(wifiConfiguration);
+            // WifiConfiguration.SSID needs quotes around unicode SSID.
+            if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
+                wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
+            }
+            if (mBssidPatternMatcher.second == MATCH_EXACT_BSSID_PATTERN_MASK) {
+                wifiConfiguration.BSSID = mBssidPatternMatcher.first.toString();
+            }
+            setSecurityParamsInWifiConfiguration(wifiConfiguration);
+            wifiConfiguration.hiddenSSID = mIsHiddenSSID;
+            return wifiConfiguration;
+        }
+
+        private boolean hasSetAnyPattern() {
+            return mSsidPatternMatcher != null || mBssidPatternMatcher != null;
+        }
+
+        private void setMatchAnyPatternIfUnset() {
+            if (mSsidPatternMatcher == null) {
+                mSsidPatternMatcher = new PatternMatcher(MATCH_ALL_SSID_PATTERN_PATH,
+                        PatternMatcher.PATTERN_SIMPLE_GLOB);
+            }
+            if (mBssidPatternMatcher == null) {
+                mBssidPatternMatcher = MATCH_ALL_BSSID_PATTERN;
+            }
+        }
+
+        private boolean hasSetMatchNonePattern() {
+            if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX
+                    && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) {
+                return true;
+            }
+            if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN1)) {
+                return true;
+            }
+            if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN2)) {
+                return true;
+            }
+            return false;
+        }
+
+        private boolean hasSetMatchAllPattern() {
+            if ((mSsidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH))
+                    && mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) {
+                return true;
+            }
+            return false;
+        }
+
+        private void validateSecurityParams() {
+            int numSecurityTypes = 0;
+            numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
+            numSecurityTypes += !TextUtils.isEmpty(mWpa2PskPassphrase) ? 1 : 0;
+            numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
+            numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
+            numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
+            if (numSecurityTypes > 1) {
+                throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
+                        + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
+                        + " can be invoked for network specifier");
+            }
+        }
+
+        /**
+         * Create a specifier object used to request a local Wi-Fi network. The generated
+         * {@link NetworkSpecifier} should be used in
+         * {@link NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} when building
+         * the {@link NetworkRequest}. These specifiers can only be used to request a local wifi
+         * network (i.e no internet capability). So, the device will not switch it's default route
+         * to wifi if there are other transports (cellular for example) available.
+         *<p>
+         * Note: Apps can set a combination of network match params:
+         * <li> SSID Pattern using {@link #setSsidPattern(PatternMatcher)} OR Specific SSID using
+         * {@link #setSsid(String)}. </li>
+         * AND/OR
+         * <li> BSSID Pattern using {@link #setBssidPattern(MacAddress, MacAddress)} OR Specific
+         * BSSID using {@link #setBssid(MacAddress)} </li>
+         * to trigger connection to a network that matches the set params.
+         * The system will find the set of networks matching the request and present the user
+         * with a system dialog which will allow the user to select a specific Wi-Fi network to
+         * connect to or to deny the request.
+         *</p>
+         *
+         * For example:
+         * To connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":
+         * {@code
+         * final NetworkSpecifier specifier =
+         *      new Builder()
+         *      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
+         *      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
+         *                       MacAddress.fromString("ff:ff:ff:00:00:00"))
+         *      .buildNetworkSpecifier()
+         * final NetworkRequest request =
+         *      new NetworkRequest.Builder()
+         *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+         *      .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+         *      .setNetworkSpecifier(specifier)
+         *      .build();
+         * final ConnectivityManager connectivityManager =
+         *      context.getSystemService(Context.CONNECTIVITY_SERVICE);
+         * final NetworkCallback networkCallback = new NetworkCallback() {
+         *      ...
+         *      {@literal @}Override
+         *      void onAvailable(...) {}
+         *      // etc.
+         * };
+         * connectivityManager.requestNetwork(request, networkCallback);
+         * }
+         *
+         * @return Instance of {@link NetworkSpecifier}.
+         * @throws IllegalStateException on invalid params set.
+         */
+        public NetworkSpecifier build() {
+            if (!hasSetAnyPattern()) {
+                throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/"
+                        + "setBssid should be invoked for specifier");
+            }
+            setMatchAnyPatternIfUnset();
+            if (hasSetMatchNonePattern()) {
+                throw new IllegalStateException("cannot set match-none pattern for specifier");
+            }
+            if (hasSetMatchAllPattern()) {
+                throw new IllegalStateException("cannot set match-all pattern for specifier");
+            }
+            if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) {
+                throw new IllegalStateException("setSsid should also be invoked when "
+                        + "setIsHiddenSsid is invoked for network specifier");
+            }
+            validateSecurityParams();
+
+            return new WifiNetworkSpecifier(
+                    mSsidPatternMatcher,
+                    mBssidPatternMatcher,
+                    buildWifiConfiguration(),
+                    Process.myUid(),
+                    ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
+        }
+    }
+
     /**
      * SSID pattern match specified by the app.
+     * @hide
      */
     public final PatternMatcher ssidPatternMatcher;
 
     /**
      * BSSID pattern match specified by the app.
      * Pair of <BaseAddress, Mask>.
+     * @hide
      */
     public final Pair<MacAddress, MacAddress> bssidPatternMatcher;
 
@@ -54,6 +489,7 @@
      * WifiConfiguration are not used. Instead we use the {@link #ssidPatternMatcher} &
      * {@link #bssidPatternMatcher} fields embedded directly
      * within {@link WifiNetworkSpecifier}.
+     * @hide
      */
     public final WifiConfiguration wifiConfiguration;
 
@@ -61,18 +497,26 @@
      * The UID of the process initializing this network specifier. Validated by receiver using
      * checkUidIfNecessary() and is used by satisfiedBy() to determine whether the specifier
      * matches the offered network.
+     * @hide
      */
     public final int requestorUid;
 
     /**
      * The package name of the app initializing this network specifier.
+     * @hide
      */
     public final String requestorPackageName;
 
+    /** @hide */
+    public WifiNetworkSpecifier() throws IllegalAccessException {
+        throw new IllegalAccessException("Use the builder to create an instance");
+    }
+
+    /** @hide */
     public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher,
-                 @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher,
-                 @NonNull WifiConfiguration wifiConfiguration,
-                 int requestorUid, @NonNull String requestorPackageName) {
+                                @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher,
+                                @NonNull WifiConfiguration wifiConfiguration,
+                                int requestorUid, @NonNull String requestorPackageName) {
         checkNotNull(ssidPatternMatcher);
         checkNotNull(bssidPatternMatcher);
         checkNotNull(wifiConfiguration);
@@ -123,23 +567,6 @@
     }
 
     @Override
-    public boolean satisfiedBy(NetworkSpecifier other) {
-        if (this == other) {
-            return true;
-        }
-        // Any generic requests should be satisifed by a specific wifi network.
-        if (other == null || other instanceof MatchAllNetworkSpecifier) {
-            return true;
-        }
-        if (other instanceof WifiNetworkAgentSpecifier) {
-            return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this);
-        }
-        // Specific requests are checked for equality although testing for equality of 2 patterns do
-        // not make much sense!
-        return equals(other);
-    }
-
-    @Override
     public int hashCode() {
         return Objects.hash(
                 ssidPatternMatcher.getPath(),
@@ -184,6 +611,25 @@
                 .toString();
     }
 
+    /** @hide */
+    @Override
+    public boolean satisfiedBy(NetworkSpecifier other) {
+        if (this == other) {
+            return true;
+        }
+        // Any generic requests should be satisifed by a specific wifi network.
+        if (other == null || other instanceof MatchAllNetworkSpecifier) {
+            return true;
+        }
+        if (other instanceof WifiNetworkAgentSpecifier) {
+            return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this);
+        }
+        // Specific requests are checked for equality although testing for equality of 2 patterns do
+        // not make much sense!
+        return equals(other);
+    }
+
+    /** @hide */
     @Override
     public void assertValidFromUid(int requestorUid) {
         if (this.requestorUid != requestorUid) {
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 6b05dfc..460c633 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -19,23 +19,449 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityThread;
+import android.net.MacAddress;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.text.TextUtils;
 
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Objects;
 
 /**
  * The Network Suggestion object is used to provide a Wi-Fi network for consideration when
  * auto-connecting to networks. Apps cannot directly create this object, they must use
- * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} to obtain an instance
- * of this object.
+ * {@link WifiNetworkSuggestion.Builder#build()} to obtain an instance of this object.
  *<p>
  * Apps can provide a list of such networks to the platform using
  * {@link WifiManager#addNetworkSuggestions(List)}.
  */
 public final class WifiNetworkSuggestion implements Parcelable {
+
+    /**
+     * Builder used to create {@link WifiNetworkSuggestion} objects.
+     */
+    public static class Builder {
+        private static final int UNASSIGNED_PRIORITY = -1;
+
+        /**
+         * SSID of the network.
+         */
+        private String mSsid;
+        /**
+         * Optional BSSID within the network.
+         */
+        private MacAddress mBssid;
+        /**
+         * Whether this is an OWE network or not.
+         */
+        private boolean mIsEnhancedOpen;
+        /**
+         * Pre-shared key for use with WPA-PSK networks.
+         */
+        private @Nullable String mWpa2PskPassphrase;
+        /**
+         * Pre-shared key for use with WPA3-SAE networks.
+         */
+        private @Nullable String mWpa3SaePassphrase;
+        /**
+         * The enterprise configuration details specifying the EAP method,
+         * certificates and other settings associated with the WPA-EAP networks.
+         */
+        private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
+        /**
+         * The enterprise configuration details specifying the EAP method,
+         * certificates and other settings associated with the SuiteB networks.
+         */
+        private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
+        /**
+         * This is a network that does not broadcast its SSID, so an
+         * SSID-specific probe request must be used for scans.
+         */
+        private boolean mIsHiddenSSID;
+        /**
+         * Whether app needs to log in to captive portal to obtain Internet access.
+         */
+        private boolean mIsAppInteractionRequired;
+        /**
+         * Whether user needs to log in to captive portal to obtain Internet access.
+         */
+        private boolean mIsUserInteractionRequired;
+        /**
+         * Whether this network is metered or not.
+         */
+        private boolean mIsMetered;
+        /**
+         * Priority of this network among other network suggestions provided by the app.
+         * The lower the number, the higher the priority (i.e value of 0 = highest priority).
+         */
+        private int mPriority;
+
+        public Builder() {
+            mSsid = null;
+            mBssid =  null;
+            mIsEnhancedOpen = false;
+            mWpa2PskPassphrase = null;
+            mWpa3SaePassphrase = null;
+            mWpa2EnterpriseConfig = null;
+            mWpa3EnterpriseConfig = null;
+            mIsHiddenSSID = false;
+            mIsAppInteractionRequired = false;
+            mIsUserInteractionRequired = false;
+            mIsMetered = false;
+            mPriority = UNASSIGNED_PRIORITY;
+        }
+
+        /**
+         * Set the unicode SSID for the network.
+         * <p>
+         * <li>Overrides any previous value set using {@link #setSsid(String)}.</li>
+         *
+         * @param ssid The SSID of the network. It must be valid Unicode.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the SSID is not valid unicode.
+         */
+        public Builder setSsid(@NonNull String ssid) {
+            checkNotNull(ssid);
+            final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder();
+            if (!unicodeEncoder.canEncode(ssid)) {
+                throw new IllegalArgumentException("SSID is not a valid unicode string");
+            }
+            mSsid = new String(ssid);
+            return this;
+        }
+
+        /**
+         * Set the BSSID to use for filtering networks from scan results. Will only match network
+         * whose BSSID is identical to the specified value.
+         * <p>
+         * <li Sets a specific BSSID for the network suggestion. If set, only the specified BSSID
+         * with the specified SSID will be considered for connection.
+         * <li>If set, only the specified BSSID with the specified SSID will be considered for
+         * connection.</li>
+         * <li>If not set, all BSSIDs with the specified SSID will be considered for connection.
+         * </li>
+         * <li>Overrides any previous value set using {@link #setBssid(MacAddress)}.</li>
+         *
+         * @param bssid BSSID of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setBssid(@NonNull MacAddress bssid) {
+            checkNotNull(bssid);
+            mBssid = MacAddress.fromBytes(bssid.toByteArray());
+            return this;
+        }
+
+        /**
+         * Specifies whether this represents an Enhanced Open (OWE) network.
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsEnhancedOpen() {
+            mIsEnhancedOpen = true;
+            return this;
+        }
+
+        /**
+         * Set the ASCII WPA2 passphrase for this network. Needed for authenticating to
+         * WPA2-PSK networks.
+         *
+         * @param passphrase passphrase of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+         */
+        public Builder setWpa2Passphrase(@NonNull String passphrase) {
+            checkNotNull(passphrase);
+            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+            if (!asciiEncoder.canEncode(passphrase)) {
+                throw new IllegalArgumentException("passphrase not ASCII encodable");
+            }
+            mWpa2PskPassphrase = passphrase;
+            return this;
+        }
+
+        /**
+         * Set the ASCII WPA3 passphrase for this network. Needed for authenticating to WPA3-SAE
+         * networks.
+         *
+         * @param passphrase passphrase of the network.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+         */
+        public Builder setWpa3Passphrase(@NonNull String passphrase) {
+            checkNotNull(passphrase);
+            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+            if (!asciiEncoder.canEncode(passphrase)) {
+                throw new IllegalArgumentException("passphrase not ASCII encodable");
+            }
+            mWpa3SaePassphrase = passphrase;
+            return this;
+        }
+
+        /**
+         * Set the associated enterprise configuration for this network. Needed for authenticating
+         * to WPA2-EAP networks. See {@link WifiEnterpriseConfig} for description.
+         *
+         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setWpa2EnterpriseConfig(
+                @NonNull WifiEnterpriseConfig enterpriseConfig) {
+            checkNotNull(enterpriseConfig);
+            mWpa2EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+            return this;
+        }
+
+        /**
+         * Set the associated enterprise configuration for this network. Needed for authenticating
+         * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
+         *
+         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setWpa3EnterpriseConfig(
+                @NonNull WifiEnterpriseConfig enterpriseConfig) {
+            checkNotNull(enterpriseConfig);
+            mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+            return this;
+        }
+
+        /**
+         * Specifies whether this represents a hidden network.
+         * <p>
+         * <li>If not set, defaults to false (i.e not a hidden network).</li>
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsHiddenSsid() {
+            mIsHiddenSSID = true;
+            return this;
+        }
+
+        /**
+         * Specifies whether the app needs to log in to a captive portal to obtain Internet access.
+         * <p>
+         * This will dictate if the directed broadcast
+         * {@link WifiManager#ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} will be sent to the
+         * app after successfully connecting to the network.
+         * Use this for captive portal type networks where the app needs to authenticate the user
+         * before the device can access the network.
+         * <p>
+         * <li>If not set, defaults to false (i.e no app interaction required).</li>
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsAppInteractionRequired() {
+            mIsAppInteractionRequired = true;
+            return this;
+        }
+
+        /**
+         * Specifies whether the user needs to log in to a captive portal to obtain Internet access.
+         * <p>
+         * <li>If not set, defaults to false (i.e no user interaction required).</li>
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsUserInteractionRequired() {
+            mIsUserInteractionRequired = true;
+            return this;
+        }
+
+        /**
+         * Specify the priority of this network among other network suggestions provided by the same
+         * app (priorities have no impact on suggestions by different apps). The lower the number,
+         * the higher the priority (i.e value of 0 = highest priority).
+         * <p>
+         * <li>If not set, defaults to -1 (i.e unassigned priority).</li>
+         *
+         * @param priority Integer number representing the priority among suggestions by the app.
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         * @throws IllegalArgumentException if the priority value is negative.
+         */
+        public Builder setPriority(int priority) {
+            if (priority < 0) {
+                throw new IllegalArgumentException("Invalid priority value " + priority);
+            }
+            mPriority = priority;
+            return this;
+        }
+
+        /**
+         * Specifies whether this network is metered.
+         * <p>
+         * <li>If not set, defaults to false (i.e not metered).</li>
+         *
+         * @return Instance of {@link Builder} to enable chaining of the builder method.
+         */
+        public Builder setIsMetered() {
+            mIsMetered = true;
+            return this;
+        }
+
+        /**
+         * Set defaults for the various low level credential type fields in the newly created
+         * WifiConfiguration object.
+         *
+         * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
+         * WifiConfiguration)}.
+         *
+         * @param configuration provided WifiConfiguration object.
+         */
+        private static void setDefaultsInWifiConfiguration(
+                @NonNull WifiConfiguration configuration) {
+            configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+            configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+            configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+            configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+        }
+
+        private void setSecurityParamsInWifiConfiguration(
+                @NonNull WifiConfiguration configuration) {
+            if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+                configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
+            } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
+                // PMF mandatory for SAE.
+                configuration.requirePMF = true;
+                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+                configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
+            } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+                configuration.enterpriseConfig = mWpa2EnterpriseConfig;
+            } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+                configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+                // TODO (b/113878056): Verify these params once we verify SuiteB configuration.
+                configuration.allowedGroupManagementCiphers.set(
+                        WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
+                configuration.allowedSuiteBCiphers.set(
+                        WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
+                configuration.allowedSuiteBCiphers.set(
+                        WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+                configuration.requirePMF = true;
+                configuration.enterpriseConfig = mWpa3EnterpriseConfig;
+            } else if (mIsEnhancedOpen) { // OWE network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
+                // PMF mandatory.
+                configuration.requirePMF = true;
+            } else { // Open network
+                configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+            }
+        }
+
+        /**
+         * Helper method to build WifiConfiguration object from the builder.
+         * @return Instance of {@link WifiConfiguration}.
+         */
+        private WifiConfiguration buildWifiConfiguration() {
+            final WifiConfiguration wifiConfiguration = new WifiConfiguration();
+            setDefaultsInWifiConfiguration(wifiConfiguration);
+            // WifiConfiguration.SSID needs quotes around unicode SSID.
+            wifiConfiguration.SSID = "\"" + mSsid + "\"";
+            if (mBssid != null) {
+                wifiConfiguration.BSSID = mBssid.toString();
+            }
+
+            setSecurityParamsInWifiConfiguration(wifiConfiguration);
+
+            wifiConfiguration.hiddenSSID = mIsHiddenSSID;
+            wifiConfiguration.priority = mPriority;
+            wifiConfiguration.meteredOverride =
+                    mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
+                            : WifiConfiguration.METERED_OVERRIDE_NONE;
+            return wifiConfiguration;
+        }
+
+        private void validateSecurityParams() {
+            int numSecurityTypes = 0;
+            numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
+            numSecurityTypes += !TextUtils.isEmpty(mWpa2PskPassphrase) ? 1 : 0;
+            numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
+            numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
+            numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
+            if (numSecurityTypes > 1) {
+                throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
+                        + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
+                        + " can be invoked for network specifier");
+            }
+        }
+
+        /**
+         * Create a network suggestion object use in
+         * {@link WifiManager#addNetworkSuggestions(List)}.
+         *
+         * See {@link WifiNetworkSuggestion}.
+         *<p>
+         * Note: Apps can set a combination of SSID using {@link #setSsid(String)} and BSSID
+         * using {@link #setBssid(MacAddress)} to provide more fine grained network suggestions to
+         * the platform.
+         * </p>
+         *
+         * For example:
+         * To provide credentials for one open, one WPA2 and one WPA3 network with their
+         * corresponding SSID's:
+         * {@code
+         * final WifiNetworkSuggestion suggestion1 =
+         *      new Builder()
+         *      .setSsid("test111111")
+         *      .buildNetworkSuggestion()
+         * final WifiNetworkSuggestion suggestion2 =
+         *      new Builder()
+         *      .setSsid("test222222")
+         *      .setWpa2Passphrase("test123456")
+         *      .buildNetworkSuggestion()
+         * final WifiNetworkSuggestion suggestion3 =
+         *      new Builder()
+         *      .setSsid("test333333")
+         *      .setWpa3Passphrase("test6789")
+         *      .buildNetworkSuggestion()
+         * final List<WifiNetworkSuggestion> suggestionsList =
+         *      new ArrayList<WifiNetworkSuggestion> {{
+         *          add(suggestion1);
+         *          add(suggestion2);
+         *          add(suggestion3);
+         *      }};
+         * final WifiManager wifiManager =
+         *      context.getSystemService(Context.WIFI_SERVICE);
+         * wifiManager.addNetworkSuggestions(suggestionsList);
+         * ...
+         * }
+         *
+         * @return Instance of {@link WifiNetworkSuggestion}.
+         * @throws IllegalStateException on invalid params set.
+         */
+        public WifiNetworkSuggestion build() {
+            if (mSsid == null) {
+                throw new IllegalStateException("setSsid should be invoked for suggestion");
+            }
+            if (TextUtils.isEmpty(mSsid)) {
+                throw new IllegalStateException("invalid ssid for suggestion");
+            }
+            if (mBssid != null
+                    && (mBssid.equals(MacAddress.BROADCAST_ADDRESS)
+                    || mBssid.equals(MacAddress.ALL_ZEROS_ADDRESS))) {
+                throw new IllegalStateException("invalid bssid for suggestion");
+            }
+            validateSecurityParams();
+
+            return new WifiNetworkSuggestion(
+                    buildWifiConfiguration(),
+                    mIsAppInteractionRequired,
+                    mIsUserInteractionRequired,
+                    Process.myUid(),
+                    ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
+        }
+    }
+
     /**
      * Network configuration for the provided network.
      * @hide
@@ -67,6 +493,15 @@
     public final String suggestorPackageName;
 
     /** @hide */
+    public WifiNetworkSuggestion() {
+        this.wifiConfiguration = null;
+        this.isAppInteractionRequired = false;
+        this.isUserInteractionRequired = false;
+        this.suggestorUid = -1;
+        this.suggestorPackageName = null;
+    }
+
+    /** @hide */
     public WifiNetworkSuggestion(@NonNull WifiConfiguration wifiConfiguration,
                                  boolean isAppInteractionRequired,
                                  boolean isUserInteractionRequired,
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
deleted file mode 100644
index dd6e2c9..0000000
--- a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi;
-
-import static android.os.PatternMatcher.PATTERN_LITERAL;
-import static android.os.PatternMatcher.PATTERN_PREFIX;
-import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import android.net.MacAddress;
-import android.net.NetworkSpecifier;
-import android.os.PatternMatcher;
-import android.os.Process;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.WifiNetworkConfigBuilder}.
- */
-@SmallTest
-public class WifiNetworkConfigBuilderTest {
-    private static final String TEST_SSID = "Test123";
-    private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
-    private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
-    private static final String TEST_BSSID = "12:12:12:12:12:12";
-    private static final String TEST_PRESHARED_KEY = "Test123";
-
-    /**
-     * Validate correctness of WifiNetworkSpecifier object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for open network with SSID pattern.
-     */
-    @Test
-    public void testWifiNetworkSpecifierBuilderForOpenNetworkWithSsidPattern() {
-        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
-                .buildNetworkSpecifier();
-
-        assertTrue(specifier instanceof WifiNetworkSpecifier);
-        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
-
-        assertEquals(Process.myUid(), wifiNetworkSpecifier.requestorUid);
-        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
-        assertEquals(PATTERN_PREFIX, wifiNetworkSpecifier.ssidPatternMatcher.getType());
-        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.first);
-        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.second);
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.NONE));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSpecifier object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for WPA_PSK network with BSSID
-     * pattern.
-     */
-    @Test
-    public void testWifiNetworkSpecifierBuilderForWpa2PskNetworkWithBssidPattern() {
-        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
-                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
-                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
-                .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .buildNetworkSpecifier();
-
-        assertTrue(specifier instanceof WifiNetworkSpecifier);
-        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
-
-        assertEquals(".*", wifiNetworkSpecifier.ssidPatternMatcher.getPath());
-        assertEquals(PATTERN_SIMPLE_GLOB, wifiNetworkSpecifier.ssidPatternMatcher.getType());
-        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
-                wifiNetworkSpecifier.bssidPatternMatcher.first);
-        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_MASK),
-                wifiNetworkSpecifier.bssidPatternMatcher.second);
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
-        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
-                wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSpecifier object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for WPA_EAP network with
-     * SSID and BSSID pattern.
-     */
-    @Test
-    public void testWifiNetworkSpecifierBuilderForWpa2EapHiddenNetworkWithSsidAndBssid() {
-        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
-        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
-        enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
-
-        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setBssid(MacAddress.fromString(TEST_BSSID))
-                .setWpa2EnterpriseConfig(enterpriseConfig)
-                .setIsHiddenSsid()
-                .buildNetworkSpecifier();
-
-        assertTrue(specifier instanceof WifiNetworkSpecifier);
-        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
-
-        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
-        assertEquals(PATTERN_LITERAL, wifiNetworkSpecifier.ssidPatternMatcher.getType());
-        assertEquals(MacAddress.fromString(TEST_BSSID),
-                wifiNetworkSpecifier.bssidPatternMatcher.first);
-        assertEquals(MacAddress.BROADCAST_ADDRESS,
-                wifiNetworkSpecifier.bssidPatternMatcher.second);
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.WPA_EAP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.IEEE8021X));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
-                .get(WifiConfiguration.Protocol.RSN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
-                .get(WifiConfiguration.AuthAlgorithm.OPEN));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
-                .get(WifiConfiguration.PairwiseCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.CCMP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.TKIP));
-        assertTrue(wifiNetworkSpecifier.wifiConfiguration.hiddenSSID);
-        assertEquals(enterpriseConfig.getEapMethod(),
-                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getEapMethod());
-        assertEquals(enterpriseConfig.getPhase2Method(),
-                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method());
-    }
-
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#setSsid(String)} throws an exception
-     * when the string is not Unicode.
-     */
-    @Test(expected = IllegalArgumentException.class)
-    public void testSetSsidWithNonUnicodeString() {
-        new WifiNetworkConfigBuilder()
-                .setSsid("\ud800")
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#setWpa2Passphrase(String)} throws an exception
-     * when the string is not ASCII encodable.
-     */
-    @Test(expected = IllegalArgumentException.class)
-    public void testSetWpa2PasphraseWithNonAsciiString() {
-        new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setWpa2Passphrase("salvē")
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when neither SSID nor BSSID patterns were set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithNoSsidAndBssidPattern() {
-        new WifiNetworkConfigBuilder().buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-all SSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern1() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB))
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-all SSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern2() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(".*", PatternMatcher.PATTERN_ADVANCED_GLOB))
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-all SSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern3() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_PREFIX))
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-all BSSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchAllBssidPattern() {
-        new WifiNetworkConfigBuilder()
-                .setBssidPattern(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-none SSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern1() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_LITERAL))
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-none SSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern2() {
-        new WifiNetworkConfigBuilder()
-                .setSsid("")
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-none BSSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern1() {
-        new WifiNetworkConfigBuilder()
-                .setBssidPattern(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-none BSSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern2() {
-        new WifiNetworkConfigBuilder()
-                .setBssid(MacAddress.BROADCAST_ADDRESS)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when match-none BSSID pattern is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern3() {
-        new WifiNetworkConfigBuilder()
-                .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when SSID pattern is set for hidden network.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithBssidMatchPatternForHiddenNetwork() {
-        new WifiNetworkConfigBuilder()
-                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
-                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
-                .setIsHiddenSsid()
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when both {@link WifiNetworkConfigBuilder#setWpa2Passphrase(String)} and
-     * {@link WifiNetworkConfigBuilder#setWpa2EnterpriseConfig(WifiEnterpriseConfig)} are invoked.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithBothWpa2PasphraseAndEnterpriseConfig() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when SSID pattern is set for hidden network.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithSsidMatchPatternForHiddenNetwork() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_PREFIX))
-                .setIsHiddenSsid()
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithRequiredAppInteraction() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setIsAppInteractionRequired()
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setIsUserInteractionRequired()} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithRequiredUserInteraction() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setIsUserInteractionRequired()
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setPriority(int)} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithSetPriority() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setPriority(4)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setIsMetered()} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithMetered() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setIsMetered()
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for Open network which requires
-     * app interaction.
-     */
-    @Test
-    public void testWifiNetworkSuggestionBuilderForOpenNetworkWithReqAppInteraction() {
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setIsAppInteractionRequired()
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.NONE));
-        assertTrue(suggestion.isAppInteractionRequired);
-        assertFalse(suggestion.isUserInteractionRequired);
-        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
-                suggestion.wifiConfiguration.meteredOverride);
-        assertEquals(-1, suggestion.wifiConfiguration.priority);
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for WPA_EAP network which requires
-     * app interaction and has a priority of zero set.
-     */
-    @Test
-    public void
-            testWifiNetworkSuggestionBuilderForWpa2EapNetworkWithPriorityAndReqAppInteraction() {
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setIsAppInteractionRequired()
-                .setPriority(0)
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
-        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
-                suggestion.wifiConfiguration.preSharedKey);
-        assertTrue(suggestion.isAppInteractionRequired);
-        assertFalse(suggestion.isUserInteractionRequired);
-        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
-                suggestion.wifiConfiguration.meteredOverride);
-        assertEquals(0, suggestion.wifiConfiguration.priority);
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for WPA_PSK network which requires
-     * user interaction and is metered.
-     */
-    @Test
-    public void
-            testWifiNetworkSuggestionBuilderForWpa2PskNetworkWithMeteredAndReqUserInteraction() {
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setIsUserInteractionRequired()
-                .setIsMetered()
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
-        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
-                suggestion.wifiConfiguration.preSharedKey);
-        assertFalse(suggestion.isAppInteractionRequired);
-        assertTrue(suggestion.isUserInteractionRequired);
-        assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED,
-                suggestion.wifiConfiguration.meteredOverride);
-        assertEquals(-1, suggestion.wifiConfiguration.priority);
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for OWE network.
-     */
-    @Test
-    public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetworkWithBssid() {
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setBssid(MacAddress.fromString(TEST_BSSID))
-                .setIsEnhancedOpen()
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.OWE));
-        assertNull(suggestion.wifiConfiguration.preSharedKey);
-        assertTrue(suggestion.wifiConfiguration.requirePMF);
-    }
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for SAE network.
-     */
-    @Test
-    public void testWifiNetworkSuggestionBuilderForWpa3PskNetwork() {
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.SAE));
-        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
-                suggestion.wifiConfiguration.preSharedKey);
-        assertTrue(suggestion.wifiConfiguration.requirePMF);
-    }
-
-
-    /**
-     * Validate correctness of WifiNetworkSuggestion object created by
-     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for SuiteB network.
-     */
-    @Test
-    public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
-        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
-        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
-        enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
-
-        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setWpa3EnterpriseConfig(enterpriseConfig)
-                .buildNetworkSuggestion();
-
-        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
-        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
-                .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
-        assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
-                .get(WifiConfiguration.GroupCipher.GCMP_256));
-        assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers
-                .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
-        assertTrue(suggestion.wifiConfiguration.allowedSuiteBCiphers
-                .get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA));
-        assertTrue(suggestion.wifiConfiguration.allowedSuiteBCiphers
-                .get(WifiConfiguration.SuiteBCipher.ECDHE_RSA));
-        assertTrue(suggestion.wifiConfiguration.requirePMF);
-        assertNull(suggestion.wifiConfiguration.preSharedKey);
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setSsidPattern(PatternMatcher)} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithSsidPattern() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithBssidPattern() {
-        new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setBssidPattern(MacAddress.fromString(TEST_BSSID),
-                        MacAddress.fromString(TEST_BSSID))
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithNoSsid() {
-        new WifiNetworkConfigBuilder()
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setSsid(String)} is invoked with an invalid value.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithInvalidSsid() {
-        new WifiNetworkConfigBuilder()
-                .setSsid("")
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithInvalidBroadcastBssid() {
-        new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setBssid(MacAddress.BROADCAST_ADDRESS)
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
-     * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSuggestionBuilderWithInvalidAllZeroBssid() {
-        new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#setPriority(int)} throws an exception
-     * when the value is negative.
-     */
-    @Test(expected = IllegalArgumentException.class)
-    public void testWifiNetworkSuggestionBuilderWithInvalidPriority() {
-        new WifiNetworkConfigBuilder()
-                .setSsid(TEST_SSID)
-                .setPriority(-1)
-                .buildNetworkSuggestion();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when both {@link WifiNetworkConfigBuilder#setWpa2Passphrase(String)} and
-     * {@link WifiNetworkConfigBuilder#setWpa3Passphrase(String)} are invoked.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithBothWpa2PasphraseAndWpa3Passphrase() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setWpa2Passphrase(TEST_PRESHARED_KEY)
-                .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when both {@link WifiNetworkConfigBuilder#setWpa3Passphrase(String)} and
-     * {@link WifiNetworkConfigBuilder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)} are invoked.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnterprise() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
-                .buildNetworkSpecifier();
-    }
-
-    /**
-     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
-     * when both {@link WifiNetworkConfigBuilder#setWpa3Passphrase(String)} and
-     * {@link WifiNetworkConfigBuilder#setIsEnhancedOpen(} are invoked.
-     */
-    @Test(expected = IllegalStateException.class)
-    public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnhancedOpen() {
-        new WifiNetworkConfigBuilder()
-                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
-                .setWpa3Passphrase(TEST_PRESHARED_KEY)
-                .setIsEnhancedOpen()
-                .buildNetworkSpecifier();
-    }
-}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
index fce247f..bef33b7 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -17,6 +17,8 @@
 package android.net.wifi;
 
 import static android.os.PatternMatcher.PATTERN_LITERAL;
+import static android.os.PatternMatcher.PATTERN_PREFIX;
+import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -24,8 +26,10 @@
 
 import android.net.MacAddress;
 import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkSpecifier;
 import android.os.Parcel;
 import android.os.PatternMatcher;
+import android.os.Process;
 import android.util.Pair;
 
 import androidx.test.filters.SmallTest;
@@ -42,9 +46,343 @@
     private static final String TEST_SSID = "Test123";
     private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
     private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
+    private static final String TEST_BSSID = "12:12:12:12:12:12";
     private static final String TEST_PRESHARED_KEY = "\"Test123\"";
 
     /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkSpecifier.Builder#build()} for open network with SSID pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForOpenNetworkWithSsidPattern() {
+        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
+                .build();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(Process.myUid(), wifiNetworkSpecifier.requestorUid);
+        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_PREFIX, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.NONE));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkSpecifier.Builder#build()} for WPA_PSK network with BSSID
+     * pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForWpa2PskNetworkWithBssidPattern() {
+        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .build();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(".*", wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_SIMPLE_GLOB, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_MASK),
+                wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkSpecifier.Builder#build()} for WPA_EAP network with
+     * SSID and BSSID pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForWpa2EapHiddenNetworkWithSsidAndBssid() {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+        enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+
+        NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.fromString(TEST_BSSID))
+                .setWpa2EnterpriseConfig(enterpriseConfig)
+                .setIsHiddenSsid()
+                .build();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_LITERAL, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.fromString(TEST_BSSID),
+                wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.BROADCAST_ADDRESS,
+                wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.hiddenSSID);
+        assertEquals(enterpriseConfig.getEapMethod(),
+                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getEapMethod());
+        assertEquals(enterpriseConfig.getPhase2Method(),
+                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method());
+    }
+
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#setSsid(String)} throws an exception
+     * when the string is not Unicode.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSpecifierBuilderSetSsidWithNonUnicodeString() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsid("\ud800")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#setWpa2Passphrase(String)} throws an exception
+     * when the string is not ASCII encodable.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSpecifierSetWpa2PasphraseWithNonAsciiString() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase("salvē")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when neither SSID nor BSSID patterns were set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithNoSsidAndBssidPattern() {
+        new WifiNetworkSpecifier.Builder().build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern1() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(".*", PATTERN_SIMPLE_GLOB))
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern2() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(".*", PatternMatcher.PATTERN_ADVANCED_GLOB))
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern3() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher("", PATTERN_PREFIX))
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-all BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllBssidPattern() {
+        new WifiNetworkSpecifier.Builder()
+                .setBssidPattern(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-none SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern1() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_LITERAL))
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-none SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern2() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsid("")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-none BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern1() {
+        new WifiNetworkSpecifier.Builder()
+                .setBssidPattern(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-none BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern2() {
+        new WifiNetworkSpecifier.Builder()
+                .setBssid(MacAddress.BROADCAST_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when match-none BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern3() {
+        new WifiNetworkSpecifier.Builder()
+                .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when SSID pattern is set for hidden network.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBssidMatchPatternForHiddenNetwork() {
+        new WifiNetworkSpecifier.Builder()
+                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
+                .setIsHiddenSsid()
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSpecifier.Builder#setWpa2Passphrase(String)} and
+     * {@link WifiNetworkSpecifier.Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig)} are
+     * invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBothWpa2PasphraseAndEnterpriseConfig() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when SSID pattern is set for hidden network.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithSsidMatchPatternForHiddenNetwork() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
+                .setIsHiddenSsid()
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSpecifier.Builder#setWpa2Passphrase(String)} and
+     * {@link WifiNetworkSpecifier.Builder#setWpa3Passphrase(String)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBothWpa2PasphraseAndWpa3Passphrase() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSpecifier.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSpecifier.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)} are
+     * invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnterprise() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSpecifier.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSpecifier.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSpecifier.Builder#setIsEnhancedOpen()} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBothWpa3PasphraseAndEnhancedOpen() {
+        new WifiNetworkSpecifier.Builder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setIsEnhancedOpen()
+                .build();
+    }
+
+    /**
      * Validate that parcel marshalling/unmarshalling works
      */
     @Test
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 5f76055..05ee22c 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -18,7 +18,9 @@
 
 import static org.junit.Assert.*;
 
+import android.net.MacAddress;
 import android.os.Parcel;
+import android.os.Process;
 
 import androidx.test.filters.SmallTest;
 
@@ -36,6 +38,279 @@
     private static final String TEST_SSID = "\"Test123\"";
     private static final String TEST_BSSID = "12:12:12:12:12:12";
     private static final String TEST_SSID_1 = "\"Test1234\"";
+    private static final String TEST_PRESHARED_KEY = "Test123";
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for Open network which requires
+     * app interaction.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForOpenNetworkWithReqAppInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setIsAppInteractionRequired()
+                .build();
+
+        assertEquals(Process.myUid(), suggestion.suggestorUid);
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.NONE));
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertFalse(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(-1, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for WPA_EAP network which requires
+     * app interaction and has a priority of zero set.
+     */
+    @Test
+    public void
+            testWifiNetworkSuggestionBuilderForWpa2EapNetworkWithPriorityAndReqAppInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setIsAppInteractionRequired()
+                .setPriority(0)
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                suggestion.wifiConfiguration.preSharedKey);
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertFalse(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(0, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for WPA_PSK network which requires
+     * user interaction and is metered.
+     */
+    @Test
+    public void
+            testWifiNetworkSuggestionBuilderForWpa2PskNetworkWithMeteredAndReqUserInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setIsUserInteractionRequired()
+                .setIsMetered()
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                suggestion.wifiConfiguration.preSharedKey);
+        assertFalse(suggestion.isAppInteractionRequired);
+        assertTrue(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(-1, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for OWE network.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetworkWithBssid() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.fromString(TEST_BSSID))
+                .setIsEnhancedOpen()
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.OWE));
+        assertNull(suggestion.wifiConfiguration.preSharedKey);
+        assertTrue(suggestion.wifiConfiguration.requirePMF);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for SAE network.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForWpa3PskNetwork() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.SAE));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                suggestion.wifiConfiguration.preSharedKey);
+        assertTrue(suggestion.wifiConfiguration.requirePMF);
+    }
+
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkSuggestion.Builder#build()} for SuiteB network.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+        enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+
+        WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa3EnterpriseConfig(enterpriseConfig)
+                .build();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.SUITE_B_192));
+        assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.GCMP_256));
+        assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers
+                .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256));
+        assertTrue(suggestion.wifiConfiguration.allowedSuiteBCiphers
+                .get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA));
+        assertTrue(suggestion.wifiConfiguration.allowedSuiteBCiphers
+                .get(WifiConfiguration.SuiteBCipher.ECDHE_RSA));
+        assertTrue(suggestion.wifiConfiguration.requirePMF);
+        assertNull(suggestion.wifiConfiguration.preSharedKey);
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#setSsid(String)} throws an exception
+     * when the string is not Unicode.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderSetSsidWithNonUnicodeString() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid("\ud800")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#setWpa2Passphrase(String)} throws an exception
+     * when the string is not ASCII encodable.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderSetWpa2PasphraseWithNonAsciiString() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase("salvē")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when {@link WifiNetworkSuggestion.Builder#setSsid(String)} is not set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithNoSsid() {
+        new WifiNetworkSuggestion.Builder()
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when {@link WifiNetworkSuggestion.Builder#setSsid(String)} is invoked with an invalid value.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithInvalidSsid() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid("")
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when {@link WifiNetworkSuggestion.Builder#setBssid(MacAddress)} is invoked with an invalid
+     * value.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithInvalidBroadcastBssid() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.BROADCAST_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when {@link WifiNetworkSuggestion.Builder#setBssid(MacAddress)} is invoked with an invalid
+     * value.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithInvalidAllZeroBssid() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#setPriority(int)} throws an exception
+     * when the value is negative.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderWithInvalidPriority() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setPriority(-1)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa2Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa2PasphraseAndWpa3Passphrase() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa2Passphrase(TEST_PRESHARED_KEY)
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setWpa3EnterpriseConfig(WifiEnterpriseConfig)} are
+     * invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa3PasphraseAndEnterprise() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+                .build();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+     * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and
+     * {@link WifiNetworkSuggestion.Builder#setIsEnhancedOpen()} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBothWpa3PasphraseAndEnhancedOpen() {
+        new WifiNetworkSuggestion.Builder()
+                .setSsid(TEST_SSID)
+                .setWpa3Passphrase(TEST_PRESHARED_KEY)
+                .setIsEnhancedOpen()
+                .build();
+    }
 
     /**
      * Check that parcel marshalling/unmarshalling works