| /* |
| * 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.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.RequiresPermission; |
| import android.annotation.SystemApi; |
| import android.net.MacAddress; |
| import android.net.wifi.hotspot2.PasspointConfiguration; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.telephony.TelephonyManager; |
| 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 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 final 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; |
| /** |
| * The passpoint config for use with Hotspot 2.0 network |
| */ |
| private @Nullable PasspointConfiguration mPasspointConfiguration; |
| /** |
| * 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; |
| |
| /** |
| * The carrier ID identifies the operator who provides this network configuration. |
| * see {@link TelephonyManager#getSimCarrierId()} |
| */ |
| private int mCarrierId; |
| |
| /** |
| * Whether this network is shared credential with user to allow user manually connect. |
| */ |
| private boolean mIsSharedWithUser; |
| |
| /** |
| * Whether the setCredentialSharedWithUser have been called. |
| */ |
| private boolean mIsSharedWithUserSet; |
| |
| /** |
| * Whether this network is initialized with auto-join enabled (the default) or not. |
| */ |
| private boolean mIsInitialAutoJoinEnabled; |
| |
| /** |
| * Pre-shared key for use with WAPI-PSK networks. |
| */ |
| private @Nullable String mWapiPskPassphrase; |
| |
| /** |
| * The enterprise configuration details specifying the EAP method, |
| * certificates and other settings associated with the WAPI networks. |
| */ |
| private @Nullable WifiEnterpriseConfig mWapiEnterpriseConfig; |
| |
| /** |
| * Whether this network will be brought up as untrusted (TRUSTED capability bit removed). |
| */ |
| private boolean mIsNetworkUntrusted; |
| |
| public Builder() { |
| mSsid = null; |
| mBssid = null; |
| mIsEnhancedOpen = false; |
| mWpa2PskPassphrase = null; |
| mWpa3SaePassphrase = null; |
| mWpa2EnterpriseConfig = null; |
| mWpa3EnterpriseConfig = null; |
| mPasspointConfiguration = null; |
| mIsHiddenSSID = false; |
| mIsAppInteractionRequired = false; |
| mIsUserInteractionRequired = false; |
| mIsMetered = false; |
| mIsSharedWithUser = true; |
| mIsSharedWithUserSet = false; |
| mIsInitialAutoJoinEnabled = true; |
| mPriority = UNASSIGNED_PRIORITY; |
| mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; |
| mWapiPskPassphrase = null; |
| mWapiEnterpriseConfig = null; |
| mIsNetworkUntrusted = false; |
| } |
| |
| /** |
| * 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 @NonNull 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 @NonNull Builder setBssid(@NonNull MacAddress bssid) { |
| checkNotNull(bssid); |
| mBssid = MacAddress.fromBytes(bssid.toByteArray()); |
| return this; |
| } |
| |
| /** |
| * Specifies whether this represents an Enhanced Open (OWE) network. |
| * |
| * @param isEnhancedOpen {@code true} to indicate that the network used enhanced open, |
| * {@code false} otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsEnhancedOpen(boolean isEnhancedOpen) { |
| mIsEnhancedOpen = isEnhancedOpen; |
| 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 @NonNull 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 @NonNull 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 @NonNull 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 @NonNull Builder setWpa3EnterpriseConfig( |
| @NonNull WifiEnterpriseConfig enterpriseConfig) { |
| checkNotNull(enterpriseConfig); |
| mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig); |
| return this; |
| } |
| |
| /** |
| * Set the associated Passpoint configuration for this network. Needed for authenticating |
| * to Hotspot 2.0 networks. See {@link PasspointConfiguration} for description. |
| * |
| * @param passpointConfig Instance of {@link PasspointConfiguration}. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| * @throws IllegalArgumentException if passpoint configuration is invalid. |
| */ |
| public @NonNull Builder setPasspointConfig( |
| @NonNull PasspointConfiguration passpointConfig) { |
| checkNotNull(passpointConfig); |
| if (!passpointConfig.validate()) { |
| throw new IllegalArgumentException("Passpoint configuration is invalid"); |
| } |
| mPasspointConfiguration = passpointConfig; |
| return this; |
| } |
| |
| /** |
| * Set the carrier ID of the network operator. The carrier ID associates a Suggested |
| * network with a specific carrier (and therefore SIM). The carrier ID must be provided |
| * for any network which uses the SIM-based authentication: e.g. EAP-SIM, EAP-AKA, |
| * EAP-AKA', and EAP-PEAP with SIM-based phase 2 authentication. |
| * @param carrierId see {@link TelephonyManager#getSimCarrierId()}. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) |
| public @NonNull Builder setCarrierId(int carrierId) { |
| mCarrierId = carrierId; |
| return this; |
| } |
| |
| /** |
| * Set the ASCII WAPI passphrase for this network. Needed for authenticating to |
| * WAPI-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 @NonNull Builder setWapiPassphrase(@NonNull String passphrase) { |
| checkNotNull(passphrase); |
| final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder(); |
| if (!asciiEncoder.canEncode(passphrase)) { |
| throw new IllegalArgumentException("passphrase not ASCII encodable"); |
| } |
| mWapiPskPassphrase = passphrase; |
| return this; |
| } |
| |
| /** |
| * Set the associated enterprise configuration for this network. Needed for authenticating |
| * to WAPI-CERT 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 @NonNull Builder setWapiEnterpriseConfig( |
| @NonNull WifiEnterpriseConfig enterpriseConfig) { |
| checkNotNull(enterpriseConfig); |
| mWapiEnterpriseConfig = 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> |
| * |
| * @param isHiddenSsid {@code true} to indicate that the network is hidden, {@code false} |
| * otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsHiddenSsid(boolean isHiddenSsid) { |
| mIsHiddenSSID = isHiddenSsid; |
| 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> |
| * |
| * @param isAppInteractionRequired {@code true} to indicate that app interaction is |
| * required, {@code false} otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsAppInteractionRequired(boolean isAppInteractionRequired) { |
| mIsAppInteractionRequired = isAppInteractionRequired; |
| 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> |
| * |
| * @param isUserInteractionRequired {@code true} to indicate that user interaction is |
| * required, {@code false} otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsUserInteractionRequired(boolean isUserInteractionRequired) { |
| mIsUserInteractionRequired = isUserInteractionRequired; |
| 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 higher the number, |
| * the higher the priority (i.e value of 0 = lowest priority). |
| * <p> |
| * <li>If not set, defaults a lower priority than any assigned 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 @NonNull Builder setPriority(@IntRange(from = 0) 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> |
| * |
| * @param isMetered {@code true} to indicate that the network is metered, {@code false} |
| * otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsMetered(boolean isMetered) { |
| mIsMetered = isMetered; |
| return this; |
| } |
| |
| /** |
| * Specifies whether the network credentials provided with this suggestion can be used by |
| * the user to explicitly (manually) connect to this network. If true this network will |
| * appear in the Wi-Fi Picker (in Settings) and the user will be able to select and connect |
| * to it with the provided credentials. If false, the user will need to enter network |
| * credentials and the resulting configuration will become a user saved network. |
| * <p> |
| * <li>Note: Only valid for secure (non-open) networks. |
| * <li>If not set, defaults to true (i.e. allow user to manually connect) for secure |
| * networks and false for open networks.</li> |
| * |
| * @param isShared {@code true} to indicate that the credentials may be used by the user to |
| * manually connect to the network, {@code false} otherwise. |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setCredentialSharedWithUser(boolean isShared) { |
| mIsSharedWithUser = isShared; |
| mIsSharedWithUserSet = true; |
| return this; |
| } |
| |
| /** |
| * Specifies whether the suggestion is created with auto-join enabled or disabled. The |
| * user may modify the auto-join configuration of a suggestion directly once the device |
| * associates to the network. |
| * <p> |
| * If auto-join is initialized as disabled the user may still be able to manually connect |
| * to the network. Therefore, disabling auto-join only makes sense if |
| * {@link #setCredentialSharedWithUser(boolean)} is set to true (the default) which |
| * itself implies a secure (non-open) network. |
| * <p> |
| * If not set, defaults to true (i.e. auto-join is initialized as enabled). |
| * |
| * @param enabled true for initializing with auto-join enabled (the default), false to |
| * initializing with auto-join disabled. |
| * @return Instance of (@link {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setIsInitialAutoJoinEnabled(boolean enabled) { |
| mIsInitialAutoJoinEnabled = enabled; |
| return this; |
| } |
| |
| /** |
| * Specifies whether the system will bring up the network (if selected) as untrusted. An |
| * untrusted network has its {@link android.net.NetworkCapabilities#NET_CAPABILITY_TRUSTED} |
| * capability removed. The Wi-Fi network selection process may use this information to |
| * influence priority of the suggested network for Wi-Fi network selection (most likely to |
| * reduce it). The connectivity service may use this information to influence the overall |
| * network configuration of the device. |
| * <p> |
| * <li> An untrusted network's credentials may not be shared with the user using |
| * {@link #setCredentialSharedWithUser(boolean)}.</li> |
| * <li> If not set, defaults to false (i.e. network is trusted).</li> |
| * |
| * @param isUntrusted Boolean indicating whether the network should be brought up untrusted |
| * (if true) or trusted (if false). |
| * @return Instance of {@link Builder} to enable chaining of the builder method. |
| */ |
| public @NonNull Builder setUntrusted(boolean isUntrusted) { |
| mIsNetworkUntrusted = isUntrusted; |
| return this; |
| } |
| |
| private void setSecurityParamsInWifiConfiguration( |
| @NonNull WifiConfiguration configuration) { |
| if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network. |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); |
| // WifiConfiguration.preSharedKey needs quotes around ASCII password. |
| configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\""; |
| } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network. |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); |
| // WifiConfiguration.preSharedKey needs quotes around ASCII password. |
| configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\""; |
| } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); |
| configuration.enterpriseConfig = mWpa2EnterpriseConfig; |
| } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); |
| configuration.enterpriseConfig = mWpa3EnterpriseConfig; |
| } else if (mIsEnhancedOpen) { // OWE network |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); |
| } else if (!TextUtils.isEmpty(mWapiPskPassphrase)) { // WAPI-PSK network. |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_PSK); |
| // WifiConfiguration.preSharedKey needs quotes around ASCII password. |
| configuration.preSharedKey = "\"" + mWapiPskPassphrase + "\""; |
| } else if (mWapiEnterpriseConfig != null) { // WAPI-CERT network |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_CERT); |
| configuration.enterpriseConfig = mWapiEnterpriseConfig; |
| } else { // Open network |
| configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); |
| } |
| } |
| |
| /** |
| * Helper method to build WifiConfiguration object from the builder. |
| * @return Instance of {@link WifiConfiguration}. |
| */ |
| private WifiConfiguration buildWifiConfiguration() { |
| final WifiConfiguration wifiConfiguration = new 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; |
| wifiConfiguration.carrierId = mCarrierId; |
| 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 += !TextUtils.isEmpty(mWapiPskPassphrase) ? 1 : 0; |
| numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0; |
| numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0; |
| numSecurityTypes += mWapiEnterpriseConfig != null ? 1 : 0; |
| numSecurityTypes += mPasspointConfiguration != null ? 1 : 0; |
| if (numSecurityTypes > 1) { |
| throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase," |
| + " setWpa3Passphrase, setWpa2EnterpriseConfig, setWpa3EnterpriseConfig" |
| + " setWapiPassphrase, setWapiCertSuite, setIsWapiCertSuiteAuto" |
| + " or setPasspointConfig can be invoked for network suggestion"); |
| } |
| } |
| |
| private WifiConfiguration buildWifiConfigurationForPasspoint() { |
| WifiConfiguration wifiConfiguration = new WifiConfiguration(); |
| wifiConfiguration.FQDN = mPasspointConfiguration.getHomeSp().getFqdn(); |
| wifiConfiguration.priority = mPriority; |
| wifiConfiguration.meteredOverride = |
| mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED |
| : WifiConfiguration.METERED_OVERRIDE_NONE; |
| wifiConfiguration.trusted = !mIsNetworkUntrusted; |
| mPasspointConfiguration.setCarrierId(mCarrierId); |
| return wifiConfiguration; |
| } |
| |
| /** |
| * Create a network suggestion object for use in |
| * {@link WifiManager#addNetworkSuggestions(List)}. |
| * |
| *<p class="note"> |
| * <b>Note:</b> 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, one WPA3 network with their |
| * corresponding SSID's and one with Passpoint config: |
| * |
| * <pre>{@code |
| * final WifiNetworkSuggestion suggestion1 = |
| * new Builder() |
| * .setSsid("test111111") |
| * .build(); |
| * final WifiNetworkSuggestion suggestion2 = |
| * new Builder() |
| * .setSsid("test222222") |
| * .setWpa2Passphrase("test123456") |
| * .build(); |
| * final WifiNetworkSuggestion suggestion3 = |
| * new Builder() |
| * .setSsid("test333333") |
| * .setWpa3Passphrase("test6789") |
| * .build(); |
| * final PasspointConfiguration passpointConfig= new PasspointConfiguration(); |
| * // configure passpointConfig to include a valid Passpoint configuration |
| * final WifiNetworkSuggestion suggestion4 = |
| * new Builder() |
| * .setPasspointConfig(passpointConfig) |
| * .build(); |
| * final List<WifiNetworkSuggestion> suggestionsList = |
| * new ArrayList<WifiNetworkSuggestion> { { |
| * add(suggestion1); |
| * add(suggestion2); |
| * add(suggestion3); |
| * add(suggestion4); |
| * } }; |
| * final WifiManager wifiManager = |
| * context.getSystemService(Context.WIFI_SERVICE); |
| * wifiManager.addNetworkSuggestions(suggestionsList); |
| * // ... |
| * }</pre> |
| * |
| * @return Instance of {@link WifiNetworkSuggestion} |
| * @throws IllegalStateException on invalid params set |
| * @see WifiNetworkSuggestion |
| */ |
| public @NonNull WifiNetworkSuggestion build() { |
| validateSecurityParams(); |
| WifiConfiguration wifiConfiguration; |
| if (mPasspointConfiguration != null) { |
| if (mSsid != null) { |
| throw new IllegalStateException("setSsid should not be invoked for suggestion " |
| + "with Passpoint configuration"); |
| } |
| if (mIsHiddenSSID) { |
| throw new IllegalStateException("setIsHiddenSsid should not be invoked for " |
| + "suggestion with Passpoint configuration"); |
| } |
| wifiConfiguration = buildWifiConfigurationForPasspoint(); |
| } else { |
| 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(WifiManager.ALL_ZEROS_MAC_ADDRESS))) { |
| throw new IllegalStateException("invalid bssid for suggestion"); |
| } |
| wifiConfiguration = buildWifiConfiguration(); |
| if (wifiConfiguration.isOpenNetwork()) { |
| if (mIsSharedWithUserSet && mIsSharedWithUser) { |
| throw new IllegalStateException("Open network should not be " |
| + "setCredentialSharedWithUser to true"); |
| } |
| mIsSharedWithUser = false; |
| } |
| } |
| if (!mIsSharedWithUser && !mIsInitialAutoJoinEnabled) { |
| throw new IllegalStateException("Should have not a network with both " |
| + "setCredentialSharedWithUser and " |
| + "setIsAutoJoinEnabled set to false"); |
| } |
| if (mIsNetworkUntrusted) { |
| if (mIsSharedWithUserSet && mIsSharedWithUser) { |
| throw new IllegalStateException("Should not be both" |
| + "setCredentialSharedWithUser and +" |
| + "setIsNetworkAsUntrusted to true"); |
| } |
| mIsSharedWithUser = false; |
| } |
| return new WifiNetworkSuggestion( |
| wifiConfiguration, |
| mPasspointConfiguration, |
| mIsAppInteractionRequired, |
| mIsUserInteractionRequired, |
| mIsSharedWithUser, |
| mIsInitialAutoJoinEnabled, |
| mIsNetworkUntrusted); |
| } |
| } |
| |
| /** |
| * Network configuration for the provided network. |
| * @hide |
| */ |
| @NonNull |
| public final WifiConfiguration wifiConfiguration; |
| |
| /** |
| * Passpoint configuration for the provided network. |
| * @hide |
| */ |
| @Nullable |
| public final PasspointConfiguration passpointConfiguration; |
| |
| /** |
| * Whether app needs to log in to captive portal to obtain Internet access. |
| * @hide |
| */ |
| public final boolean isAppInteractionRequired; |
| |
| /** |
| * Whether user needs to log in to captive portal to obtain Internet access. |
| * @hide |
| */ |
| public final boolean isUserInteractionRequired; |
| |
| /** |
| * Whether app share credential with the user, allow user use provided credential to |
| * connect network manually. |
| * @hide |
| */ |
| public final boolean isUserAllowedToManuallyConnect; |
| |
| /** |
| * Whether the suggestion will be initialized as auto-joined or not. |
| * @hide |
| */ |
| public final boolean isInitialAutoJoinEnabled; |
| |
| /** |
| * Whether this network will be brought up as untrusted (TRUSTED capability bit removed). |
| * @hide |
| */ |
| public final boolean isNetworkUntrusted; |
| |
| |
| /** @hide */ |
| public WifiNetworkSuggestion() { |
| this.wifiConfiguration = new WifiConfiguration(); |
| this.passpointConfiguration = null; |
| this.isAppInteractionRequired = false; |
| this.isUserInteractionRequired = false; |
| this.isUserAllowedToManuallyConnect = true; |
| this.isInitialAutoJoinEnabled = true; |
| this.isNetworkUntrusted = false; |
| } |
| |
| /** @hide */ |
| public WifiNetworkSuggestion(@NonNull WifiConfiguration networkConfiguration, |
| @Nullable PasspointConfiguration passpointConfiguration, |
| boolean isAppInteractionRequired, |
| boolean isUserInteractionRequired, |
| boolean isUserAllowedToManuallyConnect, |
| boolean isInitialAutoJoinEnabled, |
| boolean isNetworkUntrusted) { |
| checkNotNull(networkConfiguration); |
| this.wifiConfiguration = networkConfiguration; |
| this.passpointConfiguration = passpointConfiguration; |
| |
| this.isAppInteractionRequired = isAppInteractionRequired; |
| this.isUserInteractionRequired = isUserInteractionRequired; |
| this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect; |
| this.isInitialAutoJoinEnabled = isInitialAutoJoinEnabled; |
| this.isNetworkUntrusted = isNetworkUntrusted; |
| } |
| |
| public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR = |
| new Creator<WifiNetworkSuggestion>() { |
| @Override |
| public WifiNetworkSuggestion createFromParcel(Parcel in) { |
| return new WifiNetworkSuggestion( |
| in.readParcelable(null), // wifiConfiguration |
| in.readParcelable(null), // PasspointConfiguration |
| in.readBoolean(), // isAppInteractionRequired |
| in.readBoolean(), // isUserInteractionRequired |
| in.readBoolean(), // isSharedCredentialWithUser |
| in.readBoolean(), // isAutoJoinEnabled |
| in.readBoolean() |
| ); |
| } |
| |
| @Override |
| public WifiNetworkSuggestion[] newArray(int size) { |
| return new WifiNetworkSuggestion[size]; |
| } |
| }; |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| dest.writeParcelable(wifiConfiguration, flags); |
| dest.writeParcelable(passpointConfiguration, flags); |
| dest.writeBoolean(isAppInteractionRequired); |
| dest.writeBoolean(isUserInteractionRequired); |
| dest.writeBoolean(isUserAllowedToManuallyConnect); |
| dest.writeBoolean(isInitialAutoJoinEnabled); |
| dest.writeBoolean(isNetworkUntrusted); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID, |
| wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN); |
| } |
| |
| /** |
| * Equals for network suggestions. |
| */ |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (!(obj instanceof WifiNetworkSuggestion)) { |
| return false; |
| } |
| WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj; |
| if (this.passpointConfiguration == null ^ lhs.passpointConfiguration == null) { |
| return false; |
| } |
| |
| return TextUtils.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID) |
| && TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID) |
| && Objects.equals(this.wifiConfiguration.allowedKeyManagement, |
| lhs.wifiConfiguration.allowedKeyManagement) |
| && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder("WifiNetworkSuggestion[ ") |
| .append("SSID=").append(wifiConfiguration.SSID) |
| .append(", BSSID=").append(wifiConfiguration.BSSID) |
| .append(", FQDN=").append(wifiConfiguration.FQDN) |
| .append(", isAppInteractionRequired=").append(isAppInteractionRequired) |
| .append(", isUserInteractionRequired=").append(isUserInteractionRequired) |
| .append(", isCredentialSharedWithUser=").append(isUserAllowedToManuallyConnect) |
| .append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled) |
| .append(", isUnTrusted=").append(isNetworkUntrusted) |
| .append(" ]"); |
| return sb.toString(); |
| } |
| |
| /** |
| * Get the {@link WifiConfiguration} associated with this Suggestion. |
| * @hide |
| */ |
| @SystemApi |
| @NonNull |
| public WifiConfiguration getWifiConfiguration() { |
| return wifiConfiguration; |
| } |
| |
| /** |
| * Get the {@link PasspointConfiguration} associated with this Suggestion, or null if this |
| * Suggestion is not for a Passpoint network. |
| * @hide |
| */ |
| @SystemApi |
| @Nullable |
| public PasspointConfiguration getPasspointConfiguration() { |
| return passpointConfiguration; |
| } |
| } |