diff options
Diffstat (limited to 'wifi')
77 files changed, 4921 insertions, 253 deletions
diff --git a/wifi/Android.bp b/wifi/Android.bp index 52e3840c126e..07b2ea9f7847 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -31,9 +31,6 @@ filegroup { "java/**/*.java", "java/**/*.aidl", ], - exclude_srcs: [ - ":framework-wifi-non-updatable-sources" - ], path: "java", visibility: ["//visibility:private"], } @@ -43,20 +40,7 @@ filegroup { srcs: [ ":framework-wifi-updatable-java-sources", ":framework-wifi-updatable-exported-aidl-sources", - ], -} - -filegroup { - name: "framework-wifi-non-updatable-sources", - srcs: [ - // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and - // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache - // to a separate package. - "java/android/net/wifi/SoftApConfToXmlMigrationUtil.java", - "java/android/net/wifi/WifiNetworkScoreCache.java", - "java/android/net/wifi/WifiMigration.java", - "java/android/net/wifi/nl80211/*.java", - ":libwificond_ipc_aidl", + ":module-utils-os-aidls", ], } @@ -68,6 +52,7 @@ filegroup { // list of tests that are allowed to access @hide APIs from framework-wifi test_access_hidden_api_whitelist = [ "//frameworks/base/wifi/tests", + "//frameworks/base/wifi/non-updatable/tests", "//frameworks/opt/net/wifi/tests/wifitests:__subpackages__", "//external/robolectric-shadows:__subpackages__", @@ -85,13 +70,14 @@ java_defaults { "framework-wifi-util-lib", "android.hardware.wifi-V1.0-java-constants", "modules-utils-build", + "modules-utils-os", ], libs: [ "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage ], srcs: [ ":framework-wifi-updatable-sources", - ":framework-wifi-util-lib-aidls", + ":module-utils-os-aidls", ], } @@ -147,7 +133,7 @@ java_sdk_library { // defaults for tests that need to build against framework-wifi's @hide APIs java_defaults { name: "framework-wifi-test-defaults", - sdk_version: "core_platform", // tests can use @CorePlatformApi's + sdk_version: "core_current", libs: [ // order matters: classes in framework-wifi are resolved before framework, meaning // @hide APIs in framework-wifi are resolved before @SystemApi stubs in framework diff --git a/wifi/TEST_MAPPING b/wifi/TEST_MAPPING index fde3a6aa993c..7ddc30872cb9 100644 --- a/wifi/TEST_MAPPING +++ b/wifi/TEST_MAPPING @@ -1,5 +1,5 @@ { - "presubmit": [ + "presubmit-large": [ { "name": "CtsWifiTestCases", "options": [ @@ -8,5 +8,15 @@ } ] } + ], + "mainline-presubmit": [ + { + "name": "CtsWifiTestCases[com.google.android.wifi.apex]", + "options": [ + { + "exclude-annotation": "android.net.wifi.cts.VirtualDeviceNotSupported" + } + ] + } ] } diff --git a/wifi/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl b/wifi/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl new file mode 100644 index 000000000000..cb359e9b2c1b --- /dev/null +++ b/wifi/aidl-export/android/net/wifi/CoexUnsafeChannel.aidl @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2020, 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; + +parcelable CoexUnsafeChannel; diff --git a/wifi/api/current.txt b/wifi/api/current.txt index 5c4e6157e195..1ece79a37459 100644 --- a/wifi/api/current.txt +++ b/wifi/api/current.txt @@ -14,6 +14,7 @@ package android.net.wifi { field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8 field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa + field public static final int EASY_CONNECT_EVENT_FAILURE_URI_GENERATION = -13; // 0xfffffff3 } public final class ScanResult implements android.os.Parcelable { @@ -34,6 +35,7 @@ package android.net.wifi { field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR; field public String SSID; field public static final int WIFI_STANDARD_11AC = 5; // 0x5 + field public static final int WIFI_STANDARD_11AD = 7; // 0x7 field public static final int WIFI_STANDARD_11AX = 6; // 0x6 field public static final int WIFI_STANDARD_11N = 4; // 0x4 field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1 @@ -106,6 +108,7 @@ package android.net.wifi { field @Deprecated public static final int SECURITY_TYPE_EAP = 3; // 0x3 field @Deprecated public static final int SECURITY_TYPE_EAP_SUITE_B = 5; // 0x5 field @Deprecated public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9; // 0x9 + field @Deprecated public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5; // 0x5 field @Deprecated public static final int SECURITY_TYPE_OPEN = 0; // 0x0 field @Deprecated public static final int SECURITY_TYPE_OWE = 6; // 0x6 field @Deprecated public static final int SECURITY_TYPE_PSK = 2; // 0x2 @@ -307,6 +310,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>); method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration); method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener); + method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean addSuggestionUserApprovalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener); method @Deprecated public static int calculateSignalLevel(int, int); method @IntRange(from=0) public int calculateSignalLevel(int); method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback); @@ -322,6 +326,7 @@ package android.net.wifi { method public android.net.DhcpInfo getDhcpInfo(); method public int getMaxNumberOfNetworkSuggestionsPerApp(); method @IntRange(from=0) public int getMaxSignalLevel(); + method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getNetworkSuggestionUserApprovalStatus(); method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions(); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations(); method public java.util.List<android.net.wifi.ScanResult> getScanResults(); @@ -329,6 +334,7 @@ package android.net.wifi { method public boolean is5GHzBandSupported(); method public boolean is6GHzBandSupported(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isAutoWakeupEnabled(); + method public boolean isBridgedApConcurrencySupported(); method @Deprecated public boolean isDeviceToApRttSupported(); method public boolean isEasyConnectSupported(); method public boolean isEnhancedOpenSupported(); @@ -339,10 +345,12 @@ package android.net.wifi { method @Deprecated public boolean isScanAlwaysAvailable(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isScanThrottleEnabled(); method public boolean isStaApConcurrencySupported(); + method public boolean isStaBridgedApConcurrencySupported(); method public boolean isTdlsSupported(); method public boolean isWapiSupported(); method public boolean isWifiEnabled(); method public boolean isWifiStandardSupported(int); + method public boolean isWpa3ApValidationSupported(); method public boolean isWpa3SaeSupported(); method public boolean isWpa3SuiteBSupported(); method @Deprecated public boolean pingSupplicant(); @@ -353,6 +361,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}) public void removePasspointConfiguration(String); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionConnectionStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener); + method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionUserApprovalStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener); method @Deprecated public boolean saveConfiguration(); method public void setTdlsEnabled(java.net.InetAddress, boolean); method public void setTdlsEnabledWithMacAddress(String, boolean); @@ -391,6 +400,11 @@ package android.net.wifi { field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; // 0x1 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; // 0x5 field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0 + field public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; // 0x4 + field public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; // 0x2 + field public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; // 0x1 + field public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; // 0x3 + field public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; // 0x0 field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; // 0x1 field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; // 0x2 field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; // 0x3 @@ -448,6 +462,10 @@ package android.net.wifi { method public void onConnectionStatus(@NonNull android.net.wifi.WifiNetworkSuggestion, int); } + public static interface WifiManager.SuggestionUserApprovalStatusListener { + method public void onUserApprovalStatusChange(); + } + public class WifiManager.WifiLock { method public void acquire(); method public boolean isHeld(); @@ -497,6 +515,7 @@ package android.net.wifi { method @Nullable public String getSsid(); method public int getSubscriptionId(); method public boolean isAppInteractionRequired(); + method public boolean isCarrierMerged(); method public boolean isCredentialSharedWithUser(); method public boolean isEnhancedOpen(); method public boolean isHiddenSsid(); @@ -512,6 +531,7 @@ package android.net.wifi { ctor public WifiNetworkSuggestion.Builder(); method @NonNull public android.net.wifi.WifiNetworkSuggestion build(); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setBssid(@NonNull android.net.MacAddress); + method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierMerged(boolean); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setCredentialSharedWithUser(boolean); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired(boolean); method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedMacRandomizationEnabled(boolean); @@ -1143,7 +1163,11 @@ package android.net.wifi.rtt { public final class RangingRequest implements android.os.Parcelable { method public int describeContents(); + method public static int getDefaultRttBurstSize(); method public static int getMaxPeers(); + method public static int getMaxRttBurstSize(); + method public static int getMinRttBurstSize(); + method public int getRttBurstSize(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR; } @@ -1155,6 +1179,7 @@ package android.net.wifi.rtt { method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.MacAddress); method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.wifi.aware.PeerHandle); method public android.net.wifi.rtt.RangingRequest build(); + method @NonNull public android.net.wifi.rtt.RangingRequest.Builder setRttBurstSize(int); } public final class RangingResult implements android.os.Parcelable { diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt index edbd46300191..257f9d53e59f 100644 --- a/wifi/api/system-current.txt +++ b/wifi/api/system-current.txt @@ -1,8 +1,20 @@ // Signature format: 2.0 package android.net.wifi { + public final class CoexUnsafeChannel implements android.os.Parcelable { + ctor public CoexUnsafeChannel(int, int); + ctor public CoexUnsafeChannel(int, int, int); + method public int getBand(); + method public int getChannel(); + method public int getPowerCapDbm(); + method public boolean isPowerCapAvailable(); + method public void setPowerCapDbm(int); + field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.CoexUnsafeChannel> CREATOR; + } + public abstract class EasyConnectStatusCallback { ctor public EasyConnectStatusCallback(); + method public void onBootstrapUriGenerated(@NonNull String); method public abstract void onConfiguratorSuccess(int); method public abstract void onEnrolleeSuccess(int); method public void onFailure(int); @@ -265,6 +277,7 @@ package android.net.wifi { method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration(); field public static final int BAND_2GHZ = 1; // 0x1 field public static final int BAND_5GHZ = 2; // 0x2 + field public static final int BAND_60GHZ = 8; // 0x8 field public static final int BAND_6GHZ = 4; // 0x4 field @Deprecated public static final int BAND_ANY = 7; // 0x7 field public static final int RANDOMIZATION_NONE = 0; // 0x0 @@ -302,9 +315,13 @@ package android.net.wifi { field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6 field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2 field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1 + field public static final int CHANNEL_WIDTH_2160MHZ = 7; // 0x7 field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3 + field public static final int CHANNEL_WIDTH_4320MHZ = 8; // 0x8 + field public static final int CHANNEL_WIDTH_6480MHZ = 9; // 0x9 field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4 field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5 + field public static final int CHANNEL_WIDTH_8640MHZ = 10; // 0xa field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0 field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR; } @@ -321,6 +338,7 @@ package android.net.wifi { method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration(); method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus(); method @Deprecated @NonNull public String getPrintableSsid(); + method @Deprecated @NonNull public String getProfileKey(); method @Deprecated public int getRecentFailureReason(); method @Deprecated public boolean hasNoInternetAccess(); method @Deprecated public boolean isEphemeral(); @@ -344,6 +362,7 @@ package android.net.wifi { field @Deprecated public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002; // 0x3ea field @Deprecated public boolean allowAutojoin; field @Deprecated public int carrierId; + field @Deprecated public boolean carrierMerged; field @Deprecated public String creatorName; field @Deprecated public int creatorUid; field @Deprecated public boolean fromWifiNetworkSpecifier; @@ -379,6 +398,8 @@ package android.net.wifi { method @Deprecated public boolean hasEverConnected(); field @Deprecated public static final int DISABLED_ASSOCIATION_REJECTION = 1; // 0x1 field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE = 2; // 0x2 + field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10; // 0xa + field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2; // 0x2 field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; // 0x5 field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; // 0x9 field @Deprecated public static final int DISABLED_BY_WIFI_MANAGER = 7; // 0x7 @@ -425,8 +446,10 @@ package android.net.wifi { method @Nullable public String getRequestingPackageName(); method public double getRetriedTxPacketsPerSecond(); method public int getScore(); + method public int getSubscriptionId(); method public double getSuccessfulRxPacketsPerSecond(); method public double getSuccessfulTxPacketsPerSecond(); + method public boolean isCarrierMerged(); method public boolean isEphemeral(); method public boolean isOemPaid(); method public boolean isOemPrivate(); @@ -451,6 +474,8 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>); + method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public int getCoexRestrictions(); + method @NonNull @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public java.util.Set<android.net.wifi.CoexUnsafeChannel> getCoexUnsafeChannels(); method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCountryCode(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork(); method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses(); @@ -465,16 +490,19 @@ package android.net.wifi { method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>); method public boolean is60GHzBandSupported(); method public boolean isApMacRandomizationSupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean isCarrierNetworkOffloadEnabled(int, boolean); method public boolean isConnectedMacRandomizationSupported(); method @Deprecated public boolean isDeviceToDeviceRttSupported(); method public boolean isPortableHotspotSupported(); method public boolean isVerboseLoggingEnabled(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled(); method public boolean isWifiScannerSupported(); + method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void registerCoexCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.CoexCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback); method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); + method @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) public void restartWifiSubsystem(@Nullable String); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]); method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]); @@ -482,6 +510,8 @@ package android.net.wifi { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveSoftApBackupData(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setAutoWakeupEnabled(boolean); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void setCarrierNetworkOffloadEnabled(int, boolean, boolean); + method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) public void setCoexUnsafeChannels(@NonNull java.util.Set<android.net.wifi.CoexUnsafeChannel>, int); method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setPasspointMeteredOverride(@NonNull String, int); @@ -493,12 +523,16 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeResponder(@Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp(); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopTemporarilyDisablingAllNonCarrierMergedWifi(); + method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void unregisterCoexCallback(@NonNull android.net.wifi.WifiManager.CoexCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterTrafficStateCallback(@NonNull android.net.wifi.WifiManager.TrafficStateCallback); @@ -512,11 +546,22 @@ package android.net.wifi { field public static final int CHANGE_REASON_ADDED = 0; // 0x0 field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2 field public static final int CHANGE_REASON_REMOVED = 1; // 0x1 + field public static final int COEX_RESTRICTION_SOFTAP = 2; // 0x2 + field public static final int COEX_RESTRICTION_WIFI_AWARE = 4; // 0x4 + field public static final int COEX_RESTRICTION_WIFI_DIRECT = 1; // 0x1 field public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE"; field public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; // 0x1 field public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; // 0x2 field public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; // 0x3 field public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; // 0x0 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; // 0x3 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; // 0x4 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; // 0x5 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT = 0; // 0x0 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; // 0x0 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; // 0x1 + field public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; // 0x2 + field public static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; // 0x28 field public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; // 0x1 field public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; // 0x0 field public static final String EXTRA_CHANGE_REASON = "changeReason"; @@ -559,6 +604,11 @@ package android.net.wifi { method public void onSuccess(); } + public abstract static class WifiManager.CoexCallback { + ctor public WifiManager.CoexCallback(); + method public abstract void onCoexUnsafeChannelsChanged(); + } + public static interface WifiManager.NetworkRequestMatchCallback { method public default void onAbort(); method public default void onMatch(@NonNull java.util.List<android.net.wifi.ScanResult>); @@ -590,6 +640,7 @@ package android.net.wifi { method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability); method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>); method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo); + method public default void onInfoListChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>); method public default void onStateChanged(int, int); } @@ -915,6 +966,10 @@ package android.net.wifi.p2p { package android.net.wifi.rtt { + public final class RangingRequest implements android.os.Parcelable { + method @NonNull public java.util.List<android.net.wifi.rtt.ResponderConfig> getRttPeers(); + } + public static final class RangingRequest.Builder { method public android.net.wifi.rtt.RangingRequest.Builder addResponder(@NonNull android.net.wifi.rtt.ResponderConfig); } diff --git a/wifi/api/system-lint-baseline.txt b/wifi/api/system-lint-baseline.txt index a5f3f7c08fa4..9a3b66a30425 100644 --- a/wifi/api/system-lint-baseline.txt +++ b/wifi/api/system-lint-baseline.txt @@ -7,5 +7,7 @@ MissingNullability: android.net.wifi.rtt.RangingRequest.Builder#addResponder(and +MutableBareField: android.net.wifi.WifiConfiguration#carrierMerged: + MutableBareField: android.net.wifi.WifiConfiguration#subscriptionId: Bare field subscriptionId must be marked final, or moved behind accessors if mutable diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt index ff06a180b8c1..2331c2f1fadc 100644 --- a/wifi/jarjar-rules.txt +++ b/wifi/jarjar-rules.txt @@ -21,6 +21,7 @@ rule android.net.ProvisioningConfigurationParcelable* com.android.wifi.x.@0 rule android.net.ResolverParamsParcel* com.android.wifi.x.@0 rule android.net.RouteInfoParcel* com.android.wifi.x.@0 rule android.net.ScanResultInfoParcelable* com.android.wifi.x.@0 +rule android.net.TcpKeepalivePacketDataParcelable* com.android.wifi.x.@0 rule android.net.TetherConfigParcel* com.android.wifi.x.@0 rule android.net.TetherOffloadRuleParcel* com.android.wifi.x.@0 rule android.net.TetherStatsParcel* com.android.wifi.x.@0 @@ -43,7 +44,6 @@ rule android.net.DhcpResults* com.android.wifi.x.@0 rule android.net.InterfaceConfiguration* com.android.wifi.x.@0 rule android.net.IpMemoryStore* com.android.wifi.x.@0 rule android.net.NetworkMonitorManager* com.android.wifi.x.@0 -rule android.net.TcpKeepalivePacketData* com.android.wifi.x.@0 rule android.net.NetworkFactory* com.android.wifi.x.@0 rule android.net.ip.IpClientCallbacks* com.android.wifi.x.@0 rule android.net.ip.IpClientManager* com.android.wifi.x.@0 @@ -89,8 +89,6 @@ rule android.util.BackupUtils* com.android.wifi.x.@0 rule android.util.LocalLog* com.android.wifi.x.@0 rule android.util.Rational* com.android.wifi.x.@0 -rule android.os.BasicShellCommandHandler* com.android.wifi.x.@0 - # Use our statically linked bouncy castle library rule org.bouncycastle.** com.android.wifi.x.@0 # Use our statically linked protobuf library @@ -112,10 +110,6 @@ rule org.ksoap2.** com.android.wifi.x.@0 rule fi.iki.elonen.** com.android.wifi.x.@0 ## used by both framework-wifi and service-wifi ## -rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0 -rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0 -rule android.net.util.MacAddressUtils* com.android.wifi.x.@0 -rule android.net.util.nsd.DnsSdTxtRecord* com.android.wifi.x.@0 rule android.os.HandlerExecutor* com.android.wifi.x.@0 rule android.telephony.Annotation* com.android.wifi.x.@0 rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0 diff --git a/wifi/java/android/net/wifi/CoexUnsafeChannel.java b/wifi/java/android/net/wifi/CoexUnsafeChannel.java new file mode 100644 index 000000000000..3f9efa020d05 --- /dev/null +++ b/wifi/java/android/net/wifi/CoexUnsafeChannel.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2020 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.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; +import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ; +import static android.net.wifi.WifiScanner.WIFI_BAND_6_GHZ; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Data structure class representing a Wi-Fi channel that would cause interference to/receive + * interference from the active cellular channels and should be avoided. + * + * If {@link #isPowerCapAvailable()} is {@code true}, then a valid power cap value is available + * through {@link #getPowerCapDbm()} to be used if this channel cannot be avoided. If {@code false}, + * then {@link #getPowerCapDbm()} throws an IllegalStateException and the channel will not need to + * cap its power. + * + * @hide + */ +@SystemApi +public final class CoexUnsafeChannel implements Parcelable { + private @WifiAnnotations.WifiBandBasic int mBand; + private int mChannel; + private boolean mIsPowerCapAvailable = false; + private int mPowerCapDbm; + + /** + * Constructor for a CoexUnsafeChannel with no power cap specified. + * @param band One of {@link WifiAnnotations.WifiBandBasic} + * @param channel Channel number + */ + public CoexUnsafeChannel(@WifiAnnotations.WifiBandBasic int band, int channel) { + mBand = band; + mChannel = channel; + } + + /** + * Constructor for a CoexUnsafeChannel with power cap specified. + * @param band One of {@link WifiAnnotations.WifiBandBasic} + * @param channel Channel number + * @param powerCapDbm Power cap in dBm + */ + public CoexUnsafeChannel(@WifiAnnotations.WifiBandBasic int band, int channel, + int powerCapDbm) { + mBand = band; + mChannel = channel; + setPowerCapDbm(powerCapDbm); + } + + /** Returns the Wi-Fi band of this channel as one of {@link WifiAnnotations.WifiBandBasic} */ + public @WifiAnnotations.WifiBandBasic int getBand() { + return mBand; + } + + /** Returns the channel number of this channel. */ + public int getChannel() { + return mChannel; + } + + /** Returns {@code true} if {@link #getPowerCapDbm()} is a valid value, else {@code false} */ + public boolean isPowerCapAvailable() { + return mIsPowerCapAvailable; + } + + /** + * Returns the power cap of this channel in dBm. Throws IllegalStateException if + * {@link #isPowerCapAvailable()} is {@code false}. + */ + public int getPowerCapDbm() { + if (!mIsPowerCapAvailable) { + throw new IllegalStateException("getPowerCapDbm called but power cap is unavailable"); + } + return mPowerCapDbm; + } + + /** Set the power cap of this channel. */ + public void setPowerCapDbm(int powerCapDbm) { + mIsPowerCapAvailable = true; + mPowerCapDbm = powerCapDbm; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CoexUnsafeChannel that = (CoexUnsafeChannel) o; + return mBand == that.mBand + && mChannel == that.mChannel + && mIsPowerCapAvailable == that.mIsPowerCapAvailable + && mPowerCapDbm == that.mPowerCapDbm; + } + + @Override + public int hashCode() { + return Objects.hash(mBand, mChannel, mIsPowerCapAvailable, mPowerCapDbm); + } + + @Override + public String toString() { + StringBuilder sj = new StringBuilder("CoexUnsafeChannel{"); + sj.append(mChannel); + sj.append(", "); + if (mBand == WIFI_BAND_24_GHZ) { + sj.append("2.4GHz"); + } else if (mBand == WIFI_BAND_5_GHZ) { + sj.append("5GHz"); + } else if (mBand == WIFI_BAND_6_GHZ) { + sj.append("6GHz"); + } else { + sj.append("UNKNOWN BAND"); + } + if (mIsPowerCapAvailable) { + sj.append(", ").append(mPowerCapDbm).append("dBm"); + } + sj.append('}'); + return sj.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface {@hide} */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mBand); + dest.writeInt(mChannel); + dest.writeBoolean(mIsPowerCapAvailable); + if (mIsPowerCapAvailable) { + dest.writeInt(mPowerCapDbm); + } + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<CoexUnsafeChannel> CREATOR = + new Creator<CoexUnsafeChannel>() { + public CoexUnsafeChannel createFromParcel(Parcel in) { + final int band = in.readInt(); + final int channel = in.readInt(); + final boolean isPowerCapAvailable = in.readBoolean(); + if (isPowerCapAvailable) { + final int powerCapDbm = in.readInt(); + return new CoexUnsafeChannel(band, channel, powerCapDbm); + } + return new CoexUnsafeChannel(band, channel); + } + + public CoexUnsafeChannel[] newArray(int size) { + return new CoexUnsafeChannel[size]; + } + }; +} diff --git a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java index 6c2e6ddf5dd2..ee7025594bc6 100644 --- a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java +++ b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java @@ -161,6 +161,11 @@ public abstract class EasyConnectStatusCallback { */ public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12; + /** + * Easy Connect Failure event: System failed to generate DPP URI. + */ + public static final int EASY_CONNECT_EVENT_FAILURE_URI_GENERATION = -13; + /** @hide */ @IntDef(prefix = {"EASY_CONNECT_EVENT_FAILURE_"}, value = { EASY_CONNECT_EVENT_FAILURE_INVALID_URI, @@ -175,6 +180,7 @@ public abstract class EasyConnectStatusCallback { EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK, EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION, EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION, + EASY_CONNECT_EVENT_FAILURE_URI_GENERATION, }) @Retention(RetentionPolicy.SOURCE) public @interface EasyConnectFailureStatusCode { @@ -264,4 +270,17 @@ public abstract class EasyConnectStatusCallback { */ @SystemApi public abstract void onProgress(@EasyConnectProgressStatusCode int code); + + /** + * Called when local Easy Connect Responder successfully generates a DPP URI from + * the supplicant. This callback is the first successful outcome + * of a Easy Connect Responder flow starting with + * {@link WifiManager#startEasyConnectAsEnrolleeResponder(String, int, Executor, + * EasyConnectStatusCallback)} . + * + * @param uri DPP URI from the supplicant. + * @hide + */ + @SystemApi + public void onBootstrapUriGenerated(@NonNull String uri) {}; } diff --git a/wifi/java/android/net/wifi/ICoexCallback.aidl b/wifi/java/android/net/wifi/ICoexCallback.aidl new file mode 100644 index 000000000000..89e4c4b93013 --- /dev/null +++ b/wifi/java/android/net/wifi/ICoexCallback.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 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; + +/** + * Interface for Wi-Fi/cellular coex callback. + * @hide + */ +oneway interface ICoexCallback +{ + void onCoexUnsafeChannelsChanged(); +} diff --git a/wifi/java/android/net/wifi/IDppCallback.aidl b/wifi/java/android/net/wifi/IDppCallback.aidl index d7a958a5b4b1..dcbe8468de9e 100644 --- a/wifi/java/android/net/wifi/IDppCallback.aidl +++ b/wifi/java/android/net/wifi/IDppCallback.aidl @@ -45,4 +45,10 @@ oneway interface IDppCallback * to show progress. */ void onProgress(int status); + + /** + * Called when local DPP Responder successfully generates a URI. + */ + void onBootstrapUriGenerated(String uri); + } diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index f81bcb9e06d7..a28a8fb626b1 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -53,6 +53,12 @@ oneway interface ISoftApCallback */ void onInfoChanged(in SoftApInfo softApInfo); + /** + * Service to manager callback providing informations of softap. + * + * @param softApInfoList is the list of the softap informations. {@link SoftApInfo} + */ + void onInfoListChanged(in List<SoftApInfo> softApInfoList); /** * Service to manager callback providing capability of softap. diff --git a/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl new file mode 100644 index 000000000000..5aa3a90ee2bb --- /dev/null +++ b/wifi/java/android/net/wifi/ISuggestionUserApprovalStatusListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 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; + +/** + * Interface for suggestion user approval status listener. + * + * @hide + */ +oneway interface ISuggestionUserApprovalStatusListener +{ + void onUserApprovalStatusChange(); +} diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 7329c16d68d0..23f47efdee21 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -16,15 +16,15 @@ package android.net.wifi; -import android.content.pm.ParceledListSlice; - import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.DhcpInfo; import android.net.Network; +import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.IActionListener; +import android.net.wifi.ICoexCallback; import android.net.wifi.IDppCallback; import android.net.wifi.ILocalOnlyHotspotCallback; import android.net.wifi.INetworkRequestMatchCallback; @@ -33,6 +33,7 @@ import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.IScanResultsCallback; import android.net.wifi.ISoftApCallback; import android.net.wifi.ISuggestionConnectionStatusListener; +import android.net.wifi.ISuggestionUserApprovalStatusListener; import android.net.wifi.ITrafficStateCallback; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.ScanResult; @@ -45,6 +46,8 @@ import android.os.Messenger; import android.os.ResultReceiver; import android.os.WorkSource; +import com.android.modules.utils.ParceledListSlice; + /** * Interface that allows controlling and querying Wi-Fi connectivity. * @@ -144,6 +147,18 @@ interface IWifiManager void updateInterfaceIpState(String ifaceName, int mode); + boolean isDefaultCoexAlgorithmEnabled(); + + void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions); + + List<CoexUnsafeChannel> getCoexUnsafeChannels(); + + int getCoexRestrictions(); + + void registerCoexCallback(in ICoexCallback callback); + + void unregisterCoexCallback(in ICoexCallback callback); + boolean startSoftAp(in WifiConfiguration wifiConfig, String packageName); boolean startTetheredHotspot(in SoftApConfiguration softApConfig, String packageName); @@ -235,6 +250,9 @@ interface IWifiManager void startDppAsEnrolleeInitiator(in IBinder binder, in String configuratorUri, in IDppCallback callback); + void startDppAsEnrolleeResponder(in IBinder binder, in String deviceInfo, int curve, + in IDppCallback callback); + void stopDppSession(); void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec); @@ -275,4 +293,20 @@ interface IWifiManager void setAutoWakeupEnabled(boolean enable); boolean isAutoWakeupEnabled(); + + int getNetworkSuggestionUserApprovalStatus(String packageName); + + void startTemporarilyDisablingAllNonCarrierMergedWifi(int subId); + + void stopTemporarilyDisablingAllNonCarrierMergedWifi(); + + void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled); + + boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged); + + void restartWifiSubsystem(String reason); + + boolean addSuggestionUserApprovalStatusListener(in IBinder binder, in ISuggestionUserApprovalStatusListener listener, int listenerIdentifier, String packageName, String featureId); + + void removeSuggestionUserApprovalStatusListener(int listenerIdentifier, String packageName); } diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 73c52ab0ab1b..034defb083de 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -173,7 +173,7 @@ public class RttManager { /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public Capabilities getCapabilities() { throw new UnsupportedOperationException( "getCapabilities is not supported in the adaptation layer"); diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 4c23286258d8..9f8ecf14175d 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -320,6 +320,11 @@ public final class ScanResult implements Parcelable { public static final int WIFI_STANDARD_11AX = 6; /** + * Wi-Fi 802.11ad/ay + */ + public static final int WIFI_STANDARD_11AD = 7; + + /** * AP wifi standard. */ private @WifiStandard int mWifiStandard; @@ -352,6 +357,8 @@ public final class ScanResult implements Parcelable { return "11ac"; case WIFI_STANDARD_11AX: return "11ax"; + case WIFI_STANDARD_11AD: + return "11ad"; case WIFI_STANDARD_UNKNOWN: return "unknown"; } @@ -705,6 +712,13 @@ public final class ScanResult implements Parcelable { return UNSPECIFIED; } } + if (band == WifiScanner.WIFI_BAND_60_GHZ) { + if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) { + return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ; + } else { + return UNSPECIFIED; + } + } return UNSPECIFIED; } diff --git a/wifi/java/android/net/wifi/SecurityParams.java b/wifi/java/android/net/wifi/SecurityParams.java new file mode 100644 index 000000000000..0ab6f572fba3 --- /dev/null +++ b/wifi/java/android/net/wifi/SecurityParams.java @@ -0,0 +1,824 @@ +/* + * Copyright (C) 2020 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 android.annotation.IntDef; +import android.annotation.NonNull; +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.net.wifi.WifiConfiguration.SecurityType; +import android.net.wifi.WifiConfiguration.SuiteBCipher; +import android.os.Parcel; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.BitSet; +import java.util.Objects; + +/** + * A class representing a security configuration. + * @hide + */ +public class SecurityParams { + private static final String TAG = "SecurityParams"; + + /** Passpoint Release 1 */ + public static final int PASSPOINT_R1 = 1; + + /** Passpoint Release 2 */ + public static final int PASSPOINT_R2 = 2; + + /** Passpoint Release 3 */ + public static final int PASSPOINT_R3 = 3; + + @IntDef(prefix = { "PASSPOINT_" }, value = { + PASSPOINT_R1, + PASSPOINT_R2, + PASSPOINT_R3, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PasspointRelease {} + + private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + /** + * This indicates that this security type is enabled or disabled. + * Ex. While receiving Transition Disable Indication, older + * security should be disabled. + */ + private boolean mEnabled = true; + + /** + * The set of key management protocols supported by this configuration. + * See {@link KeyMgmt} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedKeyManagement = new BitSet(); + + /** + * The set of security protocols supported by this configuration. + * See {@link Protocol} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedProtocols = new BitSet(); + + /** + * The set of authentication protocols supported by this configuration. + * See {@link AuthAlgorithm} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedAuthAlgorithms = new BitSet(); + + /** + * The set of pairwise ciphers for WPA supported by this configuration. + * See {@link PairwiseCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedPairwiseCiphers = new BitSet(); + + /** + * The set of group ciphers supported by this configuration. + * See {@link GroupCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedGroupCiphers = new BitSet(); + + /** + * The set of group management ciphers supported by this configuration. + * See {@link GroupMgmtCipher} for descriptions of the values. + */ + private BitSet mAllowedGroupManagementCiphers = new BitSet(); + + /** + * The set of SuiteB ciphers supported by this configuration. + * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the + * certificate type that is used in this configuration. + */ + private BitSet mAllowedSuiteBCiphers = new BitSet(); + + /** + * True if the network requires Protected Management Frames (PMF), false otherwise. + */ + private boolean mRequirePmf = false; + + private @PasspointRelease int mPasspointRelease = PASSPOINT_R2; + + /** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */ + private boolean mIsSaeH2eOnlyMode = false; + + /** Indicate that this SAE security type only accepts PK (Public Key) mode. */ + private boolean mIsSaePkOnlyMode = false; + + /** Indicate whether this is added by auto-upgrade or not. */ + private boolean mIsAddedByAutoUpgrade = false; + + /** Constructor */ + private SecurityParams() { + } + + /** Copy constructor */ + public SecurityParams(@NonNull SecurityParams source) { + this.mSecurityType = source.mSecurityType; + this.mEnabled = source.mEnabled; + this.mAllowedKeyManagement = (BitSet) source.mAllowedKeyManagement.clone(); + this.mAllowedProtocols = (BitSet) source.mAllowedProtocols.clone(); + this.mAllowedAuthAlgorithms = (BitSet) source.mAllowedAuthAlgorithms.clone(); + this.mAllowedPairwiseCiphers = (BitSet) source.mAllowedPairwiseCiphers.clone(); + this.mAllowedGroupCiphers = (BitSet) source.mAllowedGroupCiphers.clone(); + this.mAllowedGroupManagementCiphers = + (BitSet) source.mAllowedGroupManagementCiphers.clone(); + this.mAllowedSuiteBCiphers = + (BitSet) source.mAllowedSuiteBCiphers.clone(); + this.mRequirePmf = source.mRequirePmf; + this.mIsSaeH2eOnlyMode = source.mIsSaeH2eOnlyMode; + this.mIsSaePkOnlyMode = source.mIsSaePkOnlyMode; + this.mIsAddedByAutoUpgrade = source.mIsAddedByAutoUpgrade; + } + + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; + } + if (!(thatObject instanceof SecurityParams)) { + return false; + } + SecurityParams that = (SecurityParams) thatObject; + + if (this.mSecurityType != that.mSecurityType) return false; + if (this.mEnabled != that.mEnabled) return false; + if (!this.mAllowedKeyManagement.equals(that.mAllowedKeyManagement)) return false; + if (!this.mAllowedProtocols.equals(that.mAllowedProtocols)) return false; + if (!this.mAllowedAuthAlgorithms.equals(that.mAllowedAuthAlgorithms)) return false; + if (!this.mAllowedPairwiseCiphers.equals(that.mAllowedPairwiseCiphers)) return false; + if (!this.mAllowedGroupCiphers.equals(that.mAllowedGroupCiphers)) return false; + if (!this.mAllowedGroupManagementCiphers.equals(that.mAllowedGroupManagementCiphers)) { + return false; + } + if (!this.mAllowedSuiteBCiphers.equals(that.mAllowedSuiteBCiphers)) return false; + if (this.mRequirePmf != that.mRequirePmf) return false; + if (this.mIsSaeH2eOnlyMode != that.mIsSaeH2eOnlyMode) return false; + if (this.mIsSaePkOnlyMode != that.mIsSaePkOnlyMode) return false; + if (this.mIsAddedByAutoUpgrade != that.mIsAddedByAutoUpgrade) return false; + + return true; + } + + @Override + public int hashCode() { + return Objects.hash(mSecurityType, mEnabled, + mAllowedKeyManagement, mAllowedProtocols, mAllowedAuthAlgorithms, + mAllowedPairwiseCiphers, mAllowedGroupCiphers, mAllowedGroupManagementCiphers, + mAllowedSuiteBCiphers, mRequirePmf, + mIsSaeH2eOnlyMode, mIsSaePkOnlyMode, mIsAddedByAutoUpgrade); + } + + /** + * Check the security type of this params. + * + * @param type the testing security type. + * @return true if this is for the corresponiding type. + */ + public boolean isSecurityType(@SecurityType int type) { + return type == mSecurityType; + } + + /** + * Check whether the security of given params is the same as this one. + * + * @param params the testing security params. + * @return true if their security types are the same. + */ + public boolean isSameSecurityType(SecurityParams params) { + return params.mSecurityType == mSecurityType; + } + + /** + * Update security params to legacy WifiConfiguration object. + * + * @param config the target configuration. + */ + public void updateLegacyWifiConfiguration(WifiConfiguration config) { + config.allowedKeyManagement = (BitSet) mAllowedKeyManagement.clone(); + config.allowedProtocols = (BitSet) mAllowedProtocols.clone(); + config.allowedAuthAlgorithms = (BitSet) mAllowedAuthAlgorithms.clone(); + config.allowedPairwiseCiphers = (BitSet) mAllowedPairwiseCiphers.clone(); + config.allowedGroupCiphers = (BitSet) mAllowedGroupCiphers.clone(); + config.allowedGroupManagementCiphers = (BitSet) mAllowedGroupManagementCiphers.clone(); + config.allowedSuiteBCiphers = (BitSet) mAllowedSuiteBCiphers.clone(); + config.requirePmf = mRequirePmf; + } + + /** + * Set this params enabled. + * + * @param enable enable a specific security type. + */ + public void setEnabled(boolean enable) { + mEnabled = enable; + } + + /** + * Indicate this params is enabled or not. + */ + public boolean isEnabled() { + return mEnabled; + } + + /** + * Set the supporting Fast Initial Link Set-up (FILS) key management. + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + if (enableFilsSha256) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA256); + } + + if (enableFilsSha384) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA384); + } + } + + /** + * Get the copy of allowed key management. + */ + public BitSet getAllowedKeyManagement() { + return (BitSet) mAllowedKeyManagement.clone(); + } + + /** + * Get the copy of allowed protocols. + */ + public BitSet getAllowedProtocols() { + return (BitSet) mAllowedProtocols.clone(); + } + + /** + * Get the copy of allowed auth algorithms. + */ + public BitSet getAllowedAuthAlgorithms() { + return (BitSet) mAllowedAuthAlgorithms.clone(); + } + + /** + * Get the copy of allowed pairwise ciphers. + */ + public BitSet getAllowedPairwiseCiphers() { + return (BitSet) mAllowedPairwiseCiphers.clone(); + } + + /** + * Get the copy of allowed group ciphers. + */ + public BitSet getAllowedGroupCiphers() { + return (BitSet) mAllowedGroupCiphers.clone(); + } + + /** + * Get the copy of allowed group management ciphers. + */ + public BitSet getAllowedGroupManagementCiphers() { + return (BitSet) mAllowedGroupManagementCiphers.clone(); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + if (enableEcdheEcdsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_ECDSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_ECDSA); + } + + if (enableEcdheRsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_RSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_RSA); + } + } + + /** + * Get the copy of allowed suite-b ciphers. + */ + public BitSet getAllowedSuiteBCiphers() { + return (BitSet) mAllowedSuiteBCiphers.clone(); + } + + /** + * Indicate PMF is required or not. + */ + public boolean isRequirePmf() { + return mRequirePmf; + } + + /** + * Indicate that this is open security type. + */ + public boolean isOpenSecurityType() { + return isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN) + || isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE); + } + + /** + * Indicate that this is enterprise security type. + */ + public boolean isEnterpriseSecurityType() { + return mAllowedKeyManagement.get(KeyMgmt.WPA_EAP) + || mAllowedKeyManagement.get(KeyMgmt.IEEE8021X) + || mAllowedKeyManagement.get(KeyMgmt.SUITE_B_192) + || mAllowedKeyManagement.get(KeyMgmt.WAPI_CERT); + } + + /** + * Enable Hash-to-Element only mode. + * + * @param enable set H2E only mode enabled or not. + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mIsSaeH2eOnlyMode = enable; + } + + /** + * Indicate whether this params is H2E only mode. + * + * @return true if this is H2E only mode params. + */ + public boolean isSaeH2eOnlyMode() { + return mIsSaeH2eOnlyMode; + } + /** + * Enable Pubilc-Key only mode. + * + * @param enable set PK only mode enabled or not. + */ + public void enableSaePkOnlyMode(boolean enable) { + mIsSaePkOnlyMode = enable; + } + + /** + * Indicate whether this params is PK only mode. + * + * @return true if this is PK only mode params. + */ + public boolean isSaePkOnlyMode() { + return mIsSaePkOnlyMode; + } + + /** + * Set whether this is added by auto-upgrade. + * + * @param addedByAutoUpgrade true if added by auto-upgrade. + */ + public void setIsAddedByAutoUpgrade(boolean addedByAutoUpgrade) { + mIsAddedByAutoUpgrade = addedByAutoUpgrade; + } + + /** + * Indicate whether this is added by auto-upgrade or not. + * + * @return true if added by auto-upgrade; otherwise, false. + */ + public boolean isAddedByAutoUpgrade() { + return mIsAddedByAutoUpgrade; + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("Security Parameters:\n"); + sbuf.append(" Type: ").append(mSecurityType).append("\n"); + sbuf.append(" Enabled: ").append(mEnabled).append("\n"); + sbuf.append(" KeyMgmt:"); + for (int k = 0; k < mAllowedKeyManagement.size(); k++) { + if (mAllowedKeyManagement.get(k)) { + sbuf.append(" "); + if (k < KeyMgmt.strings.length) { + sbuf.append(KeyMgmt.strings[k]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" Protocols:"); + for (int p = 0; p < mAllowedProtocols.size(); p++) { + if (mAllowedProtocols.get(p)) { + sbuf.append(" "); + if (p < Protocol.strings.length) { + sbuf.append(Protocol.strings[p]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" AuthAlgorithms:"); + for (int a = 0; a < mAllowedAuthAlgorithms.size(); a++) { + if (mAllowedAuthAlgorithms.get(a)) { + sbuf.append(" "); + if (a < AuthAlgorithm.strings.length) { + sbuf.append(AuthAlgorithm.strings[a]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" PairwiseCiphers:"); + for (int pc = 0; pc < mAllowedPairwiseCiphers.size(); pc++) { + if (mAllowedPairwiseCiphers.get(pc)) { + sbuf.append(" "); + if (pc < PairwiseCipher.strings.length) { + sbuf.append(PairwiseCipher.strings[pc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupCiphers:"); + for (int gc = 0; gc < mAllowedGroupCiphers.size(); gc++) { + if (mAllowedGroupCiphers.get(gc)) { + sbuf.append(" "); + if (gc < GroupCipher.strings.length) { + sbuf.append(GroupCipher.strings[gc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupMgmtCiphers:"); + for (int gmc = 0; gmc < mAllowedGroupManagementCiphers.size(); gmc++) { + if (mAllowedGroupManagementCiphers.get(gmc)) { + sbuf.append(" "); + if (gmc < GroupMgmtCipher.strings.length) { + sbuf.append(GroupMgmtCipher.strings[gmc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" SuiteBCiphers:"); + for (int sbc = 0; sbc < mAllowedSuiteBCiphers.size(); sbc++) { + if (mAllowedSuiteBCiphers.get(sbc)) { + sbuf.append(" "); + if (sbc < SuiteBCipher.strings.length) { + sbuf.append(SuiteBCipher.strings[sbc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" RequirePmf: ").append(mRequirePmf).append('\n'); + sbuf.append(" IsAddedByAutoUpgrade: ").append(mIsAddedByAutoUpgrade).append("\n"); + sbuf.append(" IsSaeH2eOnlyMode: ").append(mIsSaeH2eOnlyMode).append("\n"); + sbuf.append(" IsSaePkOnlyMode: ").append(mIsSaePkOnlyMode).append("\n"); + return sbuf.toString(); + } + + private static BitSet readBitSet(Parcel src) { + int cardinality = src.readInt(); + + BitSet set = new BitSet(); + for (int i = 0; i < cardinality; i++) { + set.set(src.readInt()); + } + + return set; + } + + private static void writeBitSet(Parcel dest, BitSet set) { + int nextSetBit = -1; + + dest.writeInt(set.cardinality()); + + while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { + dest.writeInt(nextSetBit); + } + } + + /** Write this object to the parcel. */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSecurityType); + dest.writeBoolean(mEnabled); + writeBitSet(dest, mAllowedKeyManagement); + writeBitSet(dest, mAllowedProtocols); + writeBitSet(dest, mAllowedAuthAlgorithms); + writeBitSet(dest, mAllowedPairwiseCiphers); + writeBitSet(dest, mAllowedGroupCiphers); + writeBitSet(dest, mAllowedGroupManagementCiphers); + writeBitSet(dest, mAllowedSuiteBCiphers); + dest.writeBoolean(mRequirePmf); + dest.writeBoolean(mIsAddedByAutoUpgrade); + dest.writeBoolean(mIsSaeH2eOnlyMode); + dest.writeBoolean(mIsSaePkOnlyMode); + + } + + /** Create a SecurityParams object from the parcel. */ + public static final @NonNull SecurityParams createFromParcel(Parcel in) { + SecurityParams params = new SecurityParams(); + params.mSecurityType = in.readInt(); + params.mEnabled = in.readBoolean(); + params.mAllowedKeyManagement = readBitSet(in); + params.mAllowedProtocols = readBitSet(in); + params.mAllowedAuthAlgorithms = readBitSet(in); + params.mAllowedPairwiseCiphers = readBitSet(in); + params.mAllowedGroupCiphers = readBitSet(in); + params.mAllowedGroupManagementCiphers = readBitSet(in); + params.mAllowedSuiteBCiphers = readBitSet(in); + params.mRequirePmf = in.readBoolean(); + params.mIsAddedByAutoUpgrade = in.readBoolean(); + params.mIsSaeH2eOnlyMode = in.readBoolean(); + params.mIsSaePkOnlyMode = in.readBoolean(); + return params; + } + + /** + * Create EAP security params. + */ + public static @NonNull SecurityParams createWpaWpa2EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create Passpoint security params. + */ + public static @NonNull SecurityParams createPasspointParams(@PasspointRelease int release) { + SecurityParams params = new SecurityParams(); + switch (release) { + case PASSPOINT_R1: + case PASSPOINT_R2: + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + break; + case PASSPOINT_R3: + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3; + params.mRequirePmf = true; + break; + default: + throw new IllegalArgumentException("invalid passpoint release " + release); + } + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + + return params; + } + + /** + * Create Enhanced Open params. + */ + public static @NonNull SecurityParams createEnhancedOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + + params.mAllowedKeyManagement.set(KeyMgmt.OWE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create Open params. + */ + public static @NonNull SecurityParams createOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + return params; + } + + /** + * Create OSEN params. + */ + public static @NonNull SecurityParams createOsenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + + params.mAllowedKeyManagement.set(KeyMgmt.OSEN); + + params.mAllowedProtocols.set(Protocol.OSEN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create WAPI-CERT params. + */ + public static @NonNull SecurityParams createWapiCertParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_CERT); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WAPI-PSK params. + */ + public static @NonNull SecurityParams createWapiPskParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_PSK); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WEP params. + */ + public static @NonNull SecurityParams createWepParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.OPEN); + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.SHARED); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } + + /** + * Create WPA3 Enterprise 192-bit params. + */ + public static @NonNull SecurityParams createWpa3Enterprise192BitParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + params.mAllowedKeyManagement.set(KeyMgmt.SUITE_B_192); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mAllowedGroupManagementCiphers.set(GroupMgmtCipher.BIP_GMAC_256); + + // Note: allowedSuiteBCiphers bitset will be set by the service once the + // certificates are attached to this profile + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Enterprise params. + */ + public static @NonNull SecurityParams createWpa3EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Personal params. + */ + public static @NonNull SecurityParams createWpa3PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + + params.mAllowedKeyManagement.set(KeyMgmt.SAE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA/WPA2 Personal params. + */ + public static @NonNull SecurityParams createWpaWpa2PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_PSK); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } +} diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java index d570b7e8afa9..6f72f0b58b4b 100644 --- a/wifi/java/android/net/wifi/SoftApCapability.java +++ b/wifi/java/android/net/wifi/SoftApCapability.java @@ -116,6 +116,11 @@ public final class SoftApCapability implements Parcelable { private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY; /** + * A list storing supported 60G channels. + */ + private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY; + + /** * Get the maximum supported client numbers which AP resides on. */ public int getMaxSupportedClients() { @@ -147,8 +152,8 @@ public final class SoftApCapability implements Parcelable { * Set supported channel list in target band type. * * @param band One of the following band types: - * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or - * {@link SoftApConfiguation#BAND_6GHZ}. + * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ}, + * {@link SoftApConfiguation#BAND_6GHZ}, or {@link SoftApConfiguation#BAND_60GHZ}. * @param supportedChannelList supported channel list in target band * @return true if band and supportedChannelList are valid, otherwise false. * @@ -168,6 +173,9 @@ public final class SoftApCapability implements Parcelable { case SoftApConfiguration.BAND_6GHZ: mSupportedChannelListIn6g = supportedChannelList; break; + case SoftApConfiguration.BAND_60GHZ: + mSupportedChannelListIn60g = supportedChannelList; + break; default: throw new IllegalArgumentException("Invalid band: " + band); } @@ -181,8 +189,8 @@ public final class SoftApCapability implements Parcelable { * {@link SoftapConfiguration.Builder#setChannel(int, int)} API. * * @param band One of the following band types: - * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or - * {@link SoftApConfiguation#BAND_6GHZ}. + * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ}, + * {@link SoftApConfiguation#BAND_6GHZ}, {@link SoftApConfiguation#BAND_60GHZ}. * @return List of supported channels for the band. * * @throws IllegalArgumentException when band type is invalid. @@ -199,6 +207,8 @@ public final class SoftApCapability implements Parcelable { return mSupportedChannelListIn5g; case SoftApConfiguration.BAND_6GHZ: return mSupportedChannelListIn6g; + case SoftApConfiguration.BAND_60GHZ: + return mSupportedChannelListIn60g; default: throw new IllegalArgumentException("Invalid band: " + band); } @@ -214,6 +224,7 @@ public final class SoftApCapability implements Parcelable { mSupportedChannelListIn24g = source.mSupportedChannelListIn24g; mSupportedChannelListIn5g = source.mSupportedChannelListIn5g; mSupportedChannelListIn6g = source.mSupportedChannelListIn6g; + mSupportedChannelListIn60g = source.mSupportedChannelListIn60g; } } @@ -244,6 +255,7 @@ public final class SoftApCapability implements Parcelable { dest.writeIntArray(mSupportedChannelListIn24g); dest.writeIntArray(mSupportedChannelListIn5g); dest.writeIntArray(mSupportedChannelListIn6g); + dest.writeIntArray(mSupportedChannelListIn60g); } @NonNull @@ -255,6 +267,7 @@ public final class SoftApCapability implements Parcelable { capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray()); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray()); capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray()); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray()); return capability; } @@ -273,6 +286,8 @@ public final class SoftApCapability implements Parcelable { .append(Arrays.toString(mSupportedChannelListIn24g)); sbuf.append("SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g)); sbuf.append("SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g)); + sbuf.append("SupportedChannelListIn60g") + .append(Arrays.toString(mSupportedChannelListIn60g)); return sbuf.toString(); } @@ -285,7 +300,8 @@ public final class SoftApCapability implements Parcelable { && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g) && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g) - && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g); + && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g) + && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g); } @Override @@ -293,6 +309,7 @@ public final class SoftApCapability implements Parcelable { return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber, Arrays.hashCode(mSupportedChannelListIn24g), Arrays.hashCode(mSupportedChannelListIn5g), - Arrays.hashCode(mSupportedChannelListIn6g)); + Arrays.hashCode(mSupportedChannelListIn6g), + Arrays.hashCode(mSupportedChannelListIn60g)); } } diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index e9d1a008eb5f..d36acb72ff8a 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -88,6 +88,13 @@ public final class SoftApConfiguration implements Parcelable { public static final int BAND_6GHZ = 1 << 2; /** + * 60GHz band. + * @hide + */ + @SystemApi + public static final int BAND_60GHZ = 1 << 3; + + /** * Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability, * operating country code and current radio conditions. * @hide @@ -104,11 +111,13 @@ public final class SoftApConfiguration implements Parcelable { BAND_2GHZ, BAND_5GHZ, BAND_6GHZ, + BAND_60GHZ, }) public @interface BandType {} private static boolean isBandValid(@BandType int band) { - return ((band != 0) && ((band & ~BAND_ANY) == 0)); + int bandAny = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ | BAND_60GHZ; + return ((band != 0) && ((band & ~bandAny) == 0)); } private static final int MIN_CH_2G_BAND = 1; @@ -117,6 +126,8 @@ public final class SoftApConfiguration implements Parcelable { private static final int MAX_CH_5G_BAND = 196; private static final int MIN_CH_6G_BAND = 1; private static final int MAX_CH_6G_BAND = 253; + private static final int MIN_CH_60G_BAND = 1; + private static final int MAX_CH_60G_BAND = 6; @@ -139,6 +150,13 @@ public final class SoftApConfiguration implements Parcelable { return false; } break; + + case BAND_60GHZ: + if (channel < MIN_CH_60G_BAND || channel > MAX_CH_60G_BAND) { + return false; + } + break; + default: return false; } @@ -538,7 +556,7 @@ public final class SoftApConfiguration implements Parcelable { if (!SdkLevel.isAtLeastS()) { throw new UnsupportedOperationException(); } - return mChannels; + return mChannels.clone(); } /** @@ -926,6 +944,9 @@ public final class SoftApConfiguration implements Parcelable { * on the requested bands (if possible). * <p> * + * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine + * whether or not concurrent APs are supported. + * * @param bands Array of the {@link #BandType}. * @return Builder for chaining. * @throws IllegalArgumentException when more than 2 bands are set or an invalid band type @@ -933,6 +954,9 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setBands(@NonNull int[] bands) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } if (bands.length == 0 || bands.length > 2) { throw new IllegalArgumentException("Unsupported number of bands(" + bands.length + ") configured"); @@ -998,6 +1022,9 @@ public final class SoftApConfiguration implements Parcelable { * The {@link SoftApCapability#getSupportedChannelList(int)} can be used to obtain * valid channels in each band. * + * Use {@link WifiManager#isBridgedApConcurrencySupported()} to determine + * whether or not concurrent APs are supported. + * * <p> * If not set, the default for the channel is the special value 0 which has the framework * auto-select a valid channel from the band configured with {@link #setBands(int[])}. @@ -1021,6 +1048,9 @@ public final class SoftApConfiguration implements Parcelable { */ @NonNull public Builder setChannels(@NonNull SparseIntArray channels) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } if (channels.size() == 0 || channels.size() > 2) { throw new IllegalArgumentException("Unsupported number of channels(" + channels.size() + ") configured"); diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java index 9a16facfec26..e42e7868e944 100644 --- a/wifi/java/android/net/wifi/SoftApInfo.java +++ b/wifi/java/android/net/wifi/SoftApInfo.java @@ -86,6 +86,34 @@ public final class SoftApInfo implements Parcelable { */ public static final int CHANNEL_WIDTH_160MHZ = 6; + /** + * AP Channel bandwidth is 2160 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_2160MHZ = 7; + + /** + * AP Channel bandwidth is 4320 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_4320MHZ = 8; + + /** + * AP Channel bandwidth is 6480 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_6480MHZ = 9; + + /** + * AP Channel bandwidth is 8640 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_8640MHZ = 10; + /** The frequency which AP resides on. */ private int mFrequency = 0; @@ -96,6 +124,10 @@ public final class SoftApInfo implements Parcelable { @Nullable private MacAddress mBssid; + /** The identifier of the AP instance which AP resides on with current info. */ + @Nullable + private String mApInstanceIdentifier; + /** * The operational mode of the AP. */ @@ -121,7 +153,9 @@ public final class SoftApInfo implements Parcelable { * * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, - * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_INVALID}. + * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, {@link #CHANNEL_WIDTH_2160MHZ}, + * {@link #CHANNEL_WIDTH_4320MHZ}, {@link #CHANNEL_WIDTH_6480MHZ}, + * {@link #CHANNEL_WIDTH_8640MHZ}, or {@link #CHANNEL_WIDTH_INVALID}. */ @WifiAnnotations.Bandwidth public int getBandwidth() { @@ -187,6 +221,28 @@ public final class SoftApInfo implements Parcelable { } /** + * Set the AP instance identifier. + * @hide + */ + public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) { + mApInstanceIdentifier = apInstanceIdentifier; + } + + /** + * Get the AP instance identifier. + * + * The AP instance identifier is a unique identity which can be used to + * associate the {@link SoftApInfo} to a specific {@link WifiClient} + * - see {@link WifiClient#getApInstanceIdentifier()} + * + * @hide + */ + @Nullable + public String getApInstanceIdentifier() { + return mApInstanceIdentifier; + } + + /** * @hide */ public SoftApInfo(@Nullable SoftApInfo source) { @@ -195,6 +251,7 @@ public final class SoftApInfo implements Parcelable { mBandwidth = source.mBandwidth; mBssid = source.mBssid; mWifiStandard = source.mWifiStandard; + mApInstanceIdentifier = source.mApInstanceIdentifier; } } @@ -217,6 +274,7 @@ public final class SoftApInfo implements Parcelable { dest.writeInt(mBandwidth); dest.writeParcelable(mBssid, flags); dest.writeInt(mWifiStandard); + dest.writeString(mApInstanceIdentifier); } @NonNull @@ -228,6 +286,7 @@ public final class SoftApInfo implements Parcelable { info.mBandwidth = in.readInt(); info.mBssid = in.readParcelable(MacAddress.class.getClassLoader()); info.mWifiStandard = in.readInt(); + info.mApInstanceIdentifier = in.readString(); return info; } @@ -245,6 +304,7 @@ public final class SoftApInfo implements Parcelable { sbuf.append(", frequency= ").append(mFrequency); if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString()); sbuf.append(", wifiStandard= ").append(mWifiStandard); + sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier); sbuf.append("}"); return sbuf.toString(); } @@ -257,11 +317,12 @@ public final class SoftApInfo implements Parcelable { return mFrequency == softApInfo.mFrequency && mBandwidth == softApInfo.mBandwidth && Objects.equals(mBssid, softApInfo.mBssid) - && mWifiStandard == softApInfo.mWifiStandard; + && mWifiStandard == softApInfo.mWifiStandard + && Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier); } @Override public int hashCode() { - return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard); + return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier); } } diff --git a/wifi/java/android/net/wifi/WifiAnnotations.java b/wifi/java/android/net/wifi/WifiAnnotations.java index acda7e06c95d..807b40b5722c 100644 --- a/wifi/java/android/net/wifi/WifiAnnotations.java +++ b/wifi/java/android/net/wifi/WifiAnnotations.java @@ -57,6 +57,10 @@ public final class WifiAnnotations { SoftApInfo.CHANNEL_WIDTH_80MHZ, SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ, SoftApInfo.CHANNEL_WIDTH_160MHZ, + SoftApInfo.CHANNEL_WIDTH_2160MHZ, + SoftApInfo.CHANNEL_WIDTH_4320MHZ, + SoftApInfo.CHANNEL_WIDTH_6480MHZ, + SoftApInfo.CHANNEL_WIDTH_8640MHZ, }) @Retention(RetentionPolicy.SOURCE) public @interface Bandwidth {} @@ -77,6 +81,7 @@ public final class WifiAnnotations { ScanResult.WIFI_STANDARD_11N, ScanResult.WIFI_STANDARD_11AC, ScanResult.WIFI_STANDARD_11AX, + ScanResult.WIFI_STANDARD_11AD, }) @Retention(RetentionPolicy.SOURCE) public @interface WifiStandard{} diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java index 3794566f3d8f..85e2b3312b29 100644 --- a/wifi/java/android/net/wifi/WifiClient.java +++ b/wifi/java/android/net/wifi/WifiClient.java @@ -30,6 +30,9 @@ public final class WifiClient implements Parcelable { private final MacAddress mMacAddress; + /** The identifier of the AP instance which the client connected. */ + private final String mApInstanceIdentifier; + /** * The mac address of this client. */ @@ -38,15 +41,30 @@ public final class WifiClient implements Parcelable { return mMacAddress; } + /** + * Get AP instance identifier. + * + * The AP instance identifier is a unique identity which can be used to + * associate the {@link SoftApInfo} to a specific {@link WifiClient} + * - see {@link SoftApInfo#getApInstanceIdentifier()} + * @hide + */ + @NonNull + public String getApInstanceIdentifier() { + return mApInstanceIdentifier; + } + private WifiClient(Parcel in) { mMacAddress = in.readParcelable(null); + mApInstanceIdentifier = in.readString(); } /** @hide */ - public WifiClient(@NonNull MacAddress macAddress) { + public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) { Objects.requireNonNull(macAddress, "mMacAddress must not be null."); this.mMacAddress = macAddress; + this.mApInstanceIdentifier = apInstanceIdentifier; } @Override @@ -57,6 +75,7 @@ public final class WifiClient implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mMacAddress, flags); + dest.writeString(mApInstanceIdentifier); } @NonNull @@ -75,6 +94,7 @@ public final class WifiClient implements Parcelable { public String toString() { return "WifiClient{" + "mMacAddress=" + mMacAddress + + "mApInstanceIdentifier=" + mApInstanceIdentifier + '}'; } @@ -83,13 +103,12 @@ public final class WifiClient implements Parcelable { if (this == o) return true; if (!(o instanceof WifiClient)) return false; WifiClient client = (WifiClient) o; - return mMacAddress.equals(client.mMacAddress); + return Objects.equals(mMacAddress, client.mMacAddress) + && mApInstanceIdentifier.equals(client.mApInstanceIdentifier); } @Override public int hashCode() { - return Objects.hash(mMacAddress); + return Objects.hash(mMacAddress, mApInstanceIdentifier); } } - - diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 34a6938097ce..ba4a54f9a489 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -19,6 +19,7 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.PackageManager; @@ -29,7 +30,6 @@ import android.net.NetworkSpecifier; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.net.Uri; -import android.net.util.MacAddressUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -43,13 +43,17 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; +import java.util.List; /** * A class representing a configured Wi-Fi network, including the @@ -250,6 +254,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int WAPI = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WPA, RSN, OSEN, WAPI}) + public @interface ProtocolScheme {}; + public static final String varName = "proto"; public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" }; @@ -274,6 +283,11 @@ public class WifiConfiguration implements Parcelable { /** SAE (Used only for WPA3-Personal) */ public static final int SAE = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {OPEN, SHARED, LEAP, SAE}) + public @interface AuthAlgorithmScheme {}; + public static final String varName = "auth_alg"; public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" }; @@ -308,6 +322,10 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 5; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128}) + public @interface PairwiseCipherScheme {}; public static final String varName = "pairwise"; @@ -359,6 +377,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 7; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128}) + public @interface GroupCipherScheme {}; + public static final String varName = "group"; public static final String[] strings = @@ -387,9 +410,16 @@ public class WifiConfiguration implements Parcelable { /** GMAC-256 = Galois Message Authentication Code */ public static final int BIP_GMAC_256 = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256}) + public @interface GroupMgmtCipherScheme {}; + private static final String varName = "groupMgmt"; - private static final String[] strings = { "BIP_CMAC_256", + /** @hide */ + @SuppressLint("AllUpper") + public static final @NonNull String[] strings = { "BIP_CMAC_256", "BIP_GMAC_128", "BIP_GMAC_256"}; } @@ -410,9 +440,16 @@ public class WifiConfiguration implements Parcelable { /** Diffie-Hellman with_RSA signature */ public static final int ECDHE_RSA = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA}) + public @interface SuiteBCipherScheme {}; + private static final String varName = "SuiteB"; - private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; + /** @hide */ + @SuppressLint("AllUpper") + public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; } /** Possible status of a network configuration. */ @@ -439,8 +476,19 @@ public class WifiConfiguration implements Parcelable { public static final int SECURITY_TYPE_EAP = 3; /** Security type for an SAE network. */ public static final int SECURITY_TYPE_SAE = 4; - /** Security type for an EAP Suite B network. */ - public static final int SECURITY_TYPE_EAP_SUITE_B = 5; + /** + * Security type for a WPA3-Enterprise in 192-bit security network. + * This is the same as {@link #SECURITY_TYPE_EAP_SUITE_B} and uses the same value. + */ + public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT = 5; + /** + * Security type for a WPA3-Enterprise in 192-bit security network. + * @deprecated Use the {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} constant + * (which is the same value). + */ + @Deprecated + public static final int SECURITY_TYPE_EAP_SUITE_B = + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; /** Security type for an OWE network. */ public static final int SECURITY_TYPE_OWE = 6; /** Security type for a WAPI PSK network. */ @@ -449,6 +497,25 @@ public class WifiConfiguration implements Parcelable { public static final int SECURITY_TYPE_WAPI_CERT = 8; /** Security type for a WPA3-Enterprise network. */ public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9; + /** + * Security type for an OSEN network. + * @hide + */ + public static final int SECURITY_TYPE_OSEN = 10; + /** + * Security type for a Passpoint R1/R2 network. + * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed. + * @hide + */ + public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11; + + /** + * Security type for a Passpoint R3 network. + * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed, + * and PMF must be set to Required. + * @hide + */ + public static final int SECURITY_TYPE_PASSPOINT_R3 = 12; /** * Security types we support. @@ -466,12 +533,24 @@ public class WifiConfiguration implements Parcelable { SECURITY_TYPE_WAPI_PSK, SECURITY_TYPE_WAPI_CERT, SECURITY_TYPE_EAP_WPA3_ENTERPRISE, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, + SECURITY_TYPE_PASSPOINT_R1_R2, + SECURITY_TYPE_PASSPOINT_R3, }) public @interface SecurityType {} + private List<SecurityParams> mSecurityParamsList = new ArrayList<>(); + + private void updateLegacySecurityParams() { + if (mSecurityParamsList.isEmpty()) return; + mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this); + } + /** * Set the various security params to correspond to the provided security type. * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * <br> + * This API would clear existing security types and add a default one. * * @param securityType One of the following security types: * {@link #SECURITY_TYPE_OPEN}, @@ -479,99 +558,358 @@ public class WifiConfiguration implements Parcelable { * {@link #SECURITY_TYPE_PSK}, * {@link #SECURITY_TYPE_EAP}, * {@link #SECURITY_TYPE_SAE}, - * {@link #SECURITY_TYPE_EAP_SUITE_B}, * {@link #SECURITY_TYPE_OWE}, * {@link #SECURITY_TYPE_WAPI_PSK}, * {@link #SECURITY_TYPE_WAPI_CERT}, - * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE} + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, */ public void setSecurityParams(@SecurityType int securityType) { - // Clear all the bitsets. - allowedKeyManagement.clear(); - allowedProtocols.clear(); - allowedAuthAlgorithms.clear(); - allowedPairwiseCiphers.clear(); - allowedGroupCiphers.clear(); - allowedGroupManagementCiphers.clear(); - allowedSuiteBCiphers.clear(); + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(securityType); + } + /** + * Add the various security params. + * <br> + * This API would clear existing security types and add a default one. + * @hide + */ + public void setSecurityParams(SecurityParams params) { + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(params); + } + + /** + * Add the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @hide + */ + public void addSecurityParams(@SecurityType int securityType) { + // This ensures that there won't be duplicate security types. + if (mSecurityParamsList.stream().anyMatch(params -> params.isSecurityType(securityType))) { + throw new IllegalArgumentException("duplicate security type " + securityType); + } + SecurityParams params = null; switch (securityType) { case SECURITY_TYPE_OPEN: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + params = SecurityParams.createOpenParams(); break; case SECURITY_TYPE_WEP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); + params = SecurityParams.createWepParams(); break; case SECURITY_TYPE_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + params = SecurityParams.createWpaWpa2PersonalParams(); break; case SECURITY_TYPE_EAP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); + params = SecurityParams.createWpaWpa2EnterpriseParams(); break; case SECURITY_TYPE_SAE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3PersonalParams(); break; - case SECURITY_TYPE_EAP_SUITE_B: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - // Note: allowedSuiteBCiphers bitset will be set by the service once the - // certificates are attached to this profile - requirePmf = true; + // The value of {@link SECURITY_TYPE_EAP_SUITE_B} is the same as + // {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid + // duplicate case label errors. + case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT: + params = SecurityParams.createWpa3Enterprise192BitParams(); break; case SECURITY_TYPE_OWE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createEnhancedOpenParams(); break; case SECURITY_TYPE_WAPI_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiPskParams(); break; case SECURITY_TYPE_WAPI_CERT: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiCertParams(); break; case SECURITY_TYPE_EAP_WPA3_ENTERPRISE: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3EnterpriseParams(); + break; + case SECURITY_TYPE_OSEN: + params = SecurityParams.createOsenParams(); + break; + case SECURITY_TYPE_PASSPOINT_R1_R2: + params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2); + break; + case SECURITY_TYPE_PASSPOINT_R3: + params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3); break; default: throw new IllegalArgumentException("unknown security type " + securityType); } + + addSecurityParams(params); + } + + /** @hide */ + public void addSecurityParams(@NonNull SecurityParams newParams) { + if (mSecurityParamsList.stream().anyMatch(params -> params.isSameSecurityType(newParams))) { + throw new IllegalArgumentException("duplicate security params " + newParams); + } + if (!mSecurityParamsList.isEmpty()) { + if (newParams.isEnterpriseSecurityType() && !isEnterprise()) { + throw new IllegalArgumentException( + "An enterprise security type cannot be added to a personal configuation."); + } + if (!newParams.isEnterpriseSecurityType() && isEnterprise()) { + throw new IllegalArgumentException( + "A personal security type cannot be added to an enterprise configuation."); + } + if (newParams.isOpenSecurityType() && !isOpenNetwork()) { + throw new IllegalArgumentException( + "An open security type cannot be added to a non-open configuation."); + } + if (!newParams.isOpenSecurityType() && isOpenNetwork()) { + throw new IllegalArgumentException( + "A non-open security type cannot be added to an open configuation."); + } + if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) { + throw new IllegalArgumentException( + "An OSEN security type must be the only one type."); + } + } + mSecurityParamsList.add(new SecurityParams(newParams)); + updateLegacySecurityParams(); + } + + /** + * If there is no security params, generate one according to legacy fields. + * @hide + */ + public void convertLegacyFieldsToSecurityParamsIfNeeded() { + if (!mSecurityParamsList.isEmpty()) return; + + if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { + setSecurityParams(SECURITY_TYPE_WAPI_CERT); + } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { + setSecurityParams(SECURITY_TYPE_WAPI_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + setSecurityParams(SECURITY_TYPE_OWE); + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + setSecurityParams(SECURITY_TYPE_SAE); + } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { + setSecurityParams(SECURITY_TYPE_OSEN); + } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { + if (requirePmf) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } else { + setSecurityParams(SECURITY_TYPE_EAP); + } + } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.NONE)) { + if (hasWepKeys()) { + setSecurityParams(SECURITY_TYPE_WEP); + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } + + /** + * Disable the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @hide + */ + public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .ifPresent(params -> params.setEnabled(enable)); + } + + /** + * Get the specific security param. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @return the copy of specific security params if found; otherwise null. + * @hide + */ + public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) { + SecurityParams p = mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .orElse(null); + return (p != null) ? new SecurityParams(p) : null; + } + + /** + * Indicate whether this configuration is the specific security type. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @return true if there is a security params matches the type. + * @hide + */ + public boolean isSecurityType(@SecurityType int securityType) { + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(securityType)); + } + + /** + * Get the security params list of this configuration. + * + * The returning list is a priority list, the first is the lowest priority and default one. + * + * @return this list of security params. + * @hide + */ + public List<SecurityParams> getSecurityParamsList() { + return Collections.unmodifiableList(mSecurityParamsList); + } + + /** + * Enable the support of Fast Initial Link Set-up (FILS). + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + * @hide + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + mSecurityParamsList.stream() + .forEach(params -> params.enableFils(enableFilsSha256, enableFilsSha384)); + updateLegacySecurityParams(); + } + + /** + * Indicate FILS SHA256 is enabled. + * + * @return true if FILS SHA256 is enabled. + * @hide + */ + public boolean isFilsSha256Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256)); + } + + /** + * Indicate FILS SHA384 is enabled. + * + * @return true if FILS SHA384 is enabled. + * @hide + */ + public boolean isFilsSha384Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384)); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + * @hide + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT)) + .findAny() + .ifPresent(params -> params.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa)); + updateLegacySecurityParams(); + } + + /** + * Indicate ECDHE_ECDSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheEcdsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA)); + } + + /** + * Indicate ECDHE_RSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheRsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA)); + } + + /** + * Set SAE Hash-toElement only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaeH2eOnlyMode(enable)); + } + + /** + * Set SAE Public-Key only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaePkOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaePkOnlyMode(enable)); } /** @hide */ @@ -1037,6 +1375,15 @@ public class WifiConfiguration implements Parcelable { public boolean oemPrivate; /** + * Indicate whether or not the network is a carrier merged network. + * This bit can only be used by suggestion network, see + * {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} + * @hide + */ + @SystemApi + public boolean carrierMerged; + + /** * True if this Wifi configuration is created from a {@link WifiNetworkSuggestion}, * false otherwise. * @@ -1136,27 +1483,25 @@ public class WifiConfiguration implements Parcelable { return metered; } + /** Check whether wep keys exist. */ + private boolean hasWepKeys() { + if (wepKeys == null) return false; + for (int i = 0; i < wepKeys.length; i++) { + if (wepKeys[i] != null) { + return true; + } + } + return false; + } + /** * @hide - * Returns true if this WiFi config is for an open network. + * Returns true if this WiFi config is for an Open or Enhanced Open network. */ public boolean isOpenNetwork() { - final int cardinality = allowedKeyManagement.cardinality(); - final boolean hasNoKeyMgmt = cardinality == 0 - || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) - || allowedKeyManagement.get(KeyMgmt.OWE))); - - boolean hasNoWepKeys = true; - if (wepKeys != null) { - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeys[i] != null) { - hasNoWepKeys = false; - break; - } - } - } - - return hasNoKeyMgmt && hasNoWepKeys; + boolean hasNonOpenSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> !params.isOpenSecurityType()); + return !hasNonOpenSecurityType && !hasWepKeys(); } /** @@ -1363,7 +1708,9 @@ public class WifiConfiguration implements Parcelable { DISABLED_NO_INTERNET_PERMANENT, DISABLED_BY_WIFI_MANAGER, DISABLED_BY_WRONG_PASSWORD, - DISABLED_AUTHENTICATION_NO_SUBSCRIPTION}) + DISABLED_AUTHENTICATION_NO_SUBSCRIPTION, + DISABLED_AUTHENTICATION_FAILURE_GENERIC, + DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC}) public @interface NetworkSelectionDisableReason {} // Quality Network disabled reasons @@ -1376,8 +1723,16 @@ public class WifiConfiguration implements Parcelable { public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1; /** This network is temporarily disabled because of multiple association rejections. */ public static final int DISABLED_ASSOCIATION_REJECTION = 1; - /** This network is temporarily disabled because of multiple authentication failure. */ - public static final int DISABLED_AUTHENTICATION_FAILURE = 2; + /** This network is disabled due to generic authentication failure. */ + public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2; + /** Separate DISABLED_AUTHENTICATION_FAILURE into DISABLED_AUTHENTICATION_FAILURE_GENERIC + * and DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC + * @deprecated Use the {@link #DISABLED_AUTHENTICATION_FAILURE_GENERIC} constant + * (which is the same value). + */ + @Deprecated + public static final int DISABLED_AUTHENTICATION_FAILURE = + DISABLED_AUTHENTICATION_FAILURE_GENERIC; /** This network is temporarily disabled because of multiple DHCP failure. */ public static final int DISABLED_DHCP_FAILURE = 3; /** This network is temporarily disabled because it has no Internet access. */ @@ -1395,11 +1750,13 @@ public class WifiConfiguration implements Parcelable { public static final int DISABLED_BY_WRONG_PASSWORD = 8; /** This network is permanently disabled because service is not subscribed. */ public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; + /** This network is disabled due to carrier specific EAP failure. */ + public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10; /** * All other disable reasons should be strictly less than this value. * @hide */ - public static final int NETWORK_SELECTION_DISABLED_MAX = 10; + public static final int NETWORK_SELECTION_DISABLED_MAX = 11; /** * Get an integer that is equal to the maximum integer value of all the @@ -1539,6 +1896,18 @@ public class WifiConfiguration implements Parcelable { 1, Integer.MAX_VALUE)); + reasons.append(DISABLED_AUTHENTICATION_FAILURE_GENERIC, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_GENERIC", + 5, + 5 * 60 * 1000)); + + reasons.append(DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC, + new DisableReasonInfo( + "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC", + 1, + Integer.MAX_VALUE)); + return reasons; } @@ -1613,6 +1982,11 @@ public class WifiConfiguration implements Parcelable { private String mConnectChoice; /** + * The RSSI when the user made the connectChoice. + */ + private int mConnectChoiceRssi; + + /** * Used to cache the temporary candidate during the network selection procedure. It will be * kept updating once a new scan result has a higher score than current one */ @@ -1723,6 +2097,23 @@ public class WifiConfiguration implements Parcelable { mConnectChoice = newConnectChoice; } + /** + * Associate a RSSI with the user connect choice network. + * @param rssi signal strength + * @hide + */ + public void setConnectChoiceRssi(int rssi) { + mConnectChoiceRssi = rssi; + } + + /** + * @return returns the RSSI of the last time the user made the connect choice. + * @hide + */ + public int getConnectChoiceRssi() { + return mConnectChoiceRssi; + } + /** Get the current Quality network selection status as a String (for debugging). */ @NonNull public String getNetworkStatusString() { @@ -2026,6 +2417,7 @@ public class WifiConfiguration implements Parcelable { setCandidate(source.getCandidate()); setCandidateScore(source.getCandidateScore()); setConnectChoice(source.getConnectChoice()); + setConnectChoiceRssi(source.getConnectChoiceRssi()); setHasEverConnected(source.hasEverConnected()); setHasNeverDetectedCaptivePortal(source.hasNeverDetectedCaptivePortal()); } @@ -2043,6 +2435,7 @@ public class WifiConfiguration implements Parcelable { if (getConnectChoice() != null) { dest.writeInt(CONNECT_CHOICE_EXISTS); dest.writeString(getConnectChoice()); + dest.writeInt(getConnectChoiceRssi()); } else { dest.writeInt(CONNECT_CHOICE_NOT_EXISTS); } @@ -2062,6 +2455,7 @@ public class WifiConfiguration implements Parcelable { setNetworkSelectionBSSID(in.readString()); if (in.readInt() == CONNECT_CHOICE_EXISTS) { setConnectChoice(in.readString()); + setConnectChoiceRssi(in.readInt()); } else { setConnectChoice(null); } @@ -2267,6 +2661,7 @@ public class WifiConfiguration implements Parcelable { trusted = true; // Networks are considered trusted by default. oemPaid = false; oemPrivate = false; + carrierMerged = false; fromWifiNetworkSuggestion = false; fromWifiNetworkSpecifier = false; meteredHint = false; @@ -2314,12 +2709,11 @@ public class WifiConfiguration implements Parcelable { */ @UnsupportedAppUsage public boolean isEnterprise() { - return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) - || allowedKeyManagement.get(KeyMgmt.IEEE8021X) - || allowedKeyManagement.get(KeyMgmt.SUITE_B_192) - || allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) + boolean hasEnterpriseSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> params.isEnterpriseSecurityType()); + return (hasEnterpriseSecurityType && enterpriseConfig != null - && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; + && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE); } private static String logTimeOfDay(long millis) { @@ -2372,6 +2766,8 @@ public class WifiConfiguration implements Parcelable { } if (mNetworkSelectionStatus.getConnectChoice() != null) { sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice()); + sbuf.append(" connect choice rssi: ") + .append(mNetworkSelectionStatus.getConnectChoiceRssi()); } sbuf.append(" hasEverConnected: ") .append(mNetworkSelectionStatus.hasEverConnected()).append("\n"); @@ -2391,12 +2787,13 @@ public class WifiConfiguration implements Parcelable { if (this.trusted) sbuf.append(" trusted"); if (this.oemPaid) sbuf.append(" oemPaid"); if (this.oemPrivate) sbuf.append(" oemPrivate"); + if (this.carrierMerged) sbuf.append(" carrierMerged"); if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion"); if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier"); if (this.meteredHint) sbuf.append(" meteredHint"); if (this.useExternalScores) sbuf.append(" useExternalScores"); if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid - || this.oemPrivate || this.fromWifiNetworkSuggestion + || this.oemPrivate || this.carrierMerged || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) { sbuf.append("\n"); } @@ -2498,6 +2895,10 @@ public class WifiConfiguration implements Parcelable { sbuf.append('*'); } + sbuf.append("\nSecurityParams List:\n"); + mSecurityParamsList.stream() + .forEach(params -> sbuf.append(params.toString())); + sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); @@ -2720,17 +3121,18 @@ public class WifiConfiguration implements Parcelable { } /** - * Get a key for this WifiConfig to generate Persist random Mac Address. + * Get a unique key which represent this Wi-Fi network. If two profiles are for + * the same Wi-Fi network, but from different provider, they would have the same key. * @hide */ - public String getMacRandomKey() { + public String getNetworkKey() { // Passpoint ephemeral networks have their unique identifier set. Return it as is to be // able to match internally. if (mPasspointUniqueId != null) { return mPasspointUniqueId; } - String key = getSsidAndSecurityTypeString(); + String key = SSID + getDefaultSecurityType(); if (!shared) { key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier(); } @@ -2945,6 +3347,7 @@ public class WifiConfiguration implements Parcelable { allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone(); allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); + mSecurityParamsList = new ArrayList(source.mSecurityParamsList); enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); defaultGwMacAddress = source.defaultGwMacAddress; @@ -2963,6 +3366,7 @@ public class WifiConfiguration implements Parcelable { trusted = source.trusted; oemPaid = source.oemPaid; oemPrivate = source.oemPrivate; + carrierMerged = source.carrierMerged; fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion; fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier; meteredHint = source.meteredHint; @@ -3034,6 +3438,10 @@ public class WifiConfiguration implements Parcelable { writeBitSet(dest, allowedGroupManagementCiphers); writeBitSet(dest, allowedSuiteBCiphers); + dest.writeInt(mSecurityParamsList.size()); + mSecurityParamsList.stream() + .forEach(params -> params.writeToParcel(dest, flags)); + dest.writeParcelable(enterpriseConfig, flags); dest.writeParcelable(mIpConfiguration, flags); @@ -3045,6 +3453,7 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(trusted ? 1 : 0); dest.writeInt(oemPaid ? 1 : 0); dest.writeInt(oemPrivate ? 1 : 0); + dest.writeInt(carrierMerged ? 1 : 0); dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0); dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0); dest.writeInt(meteredHint ? 1 : 0); @@ -3114,6 +3523,11 @@ public class WifiConfiguration implements Parcelable { config.allowedGroupManagementCiphers = readBitSet(in); config.allowedSuiteBCiphers = readBitSet(in); + int numSecurityParams = in.readInt(); + for (int i = 0; i < numSecurityParams; i++) { + config.mSecurityParamsList.add(SecurityParams.createFromParcel(in)); + } + config.enterpriseConfig = in.readParcelable(null); config.setIpConfiguration(in.readParcelable(null)); config.dhcpServer = in.readString(); @@ -3124,6 +3538,7 @@ public class WifiConfiguration implements Parcelable { config.trusted = in.readInt() != 0; config.oemPaid = in.readInt() != 0; config.oemPrivate = in.readInt() != 0; + config.carrierMerged = in.readInt() != 0; config.fromWifiNetworkSuggestion = in.readInt() != 0; config.fromWifiNetworkSpecifier = in.readInt() != 0; config.meteredHint = in.readInt() != 0; @@ -3195,9 +3610,66 @@ public class WifiConfiguration implements Parcelable { * @hide */ public boolean needsPreSharedKey() { - return allowedKeyManagement.get(KeyMgmt.WPA_PSK) - || allowedKeyManagement.get(KeyMgmt.SAE) - || allowedKeyManagement.get(KeyMgmt.WAPI_PSK); + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(SECURITY_TYPE_PSK) + || params.isSecurityType(SECURITY_TYPE_SAE) + || params.isSecurityType(SECURITY_TYPE_WAPI_PSK)); + } + + /** + * Get a unique key which represent this Wi-Fi configuration profile. If two profiles are for + * the same Wi-Fi network, but from different providers (apps, carriers, or data subscriptions), + * they would have different keys. + * @return a unique key which represent this profile. + * @hide + */ + @SystemApi + @NonNull public String getProfileKey() { + if (mPasspointUniqueId != null) { + return mPasspointUniqueId; + } + + String key = SSID + getDefaultSecurityType(); + if (!shared) { + key += "-" + UserHandle.getUserHandleForUid(creatorUid).getIdentifier(); + } + if (fromWifiNetworkSuggestion) { + key += "_" + creatorName + "-" + carrierId + "-" + subscriptionId; + } + + return key; + } + + /** + * Get the default security type string. + * @hide + */ + public String getDefaultSecurityType() { + String key; + if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { + key = KeyMgmt.strings[KeyMgmt.WPA_PSK]; + } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) + || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { + key = KeyMgmt.strings[KeyMgmt.WPA_EAP]; + } else if (wepTxKeyIndex >= 0 && wepTxKeyIndex < wepKeys.length + && wepKeys[wepTxKeyIndex] != null) { + key = "WEP"; + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + key = KeyMgmt.strings[KeyMgmt.OWE]; + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + key = KeyMgmt.strings[KeyMgmt.SAE]; + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + key = KeyMgmt.strings[KeyMgmt.SUITE_B_192]; + } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { + key = KeyMgmt.strings[KeyMgmt.WAPI_PSK]; + } else if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { + key = KeyMgmt.strings[KeyMgmt.WAPI_CERT]; + } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { + key = KeyMgmt.strings[KeyMgmt.OSEN]; + } else { + key = KeyMgmt.strings[KeyMgmt.NONE]; + } + return key; } } diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 90edc4523b7b..e127ea99c716 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -1335,6 +1335,16 @@ public class WifiEnterpriseConfig implements Parcelable { } /** + * Initialize the value of the app installed device key and cert flag. + * + * @param isAppInstalledDeviceKeyAndCert true or false + * @hide + */ + public void initIsAppInstalledDeviceKeyAndCert(boolean isAppInstalledDeviceKeyAndCert) { + mIsAppInstalledDeviceKeyAndCert = isAppInstalledDeviceKeyAndCert; + } + + /** * Check if CA certificate was installed by an app, or manually (not by an app). If true, * CA certificate will be removed from key storage when this network is removed. If not, * then certificates and keys remain persistent until the user manually removes them. @@ -1348,6 +1358,16 @@ public class WifiEnterpriseConfig implements Parcelable { } /** + * Initialize the value of the app installed root CA cert flag. + * + * @param isAppInstalledCaCert true or false + * @hide + */ + public void initIsAppInstalledCaCert(boolean isAppInstalledCaCert) { + mIsAppInstalledCaCert = isAppInstalledCaCert; + } + + /** * Set the OCSP type. * @param ocsp is one of {@link ##OCSP_NONE}, {@link #OCSP_REQUEST_CERT_STATUS}, * {@link #OCSP_REQUIRE_CERT_STATUS} or diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 774c043136e7..6bd1ce54dc5b 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -25,8 +25,10 @@ import android.net.NetworkInfo.DetailedState; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.SubscriptionManager; import android.text.TextUtils; +import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.Inet4AddressUtils; import java.net.Inet4Address; @@ -169,6 +171,11 @@ public class WifiInfo implements Parcelable { private boolean mOemPrivate; /** + * Whether the network is a carrier merged network. + */ + private boolean mCarrierMerged; + + /** * OSU (Online Sign Up) AP for Passpoint R2. */ private boolean mOsuAp; @@ -190,6 +197,11 @@ public class WifiInfo implements Parcelable { private String mRequestingPackageName; /** + * Identify which Telephony subscription provides this network. + */ + private int mSubscriptionId; + + /** * Running total count of lost (not ACKed) transmitted unicast data packets. * @hide */ @@ -315,6 +327,7 @@ public class WifiInfo implements Parcelable { mRssi = INVALID_RSSI; mLinkSpeed = LINK_SPEED_UNKNOWN; mFrequency = -1; + mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } /** @hide */ @@ -335,11 +348,13 @@ public class WifiInfo implements Parcelable { setTrusted(false); setOemPaid(false); setOemPrivate(false); + setCarrierMerged(false); setOsuAp(false); setRequestingPackageName(null); setFQDN(null); setProviderFriendlyName(null); setPasspointUniqueId(null); + setSubscriptionId(SubscriptionManager.INVALID_SUBSCRIPTION_ID); txBad = 0; txSuccess = 0; rxSuccess = 0; @@ -373,11 +388,13 @@ public class WifiInfo implements Parcelable { mTrusted = source.mTrusted; mOemPaid = source.mOemPaid; mOemPrivate = source.mOemPrivate; + mCarrierMerged = source.mCarrierMerged; mRequestingPackageName = source.mRequestingPackageName; mOsuAp = source.mOsuAp; mFqdn = source.mFqdn; mProviderFriendlyName = source.mProviderFriendlyName; + mSubscriptionId = source.mSubscriptionId; txBad = source.txBad; txRetries = source.txRetries; txSuccess = source.txSuccess; @@ -753,6 +770,9 @@ public class WifiInfo implements Parcelable { */ @SystemApi public boolean isOemPaid() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } return mOemPaid; } @@ -768,9 +788,33 @@ public class WifiInfo implements Parcelable { */ @SystemApi public boolean isOemPrivate() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } return mOemPrivate; } + /** + * {@hide} + */ + public void setCarrierMerged(boolean carrierMerged) { + mCarrierMerged = carrierMerged; + } + + /** + * Returns true if the current Wifi network is a carrier merged network, false otherwise. + * @see WifiNetworkSuggestion.Builder#setCarrierMerged(boolean). + * {@hide} + */ + @SystemApi + public boolean isCarrierMerged() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mCarrierMerged; + } + + /** {@hide} */ public void setOsuAp(boolean osuAp) { mOsuAp = osuAp; @@ -839,6 +883,28 @@ public class WifiInfo implements Parcelable { return mRequestingPackageName; } + /** {@hide} */ + public void setSubscriptionId(int subId) { + mSubscriptionId = subId; + } + + /** + * If this network is provisioned by a carrier, returns subscription Id corresponding to the + * associated SIM on the device. If this network is not provisioned by a carrier, returns + * {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} + * + * @see WifiNetworkSuggestion.Builder#setSubscriptionId(int) + * @see android.telephony.SubscriptionInfo#getSubscriptionId() + * {@hide} + */ + @SystemApi + public int getSubscriptionId() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mSubscriptionId; + } + /** @hide */ @UnsupportedAppUsage @@ -1010,6 +1076,7 @@ public class WifiInfo implements Parcelable { dest.writeInt(mTrusted ? 1 : 0); dest.writeInt(mOemPaid ? 1 : 0); dest.writeInt(mOemPrivate ? 1 : 0); + dest.writeInt(mCarrierMerged ? 1 : 0); dest.writeInt(score); dest.writeLong(txSuccess); dest.writeDouble(mSuccessfulTxPacketsPerSecond); @@ -1028,6 +1095,7 @@ public class WifiInfo implements Parcelable { dest.writeInt(mMaxSupportedTxLinkSpeed); dest.writeInt(mMaxSupportedRxLinkSpeed); dest.writeString(mPasspointUniqueId); + dest.writeInt(mSubscriptionId); } /** Implement the Parcelable interface {@hide} */ @@ -1057,6 +1125,7 @@ public class WifiInfo implements Parcelable { info.mTrusted = in.readInt() != 0; info.mOemPaid = in.readInt() != 0; info.mOemPrivate = in.readInt() != 0; + info.mCarrierMerged = in.readInt() != 0; info.score = in.readInt(); info.txSuccess = in.readLong(); info.mSuccessfulTxPacketsPerSecond = in.readDouble(); @@ -1075,6 +1144,7 @@ public class WifiInfo implements Parcelable { info.mMaxSupportedTxLinkSpeed = in.readInt(); info.mMaxSupportedRxLinkSpeed = in.readInt(); info.mPasspointUniqueId = in.readString(); + info.mSubscriptionId = in.readInt(); return info; } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 8ee08f1610d6..6496cc7a3ba3 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -34,7 +34,6 @@ import android.annotation.SystemService; import android.app.ActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; -import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.MacAddress; @@ -53,6 +52,8 @@ import android.os.Looper; import android.os.RemoteException; import android.os.WorkSource; import android.os.connectivity.WifiActivityEnergyInfo; +import android.telephony.SubscriptionInfo; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.CloseGuard; import android.util.Log; @@ -61,6 +62,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.ParceledListSlice; import com.android.modules.utils.build.SdkLevel; import java.lang.annotation.Retention; @@ -71,6 +73,7 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -264,6 +267,44 @@ public class WifiManager { public @interface SuggestionConnectionStatusCode {} /** + * Status code if suggestion approval status is unknown, an App which hasn't made any + * suggestions will get this code. + */ + public static final int STATUS_SUGGESTION_APPROVAL_UNKNOWN = 0; + + /** + * Status code if the calling app is still pending user approval for suggestions. + */ + public static final int STATUS_SUGGESTION_APPROVAL_PENDING = 1; + + /** + * Status code if the calling app got the user approval for suggestions. + */ + public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER = 2; + + /** + * Status code if the calling app suggestions were rejected by the user. + */ + public static final int STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER = 3; + + /** + * Status code if the calling app was approved by virtue of being a carrier privileged app. + * @see TelephonyManager#hasCarrierPrivileges(). + */ + public static final int STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE = 4; + + /** @hide */ + @IntDef(prefix = {"STATUS_SUGGESTION_APPROVAL_"}, + value = {STATUS_SUGGESTION_APPROVAL_UNKNOWN, + STATUS_SUGGESTION_APPROVAL_PENDING, + STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, + STATUS_SUGGESTION_APPROVAL_REJECTED_BY_USER, + STATUS_SUGGESTION_APPROVAL_APPROVED_BY_CARRIER_PRIVILEGE + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SuggestionUserApprovalStatus {} + + /** * Broadcast intent action indicating whether Wi-Fi scanning is currently available. * Available extras: * - {@link #EXTRA_SCAN_AVAILABLE} @@ -1449,7 +1490,7 @@ public class WifiManager { new ArrayList<>(results.keySet())); for (WifiConfiguration configuration : wifiConfigurations) { Map<Integer, List<ScanResult>> scanResultsPerNetworkType = - results.get(configuration.getKey()); + results.get(configuration.getProfileKey()); if (scanResultsPerNetworkType != null) { configs.add(Pair.create(configuration, scanResultsPerNetworkType)); } @@ -2010,6 +2051,26 @@ public class WifiManager { } /** + * Get the Suggestion approval status of the calling app. When an app makes suggestions using + * the {@link #addNetworkSuggestions(List)} API they may trigger a user approval flow. This API + * provides the current approval status. + * + * @return Status code for the user approval. One of the STATUS_SUGGESTION_APPROVAL_ values. + * @throws {@link SecurityException} if the caller is missing required permissions. + */ + @RequiresPermission(ACCESS_WIFI_STATE) + public @SuggestionUserApprovalStatus int getNetworkSuggestionUserApprovalStatus() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + try { + return mService.getNetworkSuggestionUserApprovalStatus(mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** * Add or update a Passpoint configuration. The configuration provides a credential * for connecting to Passpoint networks that are operated by the Passpoint * service provider specified in the configuration. @@ -2425,6 +2486,15 @@ public class WifiManager { /** @hide */ public static final long WIFI_FEATURE_FILS_SHA384 = 0x8000000000L; // FILS-SHA384 + /** @hide */ + public static final long WIFI_FEATURE_SAE_PK = 0x10000000000L; // SAE-PK + + /** @hide */ + public static final long WIFI_FEATURE_STA_BRIDGED_AP = 0x20000000000L; // STA + Bridged AP + + /** @hide */ + public static final long WIFI_FEATURE_BRIDGED_AP = 0x40000000000L; // Bridged AP + private long getSupportedFeatures() { try { return mService.getSupportedFeatures(); @@ -2625,6 +2695,40 @@ public class WifiManager { } /** + * Query whether the device supports Station (STA) + Bridged access point (AP) + * concurrency or not. + * + * The bridged AP support means that the device supports AP + AP concurrency with the 2 APs + * bridged together. + * + * See {@link SoftApConfiguration.Builder#setBands(int[])} + * or {@link SoftApConfiguration.Builder#setChannels(SparseIntArray)} to configure bridged AP + * when the bridged AP supported. + * + * @return true if this device supports STA + bridged AP concurrency, false otherwise. + */ + public boolean isStaBridgedApConcurrencySupported() { + return isFeatureSupported(WIFI_FEATURE_STA_BRIDGED_AP); + } + + /** + * Query whether the device supports Bridged Access point (AP) concurrency or not. + * + * The bridged AP support means that the device supports AP + AP concurrency with the 2 APs + * bridged together. + * + * See {@link SoftApConfiguration.Builder#setBands(int[])} + * or {@link SoftApConfiguration.Builder#setChannels(SparseIntArray)} to configure bridged AP + * when the bridged AP supported. + * + * @return true if this device supports bridged AP concurrency, false otherwise. + */ + public boolean isBridgedApConcurrencySupported() { + return isFeatureSupported(WIFI_FEATURE_BRIDGED_AP); + } + + + /** * Interface for Wi-Fi activity energy info listener. Should be implemented by applications and * set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}. * @@ -2937,6 +3041,37 @@ public class WifiManager { } /** + * Restart the Wi-Fi subsystem. + * + * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing + * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and + * Wi-Fi Aware are disabled. + * + * The state of the system after restart is not guaranteed to match its state before the API is + * called - for instance the device may associate to a different Access Point (AP), and tethered + * hotspots may or may not be restored. + * + * @param reason If non-null, requests a bug report and attaches the reason string to it. A bug + * report may still not be generated based on framework criteria - for instance, + * build type or throttling. The WiFi subsystem is restarted whether or not a bug + * report is requested or generated. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) + public void restartWifiSubsystem(@Nullable String reason) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + try { + mService.restartWifiSubsystem(reason); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Gets the Wi-Fi enabled state. * @return One of {@link #WIFI_STATE_DISABLED}, * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, @@ -3048,6 +3183,251 @@ public class WifiManager { } } + /* Wi-Fi/Cellular Coex */ + + /** + * Mandatory coex restriction flag for Wi-Fi Direct. + * + * @see #setCoexUnsafeChannels(Set, int) + * + * @hide + */ + @SystemApi + public static final int COEX_RESTRICTION_WIFI_DIRECT = 0x1 << 0; + + /** + * Mandatory coex restriction flag for SoftAP + * + * @see #setCoexUnsafeChannels(Set, int) + * + * @hide + */ + @SystemApi + public static final int COEX_RESTRICTION_SOFTAP = 0x1 << 1; + + /** + * Mandatory coex restriction flag for Wi-Fi Aware. + * + * @see #setCoexUnsafeChannels(Set, int) + * + * @hide + */ + @SystemApi + public static final int COEX_RESTRICTION_WIFI_AWARE = 0x1 << 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = {"COEX_RESTRICTION_"}, value = { + COEX_RESTRICTION_WIFI_DIRECT, + COEX_RESTRICTION_SOFTAP, + COEX_RESTRICTION_WIFI_AWARE + }) + public @interface CoexRestriction {} + + /** + * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise. + * + * @hide + */ + public boolean isDefaultCoexAlgorithmEnabled() { + try { + return mService.isDefaultCoexAlgorithmEnabled(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Specify the set of {@link CoexUnsafeChannel} to propagate through the framework for + * Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay + * (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing. + * + * @param unsafeChannels Set of {@link CoexUnsafeChannel} to avoid. + * @param restrictions Bitmap of {@link CoexRestriction} specifying the mandatory restricted + * uses of the specified channels. If any restrictions are set, then the + * supplied CoexUnsafeChannels will be completely avoided for the + * specified modes, rather than be avoided with best effort. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS) + public void setCoexUnsafeChannels(@NonNull Set<CoexUnsafeChannel> unsafeChannels, + int restrictions) { + if (unsafeChannels == null) { + throw new IllegalArgumentException("unsafeChannels must not be null"); + } + try { + mService.setCoexUnsafeChannels(new ArrayList<>(unsafeChannels), restrictions); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the set of current {@link CoexUnsafeChannel} being used for Wi-Fi/Cellular coex + * channel avoidance. + * + * This returns the set calculated by the default algorithm if + * config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, returns the set supplied + * in {@link #setCoexUnsafeChannels(Set, int)}. + * + * If any {@link CoexRestriction} flags are set in {@link #getCoexRestrictions()}, then the + * CoexUnsafeChannels should be totally avoided (i.e. not best effort) for the Wi-Fi modes + * specified by the flags. + * + * @return Set of current CoexUnsafeChannels. + * + * @hide + */ + @NonNull + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) + public Set<CoexUnsafeChannel> getCoexUnsafeChannels() { + try { + return new HashSet<>(mService.getCoexUnsafeChannels()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Returns the current coex restrictions being used for Wi-Fi/Cellular coex + * channel avoidance. + * + * This returns the restrictions calculated by the default algorithm if + * config_wifiCoexDefaultAlgorithmEnabled is {@code true}. Otherwise, returns the value supplied + * in {@link #setCoexUnsafeChannels(Set, int)}. + * + * @return int containing a bitwise-OR combination of {@link CoexRestriction}. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) + public int getCoexRestrictions() { + try { + return mService.getCoexRestrictions(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Registers a CoexCallback to listen on the current CoexUnsafeChannels and restrictions being + * used for Wi-Fi/cellular coex channel avoidance. + * @param executor Executor to execute listener callback on + * @param callback CoexCallback to register + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) + public void registerCoexCallback( + @NonNull @CallbackExecutor Executor executor, @NonNull CoexCallback callback) { + if (executor == null) throw new IllegalArgumentException("executor must not be null"); + if (callback == null) throw new IllegalArgumentException("callback must not be null"); + CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); + proxy.initProxy(executor, callback); + try { + mService.registerCoexCallback(proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a CoexCallback from listening on the current CoexUnsafeChannels and restrictions + * being used for Wi-Fi/cellular coex channel avoidance. + * @param callback CoexCallback to unregister + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) + public void unregisterCoexCallback(@NonNull CoexCallback callback) { + if (callback == null) throw new IllegalArgumentException("callback must not be null"); + CoexCallback.CoexCallbackProxy proxy = callback.getProxy(); + try { + mService.unregisterCoexCallback(proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } finally { + proxy.cleanUpProxy(); + } + } + + /** + * Abstract callback class for applications to receive updates about current CoexUnsafeChannels + * for Wi-Fi/Cellular coex channel avoidance. + * + * @hide + */ + @SystemApi + public abstract static class CoexCallback { + private final CoexCallbackProxy mCoexCallbackProxy; + + public CoexCallback() { + mCoexCallbackProxy = new CoexCallbackProxy(); + } + + /*package*/ @NonNull + CoexCallbackProxy getProxy() { + return mCoexCallbackProxy; + } + + /** + * Indicates that the current CoexUnsafeChannels or restrictions have changed. + * Clients should call {@link #getCoexUnsafeChannels()} and {@link #getCoexRestrictions()} + * to get the updated values. + */ + public abstract void onCoexUnsafeChannelsChanged(); + + /** + * Callback proxy for CoexCallback objects. + */ + private static class CoexCallbackProxy extends ICoexCallback.Stub { + private final Object mLock = new Object(); + @Nullable @GuardedBy("mLock") private Executor mExecutor; + @Nullable @GuardedBy("mLock") private CoexCallback mCallback; + + CoexCallbackProxy() { + mExecutor = null; + mCallback = null; + } + + /*package*/ void initProxy(@NonNull Executor executor, + @NonNull CoexCallback callback) { + synchronized (mLock) { + mExecutor = executor; + mCallback = callback; + } + } + + /*package*/ void cleanUpProxy() { + synchronized (mLock) { + mExecutor = null; + mCallback = null; + } + } + + @Override + public void onCoexUnsafeChannelsChanged() { + Executor executor; + CoexCallback callback; + synchronized (mLock) { + executor = mExecutor; + callback = mCallback; + } + if (executor == null || callback == null) { + return; + } + Binder.clearCallingIdentity(); + executor.execute(callback::onCoexUnsafeChannelsChanged); + } + } + } + /** * Start Soft AP (hotspot) mode for tethering purposes with the specified configuration. * Note that starting Soft AP mode may disable station mode operation if the device does not @@ -3649,6 +4029,11 @@ public class WifiManager { /** * Called when information of softap changes. * + * Note: this API is only valid when the Soft AP is configured as a single AP + * - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP + * this callback will not be triggered - use the + * {@link #onInfoListChanged(List<SoftApInfo>)} callback in bridged AP mode. + * * @param softApInfo is the softap information. {@link SoftApInfo} */ default void onInfoChanged(@NonNull SoftApInfo softApInfo) { @@ -3656,6 +4041,24 @@ public class WifiManager { } /** + * Called when information of softap changes. + * + * The number of the information elements in the list depends on Soft AP configuration + * and state. + * For instance, an empty list will be returned when the Soft AP is disabled. + * One information element will be returned in the list when the Soft AP is configured + * as a single AP, and two information elements will be returned in the list + * when the Soft AP is configured in bridged mode. + * + * See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP. + * + * @param softApInfoList is the list of the softap information elements. {@link SoftApInfo} + */ + default void onInfoListChanged(@NonNull List<SoftApInfo> softApInfoList) { + // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. + } + + /** * Called when capability of softap changes. * * @param softApCapability is the softap capability. {@link SoftApCapability} @@ -3735,6 +4138,19 @@ public class WifiManager { } @Override + public void onInfoListChanged(List<SoftApInfo> softApInfoList) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SoftApCallbackProxy: onInfoListChange: softApInfoList=" + + softApInfoList); + } + + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.onInfoListChanged(softApInfoList); + }); + } + + @Override public void onCapabilityChanged(SoftApCapability capability) { if (mVerboseLoggingEnabled) { Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability=" @@ -4230,6 +4646,49 @@ public class WifiManager { } /** + * Temporarily disable autojoin for all currently visible and provisioned (saved, suggested) + * wifi networks except merged carrier networks from the provided subscription ID. + * + * Disabled networks will get automatically re-enabled when they are out of range for a period + * of time, or after the maximum disable duration specified in the framework. + * + * Calling {@link #stopTemporarilyDisablingAllNonCarrierMergedWifi()} will immediately re-enable + * autojoin on all disabled networks. + * + * @param subscriptionId the subscription ID of the carrier whose merged wifi networks won't be + * disabled {@link android.telephony.SubscriptionInfo#getSubscriptionId()} + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) + public void startTemporarilyDisablingAllNonCarrierMergedWifi(int subscriptionId) { + try { + mService.startTemporarilyDisablingAllNonCarrierMergedWifi(subscriptionId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Re-enable autojoin for all non carrier merged wifi networks temporarily disconnected by + * {@link #startTemporarilyDisablingAllNonCarrierMergedWifi(int)}. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) + public void stopTemporarilyDisablingAllNonCarrierMergedWifi() { + try { + mService.stopTemporarilyDisablingAllNonCarrierMergedWifi(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Save the given network to the list of configured networks for the * foreground user. If the network already exists, the configuration * is updated. Any new network is enabled by default. @@ -5330,6 +5789,13 @@ public class WifiManager { } /** + * @return true if this device supports WPA3 AP validation. + */ + public boolean isWpa3ApValidationSupported() { + return isFeatureSupported(WIFI_FEATURE_SAE_PK); + } + + /** * Gets the factory Wi-Fi MAC addresses. * @return Array of String representing Wi-Fi MAC addresses sorted lexically or an empty Array * if failed. @@ -5443,6 +5909,89 @@ public class WifiManager { } /** + * Easy Connect Device information maximum allowed length. + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH = 40; + + /** + * Easy Connect Cryptography Curve name: prime256v1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1 = 0; + + /** + * Easy Connect Cryptography Curve name: secp384r1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1 = 1; + + /** + * Easy Connect Cryptography Curve name: secp521r1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1 = 2; + + + /** + * Easy Connect Cryptography Curve name: brainpoolP256r1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1 = 3; + + + /** + * Easy Connect Cryptography Curve name: brainpoolP384r1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1 = 4; + + + /** + * Easy Connect Cryptography Curve name: brainpoolP512r1 + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1 = 5; + + /** + * Easy Connect Cryptography Curve name: default + * This allows framework to choose manadatory curve prime256v1. + * + * @hide + */ + @SystemApi + public static final int EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT = + EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1; + + /** @hide */ + @IntDef(prefix = {"EASY_CONNECT_CRYPTOGRAPHY_CURVE_"}, value = { + EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1, + EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface EasyConnectCryptographyCurve { + } + + /** * Start Easy Connect (DPP) in Configurator-Initiator role. The current device will initiate * Easy Connect bootstrapping with a peer, and configure the peer with the SSID and password of * the specified network using the Easy Connect protocol on an encrypted link. @@ -5498,6 +6047,52 @@ public class WifiManager { } /** + * Start Easy Connect (DPP) in Enrollee-Responder role. + * The device will: + * 1. Generate a DPP bootstrap URI and return it using the + * {@link EasyConnectStatusCallback#onBootstrapUriGenerated(String)} method. + * 2. Start DPP as a Responder, waiting for an Initiator device to start the DPP + * authentication process. + * The caller should use the URI provided in step #1, for instance display it as a QR code + * or communicate it in some other way to the initiator device. + * + * @param deviceInfo Device specific information to add to the DPP URI. This field allows + * the users of the configurators to identify the device. + * Optional - if not provided or in case of an empty string, + * Info field (I:) will be skipped in the generated DPP URI. + * Allowed Range of ASCII characters in deviceInfo - %x20-7E. + * semicolon and space are not allowed. + * Due to the limitation of maximum allowed characters in QR code, + * framework limits to a max of + * {@link #EASY_CONNECT_DEVICE_INFO_MAXIMUM_LENGTH} characters in + * deviceInfo. + * Violation of these rules will result in an exception. + * @param curve Elliptic curve cryptography used to generate DPP + * public/private key pair. If application is not interested in a + * specific curve, choose default curve + * {@link #EASY_CONNECT_CRYPTOGRAPHY_CURVE_DEFAULT}. + * @param callback Callback for status updates + * @param executor The Executor on which to run the callback. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) + public void startEasyConnectAsEnrolleeResponder(@Nullable String deviceInfo, + @EasyConnectCryptographyCurve int curve, + @NonNull @CallbackExecutor Executor executor, + @NonNull EasyConnectStatusCallback callback) { + Binder binder = new Binder(); + try { + mService.startDppAsEnrolleeResponder(binder, deviceInfo, curve, + new EasyConnectCallbackProxy(executor, callback)); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will * terminate any ongoing transaction, and clean up all associated resources. Caller should not * expect any callbacks once this call is made. However, due to the asynchronous nature of @@ -5571,6 +6166,15 @@ public class WifiManager { mEasyConnectStatusCallback.onProgress(status); }); } + + @Override + public void onBootstrapUriGenerated(String uri) { + Log.d(TAG, "Easy Connect onBootstrapUriGenerated callback"); + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mEasyConnectStatusCallback.onBootstrapUriGenerated(uri); + }); + } } /** @@ -5745,7 +6349,6 @@ public class WifiManager { executor.execute(callback::onScanResultsAvailable); } } - } /** @@ -6243,4 +6846,154 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } + + /** + * Sets the state of carrier offload on merged or unmerged networks for specified subscription. + * + * <p> + * When a subscription's carrier network offload is disabled, all network suggestions related to + * this subscription will not be considered for auto join. + * <p> + * If calling app want disable all carrier network offload from a specified subscription, should + * call this API twice to disable both merged and unmerged carrier network suggestions. + * + * @param subscriptionId See {@link SubscriptionInfo#getSubscriptionId()}. + * @param merged True for carrier merged network, false otherwise. + * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} + * @param enabled True for enable carrier network offload, false otherwise. + * @see #isCarrierNetworkOffloadEnabled(int, boolean) + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) + public void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, + boolean enabled) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + try { + mService.setCarrierNetworkOffloadEnabled(subscriptionId, merged, enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get the carrier network offload state for merged or unmerged networks for specified + * subscription. + * @param subscriptionId subscription ID see {@link SubscriptionInfo#getSubscriptionId()} + * @param merged True for carrier merged network, false otherwise. + * See {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} + * @return True to indicate that carrier network offload is enabled, false otherwise. + * @see #setCarrierNetworkOffloadEnabled(int, boolean, boolean) + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) + public boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + try { + return mService.isCarrierNetworkOffloadEnabled(subscriptionId, merged); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Interface for network suggestion user approval status change listener. + * Should be implemented by applications and registered using + * {@link #addSuggestionUserApprovalStatusListener(Executor, + * SuggestionUserApprovalStatusListener)} ( + */ + public interface SuggestionUserApprovalStatusListener { + + /** + * Called when the user approval status of the App has changed. The current status can be + * queried by {@link #getNetworkSuggestionUserApprovalStatus()} + */ + void onUserApprovalStatusChange(); + } + + private class SuggestionUserApprovalStatusListenerProxy extends + ISuggestionUserApprovalStatusListener.Stub { + private final Executor mExecutor; + private final SuggestionUserApprovalStatusListener mListener; + + SuggestionUserApprovalStatusListenerProxy(@NonNull Executor executor, + @NonNull SuggestionUserApprovalStatusListener listener) { + mExecutor = executor; + mListener = listener; + } + + @Override + public void onUserApprovalStatusChange() { + mExecutor.execute(() -> mListener.onUserApprovalStatusChange()); + } + + } + + /** + * Add a listener for Wi-Fi network suggestion user approval status. + * See {@link SuggestionUserApprovalStatusListener}. + * Caller will receive a callback when the user approval status of the caller has changed. + * Caller can remove a previously registered listener using + * {@link WifiManager#removeSuggestionUserApprovalStatusListener( + * SuggestionUserApprovalStatusListener)} + * A caller can add multiple listeners to monitor the event. + * @param executor The executor to execute the listener of the {@code listener} object. + * @param listener listener for suggestion user approval status changes. + * @return true if succeed otherwise false. + */ + @RequiresPermission(ACCESS_WIFI_STATE) + public boolean addSuggestionUserApprovalStatusListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull SuggestionUserApprovalStatusListener listener) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); + if (executor == null) throw new IllegalArgumentException("Executor cannot be null"); + Log.v(TAG, "addSuggestionUserApprovalStatusListener listener=" + listener + + ", executor=" + executor); + try { + return mService.addSuggestionUserApprovalStatusListener(new Binder(), + new SuggestionUserApprovalStatusListenerProxy(executor, listener), + listener.hashCode(), mContext.getOpPackageName(), mContext.getAttributionTag()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + } + + /** + * Allow callers to remove a previously registered listener using + * {@link #addSuggestionUserApprovalStatusListener(Executor, + * SuggestionUserApprovalStatusListener)}. After calling this method, + * applications will no longer receive network suggestion user approval status change through + * that listener. + * + * @param listener listener to remove. + */ + @RequiresPermission(ACCESS_WIFI_STATE) + public void removeSuggestionUserApprovalStatusListener( + @NonNull SuggestionUserApprovalStatusListener listener) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + if (listener == null) throw new IllegalArgumentException("Listener cannot be null"); + Log.v(TAG, "removeSuggestionUserApprovalStatusListener: listener=" + listener); + try { + mService.removeSuggestionUserApprovalStatusListener(listener.hashCode(), + mContext.getOpPackageName()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java index f5ffd93d5fb6..be3b45d8c82a 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java @@ -367,10 +367,12 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc && WifiEnterpriseConfig.isSuiteBCipherCert( mWpa3EnterpriseConfig.getCaCertificate())) { // WPA3-Enterprise in 192-bit security mode - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams( + WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); } else if (mWpa3EnterpriseType == WPA3_ENTERPRISE_192_BIT) { // WPA3-Enterprise in 192-bit security mode - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams( + WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); } else { // WPA3-Enterprise configuration.setSecurityParams( diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index dc5189724c25..b7450c538ff8 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -187,6 +187,11 @@ public final class WifiNetworkSuggestion implements Parcelable { private boolean mIsNetworkOemPrivate; /** + * Whether this network is a carrier merged network. + */ + private boolean mIsCarrierMerged; + + /** * Whether this network will use enhanced MAC randomization. */ private boolean mIsEnhancedMacRandomizationEnabled; @@ -214,6 +219,7 @@ public final class WifiNetworkSuggestion implements Parcelable { mIsNetworkUntrusted = false; mIsNetworkOemPaid = false; mIsNetworkOemPrivate = false; + mIsCarrierMerged = false; mPriorityGroup = 0; mIsEnhancedMacRandomizationEnabled = false; mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -775,6 +781,34 @@ public final class WifiNetworkSuggestion implements Parcelable { return this; } + /** + * Specifies whether the suggestion represents a carrier merged network. A carrier merged + * Wi-Fi network is treated as part of the mobile carrier network. Such configuration may + * impact the user interface and data usage accounting. + * <p> + * <li>A suggestion marked as carrier merged must be metered enterprise network with a valid + * subscription Id set. + * @see #setIsMetered(boolean) + * @see #setSubscriptionId(int) + * @see #setWpa2EnterpriseConfig(WifiEnterpriseConfig) + * @see #setWpa3Enterprise192BitModeConfig(WifiEnterpriseConfig) + * @see #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig) + * @see #setPasspointConfig(PasspointConfiguration) + * </li> + * <li>If not set, defaults to false (i.e. not a carrier merged network.)</li> + * </p> + * @param isCarrierMerged Boolean indicating whether the network is treated a carrier + * merged network (if true) or non-merged network (if false); + * @return Instance of {@link Builder} to enable chaining of the builder method. + */ + public @NonNull Builder setCarrierMerged(boolean isCarrierMerged) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + mIsCarrierMerged = isCarrierMerged; + return this; + } + private void setSecurityParamsInWifiConfiguration( @NonNull WifiConfiguration configuration) { if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network. @@ -796,10 +830,12 @@ public final class WifiNetworkSuggestion implements Parcelable { && WifiEnterpriseConfig.isSuiteBCipherCert( mWpa3EnterpriseConfig.getCaCertificate())) { // WPA3-Enterprise in 192-bit security mode - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams( + WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); } else if (mWpa3EnterpriseType == WPA3_ENTERPRISE_192_BIT) { // WPA3-Enterprise in 192-bit security mode - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams( + WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); } else { // WPA3-Enterprise configuration.setSecurityParams( @@ -841,6 +877,7 @@ public final class WifiNetworkSuggestion implements Parcelable { wifiConfiguration.trusted = !mIsNetworkUntrusted; wifiConfiguration.oemPaid = mIsNetworkOemPaid; wifiConfiguration.oemPrivate = mIsNetworkOemPrivate; + wifiConfiguration.carrierMerged = mIsCarrierMerged; wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled ? WifiConfiguration.RANDOMIZATION_ENHANCED : WifiConfiguration.RANDOMIZATION_PERSISTENT; @@ -875,10 +912,14 @@ public final class WifiNetworkSuggestion implements Parcelable { wifiConfiguration.trusted = !mIsNetworkUntrusted; wifiConfiguration.oemPaid = mIsNetworkOemPaid; wifiConfiguration.oemPrivate = mIsNetworkOemPrivate; + wifiConfiguration.carrierMerged = mIsCarrierMerged; wifiConfiguration.subscriptionId = mSubscriptionId; mPasspointConfiguration.setCarrierId(mCarrierId); mPasspointConfiguration.setSubscriptionId(mSubscriptionId); mPasspointConfiguration.setMeteredOverride(wifiConfiguration.meteredOverride); + mPasspointConfiguration.setOemPrivate(mIsNetworkOemPrivate); + mPasspointConfiguration.setOemPaid(mIsNetworkOemPaid); + mPasspointConfiguration.setCarrierMerged(mIsCarrierMerged); wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled ? WifiConfiguration.RANDOMIZATION_ENHANCED : WifiConfiguration.RANDOMIZATION_PERSISTENT; @@ -1002,6 +1043,14 @@ public final class WifiNetworkSuggestion implements Parcelable { } mIsSharedWithUser = false; } + if (mIsCarrierMerged) { + if (mSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID + || mMeteredOverride != WifiConfiguration.METERED_OVERRIDE_METERED + || !isEnterpriseSuggestion()) { + throw new IllegalStateException("A carrier merged network must be a metered, " + + "enterprise network with valid subscription Id"); + } + } return new WifiNetworkSuggestion( wifiConfiguration, mPasspointConfiguration, @@ -1011,8 +1060,15 @@ public final class WifiNetworkSuggestion implements Parcelable { mIsInitialAutojoinEnabled, mPriorityGroup); } + + private boolean isEnterpriseSuggestion() { + return !(mWpa2EnterpriseConfig == null && mWpa3EnterpriseConfig == null + && mWapiEnterpriseConfig == null && mPasspointConfiguration == null); + } } + + /** * Network configuration for the provided network. * @hide @@ -1127,7 +1183,8 @@ public final class WifiNetworkSuggestion implements Parcelable { @Override public int hashCode() { return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID, - wifiConfiguration.allowedKeyManagement, wifiConfiguration.getKey(), + wifiConfiguration.getDefaultSecurityType(), + wifiConfiguration.getPasspointUniqueId(), wifiConfiguration.subscriptionId, wifiConfiguration.carrierId); } @@ -1149,10 +1206,10 @@ public final class WifiNetworkSuggestion implements Parcelable { 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.getKey(), - lhs.wifiConfiguration.getKey()) + && TextUtils.equals(this.wifiConfiguration.getDefaultSecurityType(), + lhs.wifiConfiguration.getDefaultSecurityType()) + && TextUtils.equals(this.wifiConfiguration.getPasspointUniqueId(), + lhs.wifiConfiguration.getPasspointUniqueId()) && this.wifiConfiguration.carrierId == lhs.wifiConfiguration.carrierId && this.wifiConfiguration.subscriptionId == lhs.wifiConfiguration.subscriptionId; } @@ -1170,6 +1227,7 @@ public final class WifiNetworkSuggestion implements Parcelable { .append(", isUnTrusted=").append(!wifiConfiguration.trusted) .append(", isOemPaid=").append(wifiConfiguration.oemPaid) .append(", isOemPrivate=").append(wifiConfiguration.oemPrivate) + .append(", isCarrierMerged").append(wifiConfiguration.carrierMerged) .append(", priorityGroup=").append(priorityGroup) .append(" ]"); return sb.toString(); @@ -1289,6 +1347,16 @@ public final class WifiNetworkSuggestion implements Parcelable { } /** + * @see Builder#setCarrierMerged(boolean) + */ + public boolean isCarrierMerged() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return wifiConfiguration.carrierMerged; + } + + /** * Get the WifiEnterpriseConfig, or null if unset. * @see Builder#setWapiEnterpriseConfig(WifiEnterpriseConfig) * @see Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig) diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java index 41d0857214f3..7c051f0962c4 100644 --- a/wifi/java/android/net/wifi/WifiScanner.java +++ b/wifi/java/android/net/wifi/WifiScanner.java @@ -1267,7 +1267,7 @@ public class WifiScanner { * @param bssidInfos access points to watch */ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void configureWifiChange( int rssiSampleSize, /* sample size for RSSI averaging */ int lostApSampleSize, /* samples to confirm AP's loss */ @@ -1301,7 +1301,7 @@ public class WifiScanner { * provided on {@link #stopTrackingWifiChange} */ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void startTrackingWifiChange(WifiChangeListener listener) { throw new UnsupportedOperationException(); } @@ -1312,7 +1312,7 @@ public class WifiScanner { * #stopTrackingWifiChange} */ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void stopTrackingWifiChange(WifiChangeListener listener) { throw new UnsupportedOperationException(); } @@ -1320,7 +1320,7 @@ public class WifiScanner { /** @hide */ @SystemApi @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void configureWifiChange(WifiChangeSettings settings) { throw new UnsupportedOperationException(); } @@ -1376,7 +1376,7 @@ public class WifiScanner { * also be provided on {@link #stopTrackingBssids} */ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void startTrackingBssids(BssidInfo[] bssidInfos, int apLostThreshold, BssidListener listener) { throw new UnsupportedOperationException(); @@ -1387,7 +1387,7 @@ public class WifiScanner { * @param listener same object provided in {@link #startTrackingBssids} */ @Deprecated - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public void stopTrackingBssids(BssidListener listener) { throw new UnsupportedOperationException(); } diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index e19b095b27eb..540bf2a72b34 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -774,9 +774,13 @@ public class WifiAwareManager { (byte[]) msg.obj); break; case CALLBACK_MATCH_EXPIRED: + if (!SdkLevel.isAtLeastS()) { + break; + } mOriginalCallback .onServiceLost(new PeerHandle(msg.arg1), WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE); + break; } } }; diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java index 357c5bcfa265..006fbaa028bd 100644 --- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java @@ -474,6 +474,27 @@ public final class PasspointConfiguration implements Parcelable { */ private boolean mIsEnhancedMacRandomizationEnabled = false; + + /** + * Indicate whether the network is oem paid or not. Networks are considered oem paid + * if the corresponding connection is only available to system apps. + * @hide + */ + private boolean mIsOemPaid; + + /** + * Indicate whether the network is oem private or not. Networks are considered oem private + * if the corresponding connection is only available to system apps. + * @hide + */ + private boolean mIsOemPrivate; + + /** + * Indicate whether or not the network is a carrier merged network. + * @hide + */ + private boolean mIsCarrierMerged; + /** * Indicates if the end user has expressed an explicit opinion about the * meteredness of this network, such as through the Settings app. @@ -589,6 +610,54 @@ public final class PasspointConfiguration implements Parcelable { } /** + * Set whether the network is oem paid or not. + * @hide + */ + public void setOemPaid(boolean isOemPaid) { + mIsOemPaid = isOemPaid; + } + + /** + * Get whether the network is oem paid or not. + * @hide + */ + public boolean isOemPaid() { + return mIsOemPaid; + } + + /** + * Set whether the network is oem private or not. + * @hide + */ + public void setOemPrivate(boolean isOemPrivate) { + mIsOemPrivate = isOemPrivate; + } + + /** + * Get whether the network is oem private or not. + * @hide + */ + public boolean isOemPrivate() { + return mIsOemPrivate; + } + + /** + * Set whether the network is carrier merged or not. + * @hide + */ + public void setCarrierMerged(boolean isCarrierMerged) { + mIsCarrierMerged = isCarrierMerged; + } + + /** + * Get whether the network is carrier merged or not. + * @hide + */ + public boolean isCarrierMerged() { + return mIsCarrierMerged; + } + + /** * Constructor for creating PasspointConfiguration with default values. */ public PasspointConfiguration() {} @@ -635,6 +704,9 @@ public final class PasspointConfiguration implements Parcelable { mIsMacRandomizationEnabled = source.mIsMacRandomizationEnabled; mIsEnhancedMacRandomizationEnabled = source.mIsEnhancedMacRandomizationEnabled; mMeteredOverride = source.mMeteredOverride; + mIsCarrierMerged = source.mIsCarrierMerged; + mIsOemPaid = source.mIsOemPaid; + mIsOemPrivate = source.mIsOemPrivate; } @Override @@ -669,6 +741,9 @@ public final class PasspointConfiguration implements Parcelable { dest.writeBoolean(mIsEnhancedMacRandomizationEnabled); dest.writeInt(mMeteredOverride); dest.writeInt(mSubscriptionId); + dest.writeBoolean(mIsCarrierMerged); + dest.writeBoolean(mIsOemPaid); + dest.writeBoolean(mIsOemPrivate); } @Override @@ -700,6 +775,9 @@ public final class PasspointConfiguration implements Parcelable { && mUsageLimitTimeLimitInMinutes == that.mUsageLimitTimeLimitInMinutes && mCarrierId == that.mCarrierId && mSubscriptionId == that.mSubscriptionId + && mIsOemPrivate == that.mIsOemPrivate + && mIsOemPaid == that.mIsOemPaid + && mIsCarrierMerged == that.mIsCarrierMerged && mIsAutojoinEnabled == that.mIsAutojoinEnabled && mIsMacRandomizationEnabled == that.mIsMacRandomizationEnabled && mIsEnhancedMacRandomizationEnabled == that.mIsEnhancedMacRandomizationEnabled @@ -715,7 +793,8 @@ public final class PasspointConfiguration implements Parcelable { mSubscriptionExpirationTimeMillis, mUsageLimitUsageTimePeriodInMinutes, mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes, mServiceFriendlyNames, mCarrierId, mIsAutojoinEnabled, mIsMacRandomizationEnabled, - mIsEnhancedMacRandomizationEnabled, mMeteredOverride, mSubscriptionId); + mIsEnhancedMacRandomizationEnabled, mMeteredOverride, mSubscriptionId, + mIsCarrierMerged, mIsOemPaid, mIsOemPrivate); } @Override @@ -774,6 +853,9 @@ public final class PasspointConfiguration implements Parcelable { builder.append("mIsMacRandomizationEnabled:" + mIsMacRandomizationEnabled); builder.append("mIsEnhancedMacRandomizationEnabled:" + mIsEnhancedMacRandomizationEnabled); builder.append("mMeteredOverride:" + mMeteredOverride); + builder.append("mIsCarrierMerged:" + mIsCarrierMerged); + builder.append("mIsOemPaid:" + mIsOemPaid); + builder.append("mIsOemPrivate" + mIsOemPrivate); return builder.toString(); } @@ -884,6 +966,10 @@ public final class PasspointConfiguration implements Parcelable { config.mIsEnhancedMacRandomizationEnabled = in.readBoolean(); config.mMeteredOverride = in.readInt(); config.mSubscriptionId = in.readInt(); + config.mIsCarrierMerged = in.readBoolean(); + config.mIsOemPaid = in.readBoolean(); + config.mIsOemPrivate = in.readBoolean(); + return config; } diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java index dad431c1ca2c..e2f40cfa058c 100644 --- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java +++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java @@ -17,10 +17,11 @@ package android.net.wifi.p2p.nsd; import android.compat.annotation.UnsupportedAppUsage; -import android.net.util.nsd.DnsSdTxtRecord; import android.os.Build; import android.text.TextUtils; +import com.android.net.module.util.DnsSdTxtRecord; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java index 318efa61a110..04dfcf2f9cad 100644 --- a/wifi/java/android/net/wifi/rtt/RangingRequest.java +++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java @@ -30,8 +30,11 @@ import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; +import com.android.modules.utils.build.SdkLevel; + import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; /** @@ -46,6 +49,9 @@ import java.util.StringJoiner; */ public final class RangingRequest implements Parcelable { private static final int MAX_PEERS = 10; + private static final int DEFAULT_RTT_BURST_SIZE = 8; + private static final int MIN_RTT_BURST_SIZE = 2; + private static final int MAX_RTT_BURST_SIZE = 17; /** * Returns the maximum number of peers to range which can be specified in a single {@code @@ -59,12 +65,80 @@ public final class RangingRequest implements Parcelable { return MAX_PEERS; } + /** + * Returns the default RTT burst size used to determine the average range. + * + * @return the RTT burst size used by default + */ + public static int getDefaultRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return DEFAULT_RTT_BURST_SIZE; + } + + /** + * Returns the minimum RTT burst size that can be used to determine a average range. + * + * @return the minimum RTT burst size that can be used + */ + public static int getMinRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return MIN_RTT_BURST_SIZE; + } + + /** + * Returns the minimum RTT burst size that can be used to determine a average range. + * + * @return the maximum RTT burst size that can be used + */ + public static int getMaxRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return MAX_RTT_BURST_SIZE; + } + /** @hide */ public final List<ResponderConfig> mRttPeers; /** @hide */ - private RangingRequest(List<ResponderConfig> rttPeers) { + public final int mRttBurstSize; + + /** @hide */ + private RangingRequest(List<ResponderConfig> rttPeers, int rttBurstSize) { mRttPeers = rttPeers; + mRttBurstSize = rttBurstSize; + } + + /** + * Returns the list of RTT capable peers. + * + * @return the list of RTT capable peers in a common system representation + * + * @hide + */ + @SystemApi + @NonNull + public List<ResponderConfig> getRttPeers() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mRttPeers; + } + + /** + * Returns the RTT burst size used to determine the average range. + * + * @return the RTT burst size used + */ + public int getRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mRttBurstSize; } @Override @@ -75,6 +149,7 @@ public final class RangingRequest implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeList(mRttPeers); + dest.writeInt(mRttBurstSize); } public static final @android.annotation.NonNull Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() { @@ -85,7 +160,7 @@ public final class RangingRequest implements Parcelable { @Override public RangingRequest createFromParcel(Parcel in) { - return new RangingRequest(in.readArrayList(null)); + return new RangingRequest(in.readArrayList(null), in.readInt()); } }; @@ -105,12 +180,20 @@ public final class RangingRequest implements Parcelable { throw new IllegalArgumentException( "Ranging to too many peers requested. Use getMaxPeers() API to get limit."); } - for (ResponderConfig peer: mRttPeers) { if (!peer.isValid(awareSupported)) { throw new IllegalArgumentException("Invalid Responder specification"); } } + if (SdkLevel.isAtLeastS()) { + if (mRttBurstSize < getMinRttBurstSize() || mRttBurstSize > getMaxRttBurstSize()) { + throw new IllegalArgumentException("RTT burst size is out of range"); + } + } else { + if (mRttBurstSize != DEFAULT_RTT_BURST_SIZE) { + throw new IllegalArgumentException("RTT burst size is not the default value"); + } + } } /** @@ -118,6 +201,32 @@ public final class RangingRequest implements Parcelable { */ public static final class Builder { private List<ResponderConfig> mRttPeers = new ArrayList<>(); + private int mRttBurstSize = DEFAULT_RTT_BURST_SIZE; + + /** + * Set the RTT Burst size for the ranging request. + * <p> + * If not set, the default RTT burst size given by + * {@link #getDefaultRttBurstSize()} is used to determine the default value. + * If set, the value must be in the range {@link #getMinRttBurstSize()} and + * {@link #getMaxRttBurstSize()} inclusively, or a + * {@link java.lang.IllegalArgumentException} will be thrown. + * + * @param rttBurstSize The number of FTM packets used to estimate a range. + * @return The builder to facilitate chaining + * {@code builder.setXXX(..).setXXX(..)}. + */ + @NonNull + public Builder setRttBurstSize(int rttBurstSize) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + if (rttBurstSize < MIN_RTT_BURST_SIZE || rttBurstSize > MAX_RTT_BURST_SIZE) { + throw new IllegalArgumentException("RTT burst size out of range."); + } + mRttBurstSize = rttBurstSize; + return this; + } /** * Add the device specified by the {@link ScanResult} to the list of devices with @@ -241,7 +350,7 @@ public final class RangingRequest implements Parcelable { * builder. */ public RangingRequest build() { - return new RangingRequest(mRttPeers); + return new RangingRequest(mRttPeers, mRttBurstSize); } } @@ -257,11 +366,13 @@ public final class RangingRequest implements Parcelable { RangingRequest lhs = (RangingRequest) o; - return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers); + return mRttPeers.size() == lhs.mRttPeers.size() + && mRttPeers.containsAll(lhs.mRttPeers) + && mRttBurstSize == lhs.mRttBurstSize; } @Override public int hashCode() { - return mRttPeers.hashCode(); + return Objects.hash(mRttPeers, mRttBurstSize); } } diff --git a/wifi/non-updatable/java/Android.bp b/wifi/non-updatable/java/Android.bp new file mode 100644 index 000000000000..b35b4be55818 --- /dev/null +++ b/wifi/non-updatable/java/Android.bp @@ -0,0 +1,35 @@ +// Copyright (C) 2020 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. + +// This directory contains framework Wifi APIs that are not part of the Wifi module (i.e. not +// updatable), and are generally only called by the Wifi module. + +// necessary since we only want the `path` property to only refer to these files +filegroup { + name: "framework-wifi-non-updatable-sources-internal", + srcs: ["src/**/*.java"], + path: "src", + visibility: ["//visibility:private"], +} + +filegroup { + name: "framework-wifi-non-updatable-sources", + srcs: [ + // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and + // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache + // to a separate package. + ":framework-wifi-non-updatable-sources-internal", + ":libwificond_ipc_aidl", + ], +} diff --git a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java b/wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java index c5472ce34478..c5472ce34478 100755 --- a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java +++ b/wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java index 5792d27a94f9..4fabc0b0babc 100755 --- a/wifi/java/android/net/wifi/WifiMigration.java +++ b/wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java @@ -139,8 +139,8 @@ public final class WifiMigration { /** * Load data from legacy shared wifi config store file. * <p> - * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/ - * java/android/net/wifi/migration_samples}. + * Expected AOSP format is available in the sample files under {@code + * frameworks/base/wifi/non-updatable/migration_samples/}. * </p> * <p> * Note: @@ -218,8 +218,8 @@ public final class WifiMigration { /** * Load data from legacy user wifi config store file. * <p> - * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/ - * java/android/net/wifi/migration_samples}. + * Expected AOSP format is available in the sample files under {@code + * frameworks/base/wifi/non-updatable/migration_samples/}. * </p> * <p> * Note: diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java index 378549d62edf..39036580e2ef 100755 --- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java +++ b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java @@ -89,7 +89,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { @Override public final void updateScores(List<ScoredNetwork> networks) { if (networks == null || networks.isEmpty()) { - return; + return; } if (DBG) { Log.d(TAG, "updateScores list size=" + networks.size()); @@ -97,7 +97,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { boolean changed = false; - synchronized(mLock) { + synchronized (mLock) { for (ScoredNetwork network : networks) { String networkKey = buildNetworkKey(network); if (networkKey == null) { @@ -189,7 +189,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub { String key = buildNetworkKey(result); if (key == null) return null; - synchronized(mLock) { + synchronized (mLock) { ScoredNetwork network = mCache.get(key); return network; } diff --git a/wifi/java/android/net/wifi/nl80211/ChannelSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java index 4c14fd499c28..4c14fd499c28 100644 --- a/wifi/java/android/net/wifi/nl80211/ChannelSettings.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java diff --git a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java index bb0cc975a3db..bb0cc975a3db 100644 --- a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java diff --git a/wifi/java/android/net/wifi/nl80211/HiddenNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java index b1475b2c7b43..b1475b2c7b43 100644 --- a/wifi/java/android/net/wifi/nl80211/HiddenNetwork.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java diff --git a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java index 7a9b34b16058..7a9b34b16058 100644 --- a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java diff --git a/wifi/java/android/net/wifi/nl80211/NativeWifiClient.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java index 984d7d034302..984d7d034302 100644 --- a/wifi/java/android/net/wifi/nl80211/NativeWifiClient.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java diff --git a/wifi/java/android/net/wifi/nl80211/PnoNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java index e8eff09583b9..e8eff09583b9 100644 --- a/wifi/java/android/net/wifi/nl80211/PnoNetwork.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java diff --git a/wifi/java/android/net/wifi/nl80211/PnoSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java index 00ebe624ba0d..00ebe624ba0d 100644 --- a/wifi/java/android/net/wifi/nl80211/PnoSettings.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java diff --git a/wifi/java/android/net/wifi/nl80211/RadioChainInfo.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java index 2c12163dc9a1..2c12163dc9a1 100644 --- a/wifi/java/android/net/wifi/nl80211/RadioChainInfo.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java diff --git a/wifi/java/android/net/wifi/nl80211/SingleScanSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java index 24b1854fbf6c..24b1854fbf6c 100644 --- a/wifi/java/android/net/wifi/nl80211/SingleScanSettings.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java index 91d25f94be53..db2eb99297c2 100644 --- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -588,7 +588,7 @@ public class WifiNl80211Manager { public boolean setupInterfaceForClientMode(@NonNull String ifaceName, @NonNull @CallbackExecutor Executor executor, @NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) { - Log.d(TAG, "Setting up interface for client mode"); + Log.d(TAG, "Setting up interface for client mode: " + ifaceName); if (!retrieveWificondAndRegisterForDeath()) { return false; } @@ -646,7 +646,7 @@ public class WifiNl80211Manager { */ public boolean tearDownClientInterface(@NonNull String ifaceName) { if (getClientInterface(ifaceName) == null) { - Log.e(TAG, "No valid wificond client interface handler"); + Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); return false; } try { @@ -661,7 +661,7 @@ public class WifiNl80211Manager { } if (mWificond == null) { - Log.e(TAG, "Reference to wifiCond is null"); + Log.e(TAG, "tearDownClientInterface: mWificond binder is null! Did wificond die?"); return false; } @@ -691,7 +691,7 @@ public class WifiNl80211Manager { * @return true on success. */ public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) { - Log.d(TAG, "Setting up interface for soft ap mode"); + Log.d(TAG, "Setting up interface for soft ap mode for iface=" + ifaceName); if (!retrieveWificondAndRegisterForDeath()) { return false; } @@ -725,12 +725,12 @@ public class WifiNl80211Manager { */ public boolean tearDownSoftApInterface(@NonNull String ifaceName) { if (getApInterface(ifaceName) == null) { - Log.e(TAG, "No valid wificond ap interface handler"); + Log.e(TAG, "No valid wificond ap interface handler for iface=" + ifaceName); return false; } if (mWificond == null) { - Log.e(TAG, "Reference to wifiCond is null"); + Log.e(TAG, "tearDownSoftApInterface: mWificond binder is null! Did wificond die?"); return false; } @@ -797,7 +797,7 @@ public class WifiNl80211Manager { @Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) { IClientInterface iface = getClientInterface(ifaceName); if (iface == null) { - Log.e(TAG, "No valid wificond client interface handler"); + Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); return null; } @@ -828,7 +828,7 @@ public class WifiNl80211Manager { @Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) { IClientInterface iface = getClientInterface(ifaceName); if (iface == null) { - Log.e(TAG, "No valid wificond client interface handler"); + Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); return null; } @@ -871,7 +871,7 @@ public class WifiNl80211Manager { @ScanResultType int scanType) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return new ArrayList<>(); } List<NativeScanResult> results = null; @@ -936,7 +936,7 @@ public class WifiNl80211Manager { @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return false; } SingleScanSettings settings = new SingleScanSettings(); @@ -1002,7 +1002,7 @@ public class WifiNl80211Manager { @NonNull PnoScanRequestCallback callback) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return false; } @@ -1040,7 +1040,7 @@ public class WifiNl80211Manager { public boolean stopPnoScan(@NonNull String ifaceName) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return false; } try { @@ -1065,7 +1065,7 @@ public class WifiNl80211Manager { public void abortScan(@NonNull String ifaceName) { IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); if (scannerImpl == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); return; } try { @@ -1091,7 +1091,7 @@ public class WifiNl80211Manager { */ public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) { if (mWificond == null) { - Log.e(TAG, "No valid wificond scanner interface handler"); + Log.e(TAG, "getChannelsMhzForBand: mWificond binder is null! Did wificond die?"); return new int[0]; } int[] result = null; @@ -1141,7 +1141,7 @@ public class WifiNl80211Manager { */ @Nullable public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) { if (mWificond == null) { - Log.e(TAG, "Can not query for device wiphy capabilities at this time"); + Log.e(TAG, "getDeviceWiphyCapabilities: mWificond binder is null! Did wificond die?"); return null; } @@ -1176,7 +1176,7 @@ public class WifiNl80211Manager { @NonNull SoftApCallback callback) { IApInterface iface = getApInterface(ifaceName); if (iface == null) { - Log.e(TAG, "No valid ap interface handler"); + Log.e(TAG, "No valid ap interface handler for iface=" + ifaceName); return false; } @@ -1234,7 +1234,7 @@ public class WifiNl80211Manager { // TODO (b/112029045) validate mcs IClientInterface clientInterface = getClientInterface(ifaceName); if (clientInterface == null) { - Log.e(TAG, "No valid wificond client interface handler"); + Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN)); return; } diff --git a/wifi/java/android/net/wifi/migration_samples/README.txt b/wifi/non-updatable/migration_samples/README.txt index 264debaa51f9..264debaa51f9 100644 --- a/wifi/java/android/net/wifi/migration_samples/README.txt +++ b/wifi/non-updatable/migration_samples/README.txt diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml b/wifi/non-updatable/migration_samples/Shared_WifiConfigStore.xml index 3063276fae6a..3063276fae6a 100644 --- a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml +++ b/wifi/non-updatable/migration_samples/Shared_WifiConfigStore.xml diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml b/wifi/non-updatable/migration_samples/Shared_WifiConfigStoreSoftAp.xml index fd99dd3df8b2..fd99dd3df8b2 100644 --- a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml +++ b/wifi/non-updatable/migration_samples/Shared_WifiConfigStoreSoftAp.xml diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml b/wifi/non-updatable/migration_samples/User_WifiConfigStore.xml index 67d5aab215f2..67d5aab215f2 100644 --- a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml +++ b/wifi/non-updatable/migration_samples/User_WifiConfigStore.xml diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml b/wifi/non-updatable/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml index 4ecdd29709b4..4ecdd29709b4 100644 --- a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml +++ b/wifi/non-updatable/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml diff --git a/wifi/non-updatable/tests/Android.bp b/wifi/non-updatable/tests/Android.bp new file mode 100644 index 000000000000..3f5cacff017f --- /dev/null +++ b/wifi/non-updatable/tests/Android.bp @@ -0,0 +1,44 @@ +// Copyright (C) 2020 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. + +android_test { + name: "FrameworksWifiNonUpdatableApiTests", + + defaults: ["framework-wifi-test-defaults"], + + srcs: ["src/**/*.java"], + + jacoco: { + include_filter: ["android.net.wifi.*"], + // TODO(b/147521214) need to exclude test classes + exclude_filter: [], + }, + + static_libs: [ + "androidx.test.rules", + "frameworks-base-testutils", + "guava", + "mockito-target-minus-junit4", + "truth-prebuilt", + ], + + libs: [ + "android.test.runner", + "android.test.base", + ], + + test_suites: [ + "general-tests", + ], +} diff --git a/wifi/non-updatable/tests/AndroidManifest.xml b/wifi/non-updatable/tests/AndroidManifest.xml new file mode 100644 index 000000000000..b4b6b2d7997a --- /dev/null +++ b/wifi/non-updatable/tests/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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 + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.net.wifi.test"> + + <application> + <uses-library android:name="android.test.runner"/> + <activity android:label="WifiTestDummyLabel" + android:name="WifiTestDummyName" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.net.wifi.test" + android:label="Frameworks Wifi Non-updatable API Tests"> + </instrumentation> + +</manifest> diff --git a/wifi/non-updatable/tests/AndroidTest.xml b/wifi/non-updatable/tests/AndroidTest.xml new file mode 100644 index 000000000000..5f3fdd46556e --- /dev/null +++ b/wifi/non-updatable/tests/AndroidTest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 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. +--> +<configuration description="Runs Frameworks Wifi Non-updatable API Tests."> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="test-file-name" value="FrameworksWifiNonUpdatableApiTests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-tag" value="FrameworksWifiNonUpdatableApiTests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="android.net.wifi.test" /> + <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/wifi/non-updatable/tests/README.md b/wifi/non-updatable/tests/README.md new file mode 100644 index 000000000000..ad535f4ed86a --- /dev/null +++ b/wifi/non-updatable/tests/README.md @@ -0,0 +1,32 @@ +# Wifi Non-Updatable Framework Unit Tests +This package contains unit tests for the non-updatable part (i.e. outside the Wifi module) of the +Android Wifi framework APIs based on the +[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html). +The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/) +libraries. + +## Running Tests +The easiest way to run tests is simply run + +``` +atest android.net.wifi +``` + +To pick up changes in framework/base, you will need to: +1. rebuild the framework library 'make -j32' +2. sync over the updated library to the device 'adb sync' +3. restart framework on the device 'adb shell stop' then 'adb shell start' + +To enable syncing data to the device for first time after clean reflash: +1. adb disable-verity +2. adb reboot +3. adb remount + +## Adding Tests +Tests can be added by adding classes to the src directory. JUnit4 style test cases can +be written by simply annotating test methods with `org.junit.Test`. + +## Debugging Tests +If you are trying to debug why tests are not doing what you expected, you can add android log +statements and use logcat to view them. The beginning and end of every tests is automatically logged +with the tag `TestRunner`. diff --git a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java b/wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java index f49f387cbc6b..f49f387cbc6b 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java index fdd11a385651..c4967ebf1736 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package android.net.wifi; diff --git a/wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java index 7b900fec70a8..7b900fec70a8 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java diff --git a/wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java index 8ddd1899179a..8ddd1899179a 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java diff --git a/wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java index dec1db8d274e..dec1db8d274e 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java diff --git a/wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java index 905920888012..905920888012 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java diff --git a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java index 9ee0acbfbaa2..9ee0acbfbaa2 100644 --- a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java +++ b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp index 0e58740cbcf2..c0be244da28e 100644 --- a/wifi/tests/Android.bp +++ b/wifi/tests/Android.bp @@ -20,6 +20,9 @@ android_test { defaults: ["framework-wifi-test-defaults"], + min_sdk_version: "30", + target_sdk_version: "30", + srcs: ["**/*.java"], jacoco: { @@ -46,7 +49,7 @@ android_test { ], test_suites: [ - "device-tests", + "general-tests", "mts", ], diff --git a/wifi/tests/AndroidTest.xml b/wifi/tests/AndroidTest.xml index 34e2e3af9cda..2cdaddb59018 100644 --- a/wifi/tests/AndroidTest.xml +++ b/wifi/tests/AndroidTest.xml @@ -20,6 +20,8 @@ <option name="test-suite-tag" value="apct" /> <option name="test-tag" value="FrameworksWifiApiTests" /> + <option name="config-descriptor:metadata" key="mainline-param" + value="com.google.android.wifi.apex" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="android.net.wifi.test" /> <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" /> diff --git a/wifi/tests/src/android/net/wifi/CoexUnsafeChannelTest.java b/wifi/tests/src/android/net/wifi/CoexUnsafeChannelTest.java new file mode 100644 index 000000000000..320f25e715fe --- /dev/null +++ b/wifi/tests/src/android/net/wifi/CoexUnsafeChannelTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 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.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Parcel; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +/** + * Unit tests for {@link android.net.wifi.CoexUnsafeChannel}. + */ +@SmallTest +public class CoexUnsafeChannelTest { + /** + * Verifies {@link CoexUnsafeChannel#isPowerCapAvailable()} returns false if no cap is set. + */ + @Test + public void testIsPowerCapAvailable_noPowerCap_returnsFalse() { + CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6); + + assertThat(unsafeChannel.isPowerCapAvailable()).isFalse(); + } + + /** + * Verifies {@link CoexUnsafeChannel#isPowerCapAvailable()} returns true if a cap is set, and + * {@link CoexUnsafeChannel#getPowerCapDbm()} returns the set value. + */ + @Test + public void testIsPowerCapAvailable_powerCapSet_returnsTrue() { + final int powerCapDbm = -50; + CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6); + + unsafeChannel.setPowerCapDbm(powerCapDbm); + + assertThat(unsafeChannel.isPowerCapAvailable()).isTrue(); + assertThat(unsafeChannel.getPowerCapDbm()).isEqualTo(powerCapDbm); + } + + /** + * Verifies {@link CoexUnsafeChannel#getPowerCapDbm()} throws an IllegalStateException if + * {@link CoexUnsafeChannel#isPowerCapAvailable()} is {@code false}. + */ + @Test(expected = IllegalStateException.class) + public void testGetPowerCap_powerCapUnavailable_throwsException() { + CoexUnsafeChannel unsafeChannel = new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6); + + unsafeChannel.getPowerCapDbm(); + } + + /** + * Verify parcel read/write for CoexUnsafeChannel with or without power cap. + */ + @Test + public void testParcelReadWrite_withOrWithoutCap_readEqualsWritten() throws Exception { + CoexUnsafeChannel writeUnsafeChannelNoCap = + new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6); + CoexUnsafeChannel writeUnsafeChannelCapped = + new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6, -50); + + CoexUnsafeChannel readUnsafeChannelNoCap = parcelReadWrite(writeUnsafeChannelNoCap); + CoexUnsafeChannel readUnsafeChannelCapped = parcelReadWrite(writeUnsafeChannelCapped); + + assertThat(writeUnsafeChannelNoCap).isEqualTo(readUnsafeChannelNoCap); + assertThat(writeUnsafeChannelCapped).isEqualTo(readUnsafeChannelCapped); + } + + /** + * Write the provided {@link CoexUnsafeChannel} to a parcel and deserialize it. + */ + private static CoexUnsafeChannel parcelReadWrite(CoexUnsafeChannel writeResult) + throws Exception { + Parcel parcel = Parcel.obtain(); + writeResult.writeToParcel(parcel, 0); + parcel.setDataPosition(0); // Rewind data position back to the beginning for read. + return CoexUnsafeChannel.CREATOR.createFromParcel(parcel); + } +} diff --git a/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java index b10141434b0b..cf37b78b889a 100644 --- a/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java +++ b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java @@ -19,6 +19,7 @@ package android.net.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import android.annotation.NonNull; import android.util.SparseArray; import androidx.test.filters.SmallTest; @@ -52,6 +53,11 @@ public class EasyConnectStatusCallbackTest { mOnFailureR1EventReceived = true; mLastCode = code; } + + @Override + public void onBootstrapUriGenerated(@NonNull String uri) { + + } }; private boolean mOnFailureR1EventReceived; private int mLastCode; diff --git a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java new file mode 100644 index 000000000000..2f6b7245795f --- /dev/null +++ b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java @@ -0,0 +1,502 @@ +/* + * Copyright (C) 2020 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 org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.os.Parcel; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +import java.util.BitSet; + +/** + * Unit tests for {@link android.net.wifi.WifiInfo}. + */ +@SmallTest +public class SecurityParamsTest { + + private void verifySecurityParams(SecurityParams params, + int expectedSecurityType, + int[] expectedAllowedKeyManagement, + int[] expectedAllowedProtocols, + int[] expectedAllowedAuthAlgorithms, + int[] expectedAllowedPairwiseCiphers, + int[] expectedAllowedGroupCiphers, + boolean expectedRequirePmf) { + assertTrue(params.isSecurityType(expectedSecurityType)); + for (int b: expectedAllowedKeyManagement) { + assertTrue(params.getAllowedKeyManagement().get(b)); + } + for (int b: expectedAllowedProtocols) { + assertTrue(params.getAllowedProtocols().get(b)); + } + for (int b: expectedAllowedAuthAlgorithms) { + assertTrue(params.getAllowedAuthAlgorithms().get(b)); + } + for (int b: expectedAllowedPairwiseCiphers) { + assertTrue(params.getAllowedPairwiseCiphers().get(b)); + } + for (int b: expectedAllowedGroupCiphers) { + assertTrue(params.getAllowedGroupCiphers().get(b)); + } + assertEquals(expectedRequirePmf, params.isRequirePmf()); + } + + /** Verify EAP params creator. */ + @Test + public void testEapCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R1 params creator. */ + @Test + public void testEapPasspointR1Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R2 params creator. */ + @Test + public void testEapPasspointR2Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R3 params creator. */ + @Test + public void testEapPasspointR3Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Enhanced Open params creator. */ + @Test + public void testEnhancedOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createEnhancedOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OWE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Open params creator. */ + @Test + public void testOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify OSEN params creator. */ + @Test + public void testOsenCreator() throws Exception { + SecurityParams p = SecurityParams.createOsenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OSEN}; + int[] expectedAllowedProtocols = new int[] {Protocol.OSEN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI CERT params creator. */ + @Test + public void testWapiCertCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiCertParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_CERT}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI PSK params creator. */ + @Test + public void testWapiPskCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiPskParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_PSK}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WEP params creator. */ + @Test + public void testWepCreator() throws Exception { + SecurityParams p = SecurityParams.createWepParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {AuthAlgorithm.OPEN, AuthAlgorithm.SHARED}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Enterprise 192-bit params creator. */ + @Test + public void testWpa3Enterprise192BitCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3Enterprise192BitParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + int[] expectedAllowedKeyManagement = new int[] { + KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X, KeyMgmt.SUITE_B_192}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + + assertTrue(p.getAllowedGroupManagementCiphers().get(GroupMgmtCipher.BIP_GMAC_256)); + } + + /** Verify WPA3 Enterprise params creator. */ + @Test + public void testWpa3EnterpriseCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.CCMP, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Personal params creator. */ + @Test + public void testWpa3PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.SAE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA2 Personal EAP params creator. */ + @Test + public void testWpaWpa2PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_PSK}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify setter/getter methods */ + @Test + public void testCommonSetterGetter() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + + // PSK setting + BitSet allowedKeyManagement = new BitSet(); + allowedKeyManagement.set(KeyMgmt.WPA_PSK); + + BitSet allowedProtocols = new BitSet(); + allowedProtocols.set(Protocol.RSN); + allowedProtocols.set(Protocol.WPA); + + BitSet allowedPairwiseCiphers = new BitSet(); + allowedPairwiseCiphers.set(PairwiseCipher.CCMP); + allowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + BitSet allowedGroupCiphers = new BitSet(); + allowedGroupCiphers.set(GroupCipher.CCMP); + allowedGroupCiphers.set(GroupCipher.TKIP); + allowedGroupCiphers.set(GroupCipher.WEP40); + allowedGroupCiphers.set(GroupCipher.WEP104); + + assertEquals(allowedKeyManagement, params.getAllowedKeyManagement()); + assertTrue(params.getAllowedKeyManagement().get(KeyMgmt.WPA_PSK)); + + assertEquals(allowedProtocols, params.getAllowedProtocols()); + assertTrue(params.getAllowedProtocols().get(Protocol.RSN)); + assertTrue(params.getAllowedProtocols().get(Protocol.WPA)); + + assertEquals(allowedPairwiseCiphers, params.getAllowedPairwiseCiphers()); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.CCMP)); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.TKIP)); + + assertEquals(allowedGroupCiphers, params.getAllowedGroupCiphers()); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.CCMP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.TKIP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP40)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP104)); + + params.setEnabled(false); + assertFalse(params.isEnabled()); + } + + /** Verify SAE-specific methods */ + @Test + public void testSaeMethods() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + + assertFalse(p.isAddedByAutoUpgrade()); + p.setIsAddedByAutoUpgrade(true); + assertTrue(p.isAddedByAutoUpgrade()); + + assertFalse(p.isSaeH2eOnlyMode()); + p.enableSaeH2eOnlyMode(true); + assertTrue(p.isSaeH2eOnlyMode()); + + assertFalse(p.isSaePkOnlyMode()); + p.enableSaePkOnlyMode(true); + assertTrue(p.isSaePkOnlyMode()); + } + + /** Verify copy constructor. */ + @Test + public void testCopyConstructor() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + params.setEnabled(false); + params.setIsAddedByAutoUpgrade(true); + + SecurityParams copiedParams = new SecurityParams(params); + + assertTrue(params.isSameSecurityType(copiedParams)); + assertEquals(params.getAllowedKeyManagement(), copiedParams.getAllowedKeyManagement()); + assertEquals(params.getAllowedProtocols(), copiedParams.getAllowedProtocols()); + assertEquals(params.getAllowedAuthAlgorithms(), copiedParams.getAllowedAuthAlgorithms()); + assertEquals(params.getAllowedPairwiseCiphers(), copiedParams.getAllowedPairwiseCiphers()); + assertEquals(params.getAllowedGroupCiphers(), copiedParams.getAllowedGroupCiphers()); + assertEquals(params.getAllowedGroupManagementCiphers(), + copiedParams.getAllowedGroupManagementCiphers()); + assertEquals(params.getAllowedSuiteBCiphers(), copiedParams.getAllowedSuiteBCiphers()); + assertEquals(params.isRequirePmf(), copiedParams.isRequirePmf()); + assertEquals(params.isEnabled(), copiedParams.isEnabled()); + assertEquals(params.isSaeH2eOnlyMode(), copiedParams.isSaeH2eOnlyMode()); + assertEquals(params.isSaePkOnlyMode(), copiedParams.isSaePkOnlyMode()); + assertEquals(params.isAddedByAutoUpgrade(), copiedParams.isAddedByAutoUpgrade()); + } + + /** Check that two params are equal if and only if their types are the same. */ + @Test + public void testEquals() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1, saeParams2); + assertNotEquals(saeParams1, pskParams); + } + + /** Check that hash values are the same if and only if their types are the same. */ + @Test + public void testHashCode() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1.hashCode(), saeParams2.hashCode()); + assertNotEquals(saeParams1.hashCode(), pskParams.hashCode()); + } + + /** Verify open network check */ + @Test + public void testIsOpenNetwork() { + SecurityParams[] openSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + }; + for (SecurityParams p: openSecurityParams) { + assertTrue(p.isOpenSecurityType()); + } + + SecurityParams[] nonOpenSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3), + SecurityParams.createOsenParams(), + SecurityParams.createWapiCertParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonOpenSecurityParams) { + assertFalse(p.isOpenSecurityType()); + } + } + + /** Verify enterprise network check */ + @Test + public void testIsEnterpriseNetwork() { + SecurityParams[] enterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3), + SecurityParams.createWapiCertParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + }; + for (SecurityParams p: enterpriseSecurityParams) { + assertTrue(p.isEnterpriseSecurityType()); + } + + SecurityParams[] nonEnterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + SecurityParams.createOsenParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonEnterpriseSecurityParams) { + assertFalse(p.isEnterpriseSecurityType()); + } + } + + /** Check that parcel marshalling/unmarshalling works */ + @Test + public void testParcelMethods() { + SecurityParams params = SecurityParams.createWpa3PersonalParams(); + + Parcel parcelW = Parcel.obtain(); + params.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + + SecurityParams reParams = SecurityParams.createFromParcel(parcelR); + assertEquals(params, reParams); + } +} diff --git a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java index 702212b324f6..9e3b02266de1 100644 --- a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java @@ -42,10 +42,12 @@ public class SoftApCapabilityTest { | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; int[] testSupported2Glist = {1, 2, 3, 4}; int[] testSupported5Glist = {36, 149}; + int[] testSupported60Glist = {1, 2}; SoftApCapability capability = new SoftApCapability(testSoftApFeature); capability.setMaxSupportedClients(10); capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist); SoftApCapability copiedCapability = new SoftApCapability(capability); @@ -64,9 +66,11 @@ public class SoftApCapabilityTest { capability.setMaxSupportedClients(10); int[] testSupported2Glist = {1, 2, 3, 4}; int[] testSupported5Glist = {36, 149}; + int[] testSupported60Glist = {1, 2}; capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist); Parcel parcelW = Parcel.obtain(); capability.writeToParcel(parcelW, 0); diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index ad0fdd3bce26..a609a120b61f 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import android.net.MacAddress; import android.os.Parcel; @@ -371,6 +372,7 @@ public class SoftApConfigurationTest { @Test public void testDualBands() { + assumeTrue(SdkLevel.isAtLeastS()); int[] dual_bands = new int[2]; dual_bands[0] = SoftApConfiguration.BAND_2GHZ; dual_bands[1] = SoftApConfiguration.BAND_5GHZ; @@ -384,6 +386,7 @@ public class SoftApConfigurationTest { @Test public void testDualChannels() { + assumeTrue(SdkLevel.isAtLeastS()); int[] expected_dual_bands = new int[2]; expected_dual_bands[0] = SoftApConfiguration.BAND_2GHZ; expected_dual_bands[1] = SoftApConfiguration.BAND_5GHZ; @@ -417,6 +420,7 @@ public class SoftApConfigurationTest { @Test public void testInvalidBandWhenSetBands() { + assumeTrue(SdkLevel.isAtLeastS()); boolean isIllegalArgumentExceptionHappened = false; int[] dual_bands = new int[2]; dual_bands[0] = SoftApConfiguration.BAND_2GHZ; @@ -457,6 +461,7 @@ public class SoftApConfigurationTest { @Test public void testInvalidConfigWhenSetChannels() { + assumeTrue(SdkLevel.isAtLeastS()); boolean isIllegalArgumentExceptionHappened = false; SparseIntArray invalid_channels = new SparseIntArray(); try { @@ -514,4 +519,14 @@ public class SoftApConfigurationTest { } assertTrue(isIllegalArgumentExceptionHappened); } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidConfigWhenSet60GhzChannels() throws Exception { + SparseIntArray invalid_channels = new SparseIntArray(); + invalid_channels.put(SoftApConfiguration.BAND_60GHZ, 99); + SoftApConfiguration config = new SoftApConfiguration.Builder() + .setSsid("ssid") + .setChannels(invalid_channels) + .build(); + } } diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java index 28758432119c..2121d10121b0 100644 --- a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java @@ -32,17 +32,22 @@ import org.junit.Test; */ @SmallTest public class SoftApInfoTest { - + private static final String TEST_AP_INSTANCE = "wlan1"; + private static final int TEST_FREQUENCY = 2412; + private static final int TEST_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; + private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_LEGACY; + private static final MacAddress TEST_AP_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); /** * Verifies copy constructor. */ @Test public void testCopyOperator() throws Exception { SoftApInfo info = new SoftApInfo(); - info.setFrequency(2412); - info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); - info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); - info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); SoftApInfo copiedInfo = new SoftApInfo(info); @@ -57,10 +62,11 @@ public class SoftApInfoTest { @Test public void testParcelOperation() throws Exception { SoftApInfo info = new SoftApInfo(); - info.setFrequency(2412); - info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); - info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); - info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); Parcel parcelW = Parcel.obtain(); info.writeToParcel(parcelW, 0); @@ -88,6 +94,27 @@ public class SoftApInfoTest { if (SdkLevel.isAtLeastS()) { assertEquals(info.getBssid(), null); assertEquals(info.getWifiStandard(), ScanResult.WIFI_STANDARD_UNKNOWN); + assertEquals(info.getApInstanceIdentifier(), null); + } + } + + /** + * Verifies the set/get method same as expected. + */ + @Test + public void testGetXXXAlignedWithSetXXX() throws Exception { + SoftApInfo info = new SoftApInfo(); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); + assertEquals(info.getFrequency(), TEST_FREQUENCY); + assertEquals(info.getBandwidth(), TEST_BANDWIDTH); + if (SdkLevel.isAtLeastS()) { + assertEquals(info.getBssid(), TEST_AP_MAC); + assertEquals(info.getWifiStandard(), TEST_WIFI_STANDARD); + assertEquals(info.getApInstanceIdentifier(), TEST_AP_INSTANCE); } } diff --git a/wifi/tests/src/android/net/wifi/WifiClientTest.java b/wifi/tests/src/android/net/wifi/WifiClientTest.java index 7a3baf9ebaf2..704656320a91 100644 --- a/wifi/tests/src/android/net/wifi/WifiClientTest.java +++ b/wifi/tests/src/android/net/wifi/WifiClientTest.java @@ -42,9 +42,9 @@ public class WifiClientTest { */ @Test public void testWifiClientParcelWriteRead() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); - assertParcelSane(writeWifiClient, 1); + assertParcelSane(writeWifiClient, 2); } /** @@ -52,12 +52,12 @@ public class WifiClientTest { */ @Test public void testWifiClientEquals() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); - WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); assertEquals(writeWifiClient, writeWifiClientEquals); assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode()); - assertFieldCountEquals(1, WifiClient.class); + assertFieldCountEquals(2, WifiClient.class); } /** @@ -66,8 +66,8 @@ public class WifiClientTest { @Test public void testWifiClientNotEquals() throws Exception { final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00"); - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); - WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME); assertNotEquals(writeWifiClient, writeWifiClientNotEquals); assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java index 0a80dc2890ad..f351e61b5eb8 100644 --- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java @@ -17,14 +17,16 @@ package android.net.wifi; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP; -import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OSEN; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -34,22 +36,32 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import android.net.MacAddress; -import android.net.util.MacAddressUtils; +import android.net.wifi.WifiConfiguration.GroupCipher; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; import android.os.Parcel; +import android.util.Pair; import androidx.test.filters.SmallTest; +import com.android.net.module.util.MacAddressUtils; + import org.junit.Before; import org.junit.Test; +import java.util.List; + /** * Unit tests for {@link android.net.wifi.WifiConfiguration}. */ @SmallTest public class WifiConfigurationTest { private static final String TEST_PASSPOINT_UNIQUE_ID = "uniqueId"; + private static final int TEST_CARRIER_ID = 1234; + private static final int TEST_SUB_ID = 3; + private static final String TEST_PACKAGE_NAME = "google.com"; @Before public void setUp() { @@ -71,6 +83,7 @@ public class WifiConfigurationTest { config.trusted = false; config.oemPaid = true; config.oemPrivate = true; + config.carrierMerged = true; config.updateIdentifier = "1234"; config.fromWifiNetworkSpecifier = true; config.fromWifiNetworkSuggestion = true; @@ -97,6 +110,7 @@ public class WifiConfigurationTest { assertTrue(reconfig.fromWifiNetworkSuggestion); assertTrue(reconfig.oemPaid); assertTrue(reconfig.oemPrivate); + assertTrue(reconfig.carrierMerged); Parcel parcelWW = Parcel.obtain(); reconfig.writeToParcel(parcelWW, 0); @@ -112,6 +126,7 @@ public class WifiConfigurationTest { config.trusted = false; config.oemPaid = true; config.oemPrivate = true; + config.carrierMerged = true; config.updateIdentifier = "1234"; config.fromWifiNetworkSpecifier = true; config.fromWifiNetworkSuggestion = true; @@ -130,6 +145,7 @@ public class WifiConfigurationTest { assertTrue(reconfig.fromWifiNetworkSuggestion); assertTrue(reconfig.oemPaid); assertTrue(reconfig.oemPrivate); + assertTrue(reconfig.carrierMerged); } @Test @@ -179,18 +195,24 @@ public class WifiConfigurationTest { @Test public void testIsOpenNetwork_NotOpen_HasAuthType() { - for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) { - if (keyMgmt == WifiConfiguration.KeyMgmt.NONE - || keyMgmt == WifiConfiguration.KeyMgmt.OWE) { - continue; - } + int[] securityTypes = new int [] { + SECURITY_TYPE_WEP, + SECURITY_TYPE_PSK, + SECURITY_TYPE_EAP, + SECURITY_TYPE_SAE, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, + SECURITY_TYPE_WAPI_PSK, + SECURITY_TYPE_WAPI_CERT, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE, + SECURITY_TYPE_OSEN, + }; + for (int type: securityTypes) { WifiConfiguration config = new WifiConfiguration(); - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(keyMgmt); + config.setSecurityParams(type); config.wepKeys = null; - assertFalse("Open network reported when key mgmt was set to " - + WifiConfiguration.KeyMgmt.strings[keyMgmt], config.isOpenNetwork()); + assertFalse("Open network reported when security type was set to " + + type, config.isOpenNetwork()); } } @@ -200,6 +222,7 @@ public class WifiConfigurationTest { config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); config.wepKeys = null; + config.convertLegacyFieldsToSecurityParamsIfNeeded(); assertFalse(config.isOpenNetwork()); } @@ -422,11 +445,11 @@ public class WifiConfigurationTest { } /** - * Verifies that getMacRandomKey returns the correct String for networks of + * Verifies that getNetworkKey returns the correct String for networks of * various different security types, the result should be stable. */ @Test - public void testGetMacRandomKeyString() { + public void testGetNetworkKeyString() { WifiConfiguration config = new WifiConfiguration(); final String mSsid = "TestAP"; config.SSID = mSsid; @@ -434,23 +457,23 @@ public class WifiConfigurationTest { // Test various combinations config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WPA_PSK], - config.getMacRandomKey()); + config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WPA_EAP], - config.getMacRandomKey()); + config.getNetworkKey()); config.wepKeys[0] = "TestWep"; config.allowedKeyManagement.clear(); - assertEquals(mSsid + "WEP", config.getMacRandomKey()); + assertEquals(mSsid + "WEP", config.getNetworkKey()); // set WEP key and give a valid index. config.wepKeys[0] = null; config.wepKeys[2] = "TestWep"; config.wepTxKeyIndex = 2; config.allowedKeyManagement.clear(); - assertEquals(mSsid + "WEP", config.getMacRandomKey()); + assertEquals(mSsid + "WEP", config.getNetworkKey()); // set WEP key but does not give a valid index. config.wepKeys[0] = null; @@ -458,40 +481,40 @@ public class WifiConfigurationTest { config.wepTxKeyIndex = 0; config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.OWE); - assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getMacRandomKey()); + assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getNetworkKey()); config.wepKeys[0] = null; config.wepTxKeyIndex = 0; config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.OWE); - assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getMacRandomKey()); + assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.OWE], config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.SAE); - assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.SAE], config.getMacRandomKey()); + assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.SAE], config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192); assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.SUITE_B_192], - config.getMacRandomKey()); + config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.NONE); - assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.NONE], config.getMacRandomKey()); + assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.NONE], config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.WAPI_PSK); assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_PSK], - config.getMacRandomKey()); + config.getNetworkKey()); config.allowedKeyManagement.clear(); config.allowedKeyManagement.set(KeyMgmt.WAPI_CERT); assertEquals(mSsid + KeyMgmt.strings[KeyMgmt.WAPI_CERT], - config.getMacRandomKey()); + config.getNetworkKey()); config.allowedKeyManagement.clear(); config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID); - assertEquals(TEST_PASSPOINT_UNIQUE_ID, config.getMacRandomKey()); + assertEquals(TEST_PASSPOINT_UNIQUE_ID, config.getNetworkKey()); } /** @@ -569,7 +592,7 @@ public class WifiConfigurationTest { public void testSetSecurityParamsForSuiteB() throws Exception { WifiConfiguration config = new WifiConfiguration(); - config.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B); + config.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)); assertTrue(config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP)); @@ -665,7 +688,7 @@ public class WifiConfigurationTest { configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE); assertFalse(configuration.needsPreSharedKey()); - configuration.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); assertFalse(configuration.needsPreSharedKey()); } @@ -694,7 +717,7 @@ public class WifiConfigurationTest { configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE); assertEquals(KeyMgmt.WPA_EAP, configuration.getAuthType()); - configuration.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B); + configuration.setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); assertEquals(KeyMgmt.SUITE_B_192, configuration.getAuthType()); configuration.setSecurityParams(SECURITY_TYPE_WAPI_CERT); @@ -719,4 +742,381 @@ public class WifiConfigurationTest { configuration.allowedKeyManagement.set(KeyMgmt.SAE); configuration.getAuthType(); } + + /** + * Verifies that getProfileKey returns the correct String for networks of + * various different security types, the result should be stable. + */ + @Test + public void testGetProfileKeyString() { + WifiConfiguration config = new WifiConfiguration(); + final String mSsid = "TestAP"; + config.SSID = mSsid; + config.carrierId = TEST_CARRIER_ID; + config.subscriptionId = TEST_SUB_ID; + config.creatorName = TEST_PACKAGE_NAME; + + + // Test various combinations + config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_PSK], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_PSK], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_EAP], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WPA_EAP], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.wepKeys[0] = "TestWep"; + config.allowedKeyManagement.clear(); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + // set WEP key and give a valid index. + config.wepKeys[0] = null; + config.wepKeys[2] = "TestWep"; + config.wepTxKeyIndex = 2; + config.allowedKeyManagement.clear(); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, "WEP", TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + // set WEP key but does not give a valid index. + config.wepKeys[0] = null; + config.wepKeys[2] = "TestWep"; + config.wepTxKeyIndex = 0; + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.OWE); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.wepKeys[0] = null; + config.wepTxKeyIndex = 0; + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.OWE); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.OWE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.SAE); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SAE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SAE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SUITE_B_192], + TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.SUITE_B_192], + TEST_PACKAGE_NAME, TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.NONE); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.NONE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.NONE], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.WAPI_PSK); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_PSK], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_PSK], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.allowedKeyManagement.set(KeyMgmt.WAPI_CERT); + config.fromWifiNetworkSuggestion = false; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_CERT], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, false), config.getProfileKey()); + config.fromWifiNetworkSuggestion = true; + assertEquals(createProfileKey(mSsid, KeyMgmt.strings[KeyMgmt.WAPI_CERT], TEST_PACKAGE_NAME, + TEST_CARRIER_ID, TEST_SUB_ID, true), config.getProfileKey()); + + config.allowedKeyManagement.clear(); + config.setPasspointUniqueId(TEST_PASSPOINT_UNIQUE_ID); + assertEquals(TEST_PASSPOINT_UNIQUE_ID, config.getProfileKey()); + } + + private String createProfileKey(String ssid, String keyMgmt, String providerName, + int carrierId, int subId, boolean isFromSuggestion) { + StringBuilder sb = new StringBuilder(); + sb.append(ssid).append(keyMgmt); + if (isFromSuggestion) { + sb.append("_").append(providerName).append('-') + .append(carrierId).append('-').append(subId); + } + return sb.toString(); + } + + private void verifyAllowedKeyManagement(WifiConfiguration config, int[] akms) { + for (int akm: akms) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(akm))); + } + } + + private void verifyAllowedProtocols(WifiConfiguration config, int[] aps) { + for (int ap: aps) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedProtocols().get(ap))); + } + } + + private void verifyAllowedPairwiseCiphers(WifiConfiguration config, int[] apcs) { + for (int apc: apcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedPairwiseCiphers().get(apc))); + } + } + + private void verifyAllowedGroupCiphers(WifiConfiguration config, int[] agcs) { + for (int agc: agcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedGroupCiphers().get(agc))); + } + } + + /** Verify that adding security types works as expected. */ + @Test + public void testAddSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + config.addSecurityParams(SecurityParams.createWapiPskParams()); + List<SecurityParams> paramsList = config.getSecurityParamsList(); + assertEquals(3, paramsList.size()); + + verifyAllowedKeyManagement(config, new int[] { + KeyMgmt.WPA_PSK, KeyMgmt.SAE, KeyMgmt.WAPI_PSK}); + verifyAllowedProtocols(config, new int[] {Protocol.WPA, Protocol.RSN, Protocol.WAPI}); + verifyAllowedPairwiseCiphers(config, new int[] { + PairwiseCipher.CCMP, PairwiseCipher.TKIP, + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256, + PairwiseCipher.SMS4}); + verifyAllowedGroupCiphers(config, new int[] { + GroupCipher.CCMP, GroupCipher.TKIP, + GroupCipher.GCMP_128, GroupCipher.GCMP_256, + GroupCipher.SMS4}); + } + + /** Check that a personal security type can be added to a personal configuration. */ + @Test + public void testAddPersonalTypeToPersonalConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + } + + /** Check that an enterprise security type can be added to an enterprise configuration. */ + @Test + public void testAddEnterpriseTypeToEnterpriseConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } + + /** Verify that adding an enterprise type to a personal configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddEnterpriseTypeToPersonalConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + } + + /** Verify that adding a personal type to an enterprise configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddPersonalTypeToEnterpriseConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that an open security cannot be added to a non-open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOpenTypeToNonOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + } + + /** Check that a non-open security cannot be added to an open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddNonOpenTypeToOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that a OSEN security cannot be added as additional type. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOsenTypeToConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OSEN); + } + + /** Verify that adding duplicate security types raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Verify that adding duplicate security params raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityParams() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + } + + /** Verify that Suite-B type works as expected. */ + @Test + public void testAddSuiteBSecurityType() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpa3EnterpriseParams()); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(SecurityParams.createWpa3Enterprise192BitParams()); + + assertFalse(config.isSuiteBCipherEcdheRsaEnabled()); + config.enableSuiteBCiphers(false, true); + assertTrue(config.isSuiteBCipherEcdheRsaEnabled()); + } + + /** Verify that FILS bit can be set correctly. */ + @Test + public void testFilsKeyMgmt() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + config.enableFils(false, true); + assertFalse(config.isFilsSha256Enabled()); + assertTrue(config.isFilsSha384Enabled()); + } + + /** Verify that SAE mode can be configured correctly. */ + @Test + public void testSaeTypeMethods() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + SecurityParams saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertFalse(saeParams.isSaeH2eOnlyMode()); + assertFalse(saeParams.isSaePkOnlyMode()); + + config.enableSaeH2eOnlyMode(true); + config.enableSaePkOnlyMode(true); + + saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertTrue(saeParams.isSaeH2eOnlyMode()); + assertTrue(saeParams.isSaePkOnlyMode()); + } + + /** Verify the legacy configuration conversion */ + @Test + public void testLegacyConfigurationConversion() { + Pair[] keyMgmtSecurityTypePairs = new Pair[] { + new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT), + new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK), + new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE), + new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE), + new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN), + new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP), + new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN), + }; + + for (Pair pair: keyMgmtSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.allowedKeyManagement.set((int) pair.first); + config.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + + // If none of key management is set, it should be open. + WifiConfiguration emptyConfig = new WifiConfiguration(); + emptyConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(emptyConfig.getSecurityParams(SECURITY_TYPE_OPEN)); + + // If EAP key management is set and requirePmf is true, it is WPA3 Enterprise. + WifiConfiguration wpa3EnterpriseConfig = new WifiConfiguration(); + wpa3EnterpriseConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP); + wpa3EnterpriseConfig.requirePmf = true; + wpa3EnterpriseConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wpa3EnterpriseConfig.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE)); + + // If key management is NONE and wep key is set, it is WEP type. + WifiConfiguration wepConfig = new WifiConfiguration(); + wepConfig.allowedKeyManagement.set(KeyMgmt.NONE); + wepConfig.wepKeys = new String[] {"\"abcdef\""}; + wepConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wepConfig.getSecurityParams(SECURITY_TYPE_WEP)); + } + + /** Verify the set security params by SecurityParams objects. */ + @Test + public void testSetBySecurityParamsObject() { + Pair[] securityParamsSecurityTypePairs = new Pair[] { + new Pair<>(SecurityParams.createWapiCertParams(), SECURITY_TYPE_WAPI_CERT), + new Pair<>(SecurityParams.createWapiPskParams(), SECURITY_TYPE_WAPI_PSK), + new Pair<>(SecurityParams.createWpa3Enterprise192BitParams(), + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(SecurityParams.createEnhancedOpenParams(), SECURITY_TYPE_OWE), + new Pair<>(SecurityParams.createWpa3PersonalParams(), SECURITY_TYPE_SAE), + new Pair<>(SecurityParams.createOsenParams(), SECURITY_TYPE_OSEN), + new Pair<>(SecurityParams.createWpaWpa2EnterpriseParams(), SECURITY_TYPE_EAP), + new Pair<>(SecurityParams.createWpaWpa2PersonalParams(), SECURITY_TYPE_PSK), + new Pair<>(SecurityParams.createOpenParams(), SECURITY_TYPE_OPEN), + }; + for (Pair pair: securityParamsSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams((SecurityParams) pair.first); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + } } diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java index c6faf66140e2..33438ed9008e 100644 --- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java +++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import android.os.Parcel; +import android.telephony.SubscriptionManager; import androidx.test.filters.SmallTest; @@ -50,6 +51,7 @@ public class WifiInfoTest { private static final int TEST_RSSI = -60; private static final int TEST_NETWORK_ID = 5; private static final int TEST_NETWORK_ID2 = 6; + private static final int TEST_SUB_ID = 1; /** * Verify parcel write/read with WifiInfo. @@ -64,6 +66,7 @@ public class WifiInfoTest { writeWifiInfo.setTrusted(true); writeWifiInfo.setOemPaid(true); writeWifiInfo.setOemPrivate(true); + writeWifiInfo.setCarrierMerged(true); writeWifiInfo.setOsuAp(true); writeWifiInfo.setFQDN(TEST_FQDN); writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME); @@ -71,6 +74,7 @@ public class WifiInfoTest { writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD); writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS); writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS); + writeWifiInfo.setSubscriptionId(TEST_SUB_ID); Parcel parcel = Parcel.obtain(); writeWifiInfo.writeToParcel(parcel, 0); @@ -86,6 +90,7 @@ public class WifiInfoTest { assertTrue(readWifiInfo.isTrusted()); assertTrue(readWifiInfo.isOemPaid()); assertTrue(readWifiInfo.isOemPrivate()); + assertTrue(readWifiInfo.isCarrierMerged()); assertTrue(readWifiInfo.isOsuAp()); assertTrue(readWifiInfo.isPasspointAp()); assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName()); @@ -96,6 +101,7 @@ public class WifiInfoTest { readWifiInfo.getMaxSupportedTxLinkSpeedMbps()); assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS, readWifiInfo.getMaxSupportedRxLinkSpeedMbps()); + assertEquals(TEST_SUB_ID, readWifiInfo.getSubscriptionId()); } @Test @@ -108,6 +114,7 @@ public class WifiInfoTest { writeWifiInfo.setTrusted(true); writeWifiInfo.setOemPaid(true); writeWifiInfo.setOemPrivate(true); + writeWifiInfo.setCarrierMerged(true); writeWifiInfo.setOsuAp(true); writeWifiInfo.setFQDN(TEST_FQDN); writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME); @@ -115,6 +122,7 @@ public class WifiInfoTest { writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD); writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS); writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS); + writeWifiInfo.setSubscriptionId(TEST_SUB_ID); WifiInfo readWifiInfo = new WifiInfo(writeWifiInfo); @@ -125,6 +133,7 @@ public class WifiInfoTest { assertTrue(readWifiInfo.isTrusted()); assertTrue(readWifiInfo.isOemPaid()); assertTrue(readWifiInfo.isOemPrivate()); + assertTrue(readWifiInfo.isCarrierMerged()); assertTrue(readWifiInfo.isOsuAp()); assertTrue(readWifiInfo.isPasspointAp()); assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName()); @@ -135,6 +144,7 @@ public class WifiInfoTest { readWifiInfo.getMaxSupportedTxLinkSpeedMbps()); assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS, readWifiInfo.getMaxSupportedRxLinkSpeedMbps()); + assertEquals(TEST_SUB_ID, readWifiInfo.getSubscriptionId()); } /** @@ -154,6 +164,8 @@ public class WifiInfoTest { assertEquals(-1, wifiInfo.getNetworkId()); assertFalse(wifiInfo.isOemPaid()); assertFalse(wifiInfo.isOemPrivate()); + assertFalse(wifiInfo.isCarrierMerged()); + assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, wifiInfo.getSubscriptionId()); } /** diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 7340b145e8b2..b15fa2c926f4 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -19,6 +19,9 @@ package android.net.wifi; import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; import static android.net.wifi.WifiManager.ActionListener; import static android.net.wifi.WifiManager.BUSY; +import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP; +import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE; +import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT; import static android.net.wifi.WifiManager.ERROR; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; @@ -43,6 +46,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_SCANNER; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; import static android.net.wifi.WifiManager.WpsCallback; +import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -74,6 +78,7 @@ import android.content.Context; import android.content.pm.ApplicationInfo; import android.net.DhcpInfo; import android.net.MacAddress; +import android.net.wifi.WifiManager.CoexCallback; import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; import android.net.wifi.WifiManager.LocalOnlyHotspotObserver; import android.net.wifi.WifiManager.LocalOnlyHotspotReservation; @@ -84,6 +89,7 @@ import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener; import android.net.wifi.WifiManager.ScanResultsCallback; import android.net.wifi.WifiManager.SoftApCallback; import android.net.wifi.WifiManager.SuggestionConnectionStatusListener; +import android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener; import android.net.wifi.WifiManager.TrafficStateCallback; import android.net.wifi.WifiManager.WifiConnectedNetworkScorer; import android.os.Build; @@ -108,9 +114,11 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.concurrent.Executor; /** @@ -129,6 +137,8 @@ public class WifiManagerTest { private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"}; private static final int TEST_AP_FREQUENCY = 2412; private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; + private static final int TEST_SUB_ID = 3; + private static final String TEST_AP_INSTANCE = "wlan1"; @Mock Context mContext; @Mock android.net.wifi.IWifiManager mWifiService; @@ -139,18 +149,20 @@ public class WifiManagerTest { @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback; @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener; @Mock OnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener; - @Mock SuggestionConnectionStatusListener mListener; + @Mock SuggestionConnectionStatusListener mSuggestionConnectionListener; @Mock Runnable mRunnable; @Mock Executor mExecutor; @Mock Executor mAnotherExecutor; @Mock ActivityManager mActivityManager; @Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer; + @Mock SuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener; private Handler mHandler; private TestLooper mLooper; private WifiManager mWifiManager; private WifiNetworkSuggestion mWifiNetworkSuggestion; private ScanResultsCallback mScanResultsCallback; + private CoexCallback mCoexCallback; private WifiActivityEnergyInfo mWifiActivityEnergyInfo; /** @@ -214,10 +226,149 @@ public class WifiManagerTest { mRunnable.run(); } }; + mCoexCallback = new CoexCallback() { + @Override + public void onCoexUnsafeChannelsChanged() { + mRunnable.run(); + } + }; mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0); } /** + * Check the call to setCoexUnsafeChannels calls WifiServiceImpl to setCoexUnsafeChannels with + * the provided CoexUnsafeChannels and restrictions bitmask. + */ + @Test + public void testSetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception { + Set<CoexUnsafeChannel> unsafeChannels = new HashSet<>(); + int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP + | COEX_RESTRICTION_WIFI_AWARE; + + mWifiManager.setCoexUnsafeChannels(unsafeChannels, restrictions); + + verify(mWifiService).setCoexUnsafeChannels(new ArrayList<>(unsafeChannels), restrictions); + } + + /** + * Verify an IllegalArgumentException if passed a null value for unsafeChannels. + */ + @Test + public void testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels() { + try { + mWifiManager.setCoexUnsafeChannels(null, 0); + fail("expected IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + } + } + + /** + * Check the call to getCoexUnsafeChannels calls WifiServiceImpl to return the values from + * getCoexUnsafeChannels. + */ + @Test + public void testGetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception { + Set<CoexUnsafeChannel> unsafeChannels = new HashSet<>(); + unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6)); + when(mWifiService.getCoexUnsafeChannels()).thenReturn(new ArrayList<>(unsafeChannels)); + + assertEquals(mWifiManager.getCoexUnsafeChannels(), unsafeChannels); + } + + /** + * Verify call to getCoexRestrictions calls WifiServiceImpl to return the value from + * getCoexRestrictions. + */ + @Test + public void testGetCoexRestrictionsGoesToWifiServiceImpl() throws Exception { + int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP + | COEX_RESTRICTION_WIFI_AWARE; + when(mWifiService.getCoexRestrictions()).thenReturn(restrictions); + + assertEquals(mWifiService.getCoexRestrictions(), restrictions); + } + + + /** + * Verify an IllegalArgumentException is thrown if callback is not provided. + */ + @Test(expected = IllegalArgumentException.class) + public void testRegisterCoexCallbackWithNullCallback() throws Exception { + mWifiManager.registerCoexCallback(mExecutor, null); + } + + /** + * Verify an IllegalArgumentException is thrown if executor is not provided. + */ + @Test(expected = IllegalArgumentException.class) + public void testRegisterCoexCallbackWithNullExecutor() throws Exception { + mWifiManager.registerCoexCallback(null, mCoexCallback); + } + + /** + * Verify client provided callback is being called to the right callback. + */ + @Test + public void testAddCoexCallbackAndReceiveEvent() throws Exception { + ArgumentCaptor<ICoexCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ICoexCallback.Stub.class); + mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback); + verify(mWifiService).registerCoexCallback(callbackCaptor.capture()); + callbackCaptor.getValue().onCoexUnsafeChannelsChanged(); + verify(mRunnable).run(); + } + + /** + * Verify client provided callback is being called to the right executor. + */ + @Test + public void testRegisterCoexCallbackWithTheTargetExecutor() throws Exception { + ArgumentCaptor<ICoexCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ICoexCallback.Stub.class); + mWifiManager.registerCoexCallback(mExecutor, mCoexCallback); + verify(mWifiService).registerCoexCallback(callbackCaptor.capture()); + mWifiManager.registerCoexCallback(mAnotherExecutor, mCoexCallback); + callbackCaptor.getValue().onCoexUnsafeChannelsChanged(); + verify(mExecutor, never()).execute(any(Runnable.class)); + verify(mAnotherExecutor).execute(any(Runnable.class)); + } + + /** + * Verify client register unregister then register again, to ensure callback still works. + */ + @Test + public void testRegisterUnregisterThenRegisterAgainWithCoexCallback() throws Exception { + ArgumentCaptor<ICoexCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ICoexCallback.Stub.class); + mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback); + verify(mWifiService).registerCoexCallback(callbackCaptor.capture()); + mWifiManager.unregisterCoexCallback(mCoexCallback); + callbackCaptor.getValue().onCoexUnsafeChannelsChanged(); + verify(mRunnable, never()).run(); + mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback); + callbackCaptor.getValue().onCoexUnsafeChannelsChanged(); + verify(mRunnable).run(); + } + + /** + * Verify client unregisterCoexCallback. + */ + @Test + public void testUnregisterCoexCallback() throws Exception { + mWifiManager.unregisterCoexCallback(mCoexCallback); + verify(mWifiService).unregisterCoexCallback(any()); + } + + /** + * Verify client unregisterCoexCallback with null callback will cause an exception. + */ + @Test(expected = IllegalArgumentException.class) + public void testUnregisterCoexCallbackWithNullCallback() throws Exception { + mWifiManager.unregisterCoexCallback(null); + } + + + /** * Check the call to startSoftAp calls WifiService to startSoftAp with the provided * WifiConfiguration. Verify that the return value is propagated to the caller. */ @@ -963,6 +1114,27 @@ public class WifiManagerTest { verify(mSoftApCallback).onInfoChanged(testSoftApInfo); } + /* + * Verify client-provided callback is being called through callback proxy + */ + @Test + public void softApCallbackProxyCallsOnSoftApInfoListChanged() throws Exception { + SoftApInfo testSoftApInfo = new SoftApInfo(); + testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); + testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); + List<SoftApInfo> infoList = new ArrayList<>(); + infoList.add(testSoftApInfo); + ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ISoftApCallback.Stub.class); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); + verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), + anyInt()); + + callbackCaptor.getValue().onInfoListChanged(infoList); + mLooper.dispatchAll(); + verify(mSoftApCallback).onInfoListChanged(infoList); + } + /* * Verify client-provided callback is being called through callback proxy @@ -987,7 +1159,8 @@ public class WifiManagerTest { */ @Test public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception { - WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77")); + WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"), + TEST_AP_INSTANCE); ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); @@ -1009,6 +1182,8 @@ public class WifiManagerTest { SoftApInfo testSoftApInfo = new SoftApInfo(); testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); + List<SoftApInfo> infoList = new ArrayList<>(); + infoList.add(testSoftApInfo); SoftApCapability testSoftApCapability = new SoftApCapability(0); testSoftApCapability.setMaxSupportedClients(10); ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = @@ -1021,6 +1196,7 @@ public class WifiManagerTest { callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0); callbackCaptor.getValue().onConnectedClientsChanged(testClients); callbackCaptor.getValue().onInfoChanged(testSoftApInfo); + callbackCaptor.getValue().onInfoListChanged(infoList); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability); @@ -1029,6 +1205,7 @@ public class WifiManagerTest { verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0); verify(mSoftApCallback).onConnectedClientsChanged(testClients); verify(mSoftApCallback).onInfoChanged(testSoftApInfo); + verify(mSoftApCallback).onInfoListChanged(infoList); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability); } @@ -1634,6 +1811,24 @@ public class WifiManagerTest { } /** + * Verify the call to startTemporarilyDisablingAllNonCarrierMergedWifi goes to WifiServiceImpl. + */ + @Test + public void testStartTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception { + mWifiManager.startTemporarilyDisablingAllNonCarrierMergedWifi(1); + verify(mWifiService).startTemporarilyDisablingAllNonCarrierMergedWifi(1); + } + + /** + * Verify the call to stopTemporarilyDisablingAllNonCarrierMergedWifi goes to WifiServiceImpl. + */ + @Test + public void testStopTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception { + mWifiManager.stopTemporarilyDisablingAllNonCarrierMergedWifi(); + verify(mWifiService).stopTemporarilyDisablingAllNonCarrierMergedWifi(); + } + + /** * Verify the call to addOnWifiUsabilityStatsListener goes to WifiServiceImpl. */ @Test @@ -2161,7 +2356,7 @@ public class WifiManagerTest { */ @Test(expected = IllegalArgumentException.class) public void testAddSuggestionConnectionStatusListenerWithNullExecutor() { - mWifiManager.addSuggestionConnectionStatusListener(null, mListener); + mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener); } /** @@ -2181,11 +2376,12 @@ public class WifiManagerTest { ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor = ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class); Executor executor = new SynchronousExecutor(); - mWifiManager.addSuggestionConnectionStatusListener(executor, mListener); + mWifiManager.addSuggestionConnectionStatusListener(executor, mSuggestionConnectionListener); verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class), callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class)); callbackCaptor.getValue().onConnectionStatus(mWifiNetworkSuggestion, errorCode); - verify(mListener).onConnectionStatus(any(WifiNetworkSuggestion.class), eq(errorCode)); + verify(mSuggestionConnectionListener).onConnectionStatus(any(WifiNetworkSuggestion.class), + eq(errorCode)); } /** @@ -2196,7 +2392,8 @@ public class WifiManagerTest { int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION; ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor = ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class); - mWifiManager.addSuggestionConnectionStatusListener(mExecutor, mListener); + mWifiManager.addSuggestionConnectionStatusListener(mExecutor, + mSuggestionConnectionListener); verify(mWifiService).registerSuggestionConnectionStatusListener(any(IBinder.class), callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class)); callbackCaptor.getValue().onConnectionStatus(any(WifiNetworkSuggestion.class), errorCode); @@ -2216,7 +2413,7 @@ public class WifiManagerTest { */ @Test public void testRemoveSuggestionConnectionListener() throws Exception { - mWifiManager.removeSuggestionConnectionStatusListener(mListener); + mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener); verify(mWifiService).unregisterSuggestionConnectionStatusListener(anyInt(), anyString()); } @@ -2415,4 +2612,112 @@ public class WifiManagerTest { assertFalse(mWifiManager.isScanAlwaysAvailable()); verify(mWifiService).isScanAlwaysAvailable(); } + + @Test + public void testGetNetworkSuggestionUserApprovalStatus() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + + when(mWifiService.getNetworkSuggestionUserApprovalStatus(TEST_PACKAGE_NAME)) + .thenReturn(WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER); + assertEquals(WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER, + mWifiManager.getNetworkSuggestionUserApprovalStatus()); + verify(mWifiService).getNetworkSuggestionUserApprovalStatus(TEST_PACKAGE_NAME); + } + + @Test + public void testSetCarrierNetworkOffload() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, true, false); + verify(mWifiService).setCarrierNetworkOffloadEnabled(TEST_SUB_ID, + true, false); + } + + @Test + public void testGetCarrierNetworkOffload() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mWifiService.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)).thenReturn(true); + assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)); + verify(mWifiService).isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false); + } + + + /** + * Verify an IllegalArgumentException is thrown if listener is not provided. + */ + @Test(expected = IllegalArgumentException.class) + public void testRemoveSuggestionUserApprovalStatusListenerWithNullListener() { + assumeTrue(SdkLevel.isAtLeastS()); + + mWifiManager.removeSuggestionUserApprovalStatusListener(null); + } + + + /** + * Verify removeSuggestionUserApprovalStatusListener. + */ + @Test + public void testRemoveSuggestionUserApprovalStatusListener() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + + mWifiManager.removeSuggestionUserApprovalStatusListener( + mSuggestionUserApprovalStatusListener); + verify(mWifiService).removeSuggestionUserApprovalStatusListener(anyInt(), anyString()); + } + + /** + * Verify an IllegalArgumentException is thrown if executor not provided. + */ + @Test(expected = IllegalArgumentException.class) + public void testAddSuggestionUserApprovalStatusListenerWithNullExecutor() { + assumeTrue(SdkLevel.isAtLeastS()); + + mWifiManager.addSuggestionUserApprovalStatusListener(null, + mSuggestionUserApprovalStatusListener); + } + + /** + * Verify an IllegalArgumentException is thrown if listener is not provided. + */ + @Test(expected = IllegalArgumentException.class) + public void testAddSuggestionUserApprovalStatusListenerWithNullListener() { + assumeTrue(SdkLevel.isAtLeastS()); + + mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, null); + } + + /** + * Verify client provided listener is being called to the right listener. + */ + @Test + public void testAddSuggestionUserApprovalStatusListenerAndReceiveEvent() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + + ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor = + ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class); + Executor executor = new SynchronousExecutor(); + mWifiManager.addSuggestionUserApprovalStatusListener(executor, + mSuggestionUserApprovalStatusListener); + verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class), + callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class)); + callbackCaptor.getValue().onUserApprovalStatusChange(); + verify(mSuggestionUserApprovalStatusListener).onUserApprovalStatusChange(); + } + + /** + * Verify client provided listener is being called to the right executor. + */ + @Test + public void testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor() + throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor = + ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class); + mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, + mSuggestionUserApprovalStatusListener); + verify(mWifiService).addSuggestionUserApprovalStatusListener(any(IBinder.class), + callbackCaptor.capture(), anyInt(), anyString(), nullable(String.class)); + callbackCaptor.getValue().onUserApprovalStatusChange(); + verify(mExecutor).execute(any(Runnable.class)); + } + } diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java index 870ff0a26d58..5e829188f93f 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java @@ -809,7 +809,7 @@ public class WifiNetworkSuggestionTest { /** * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception * when both {@link WifiNetworkSuggestion.Builder#setWpa3Passphrase(String)} and - * {@link WifiNetworkSuggestion.Builderi + * {@link WifiNetworkSuggestion.Builder * #setWpa3EnterpriseStandardModeConfig(WifiEnterpriseConfig)} * are invoked. */ @@ -1310,6 +1310,7 @@ public class WifiNetworkSuggestionTest { .build(); assertTrue(suggestion.isOemPaid()); assertFalse(suggestion.isUserAllowedToManuallyConnect); + assertTrue(suggestion.getPasspointConfig().isOemPaid()); } /** @@ -1345,6 +1346,7 @@ public class WifiNetworkSuggestionTest { .build(); assertTrue(suggestion.isOemPrivate()); assertFalse(suggestion.isUserAllowedToManuallyConnect); + assertTrue(suggestion.getPasspointConfig().isOemPrivate()); } /** @@ -1414,4 +1416,109 @@ public class WifiNetworkSuggestionTest { .setIsInitialAutojoinEnabled(false) .build(); } + + /** + * Validate {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} set the + * correct value to the WifiConfiguration. + */ + @Test + public void testSetCarrierMergedNetwork() { + assumeTrue(SdkLevel.isAtLeastS()); + + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setSubscriptionId(1) + .setWpa2EnterpriseConfig(enterpriseConfig) + .setCarrierMerged(true) + .setIsMetered(true) + .build(); + assertTrue(suggestion.isCarrierMerged()); + assertTrue(suggestion.wifiConfiguration.carrierMerged); + } + + /** + * Validate {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} set the + * correct value to the passpoint network. + */ + @Test + public void testSetCarrierMergedNetworkOnPasspointNetwork() { + assumeTrue(SdkLevel.isAtLeastS()); + + PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig(); + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setPasspointConfig(passpointConfiguration) + .setSubscriptionId(1) + .setCarrierMerged(true) + .setIsMetered(true) + .build(); + assertTrue(suggestion.isCarrierMerged()); + assertTrue(suggestion.getPasspointConfig().isCarrierMerged()); + } + + /** + * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception + * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} + * to true on a network is not metered. + */ + @Test(expected = IllegalStateException.class) + public void testSetCarrierMergedNetworkOnUnmeteredNetworkFail() { + assumeTrue(SdkLevel.isAtLeastS()); + + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setSubscriptionId(1) + .setWpa2EnterpriseConfig(enterpriseConfig) + .setCarrierMerged(true) + .build(); + } + + /** + * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception + * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} + * to true on a network which {@link WifiNetworkSuggestion.Builder#setSubscriptionId(int)} + * is not set with a valid sub id. + */ + @Test(expected = IllegalStateException.class) + public void testSetCarrierMergedNetworkWithoutValidSubscriptionIdFail() { + assumeTrue(SdkLevel.isAtLeastS()); + + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setWpa2EnterpriseConfig(enterpriseConfig) + .setCarrierMerged(true) + .setIsMetered(true) + .build(); + assertTrue(suggestion.isCarrierMerged()); + } + + /** + * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception + * when set both {@link WifiNetworkSuggestion.Builder#setCarrierMerged(boolean)} (boolean)} + * to true on a non enterprise network. + */ + @Test(expected = IllegalStateException.class) + public void testSetCarrierMergedNetworkWithNonEnterpriseNetworkFail() { + assumeTrue(SdkLevel.isAtLeastS()); + + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setSubscriptionId(1) + .setWpa2Passphrase(TEST_PRESHARED_KEY) + .setCarrierMerged(true) + .setIsMetered(true) + .build(); + assertTrue(suggestion.isCarrierMerged()); + } } diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java index e6eae416ba78..c8006fead55b 100644 --- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java +++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java @@ -16,6 +16,8 @@ package android.net.wifi.rtt; +import static junit.framework.Assert.fail; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -143,6 +145,7 @@ public class WifiRttManagerTest { PeerHandle peerHandle1 = new PeerHandle(12); RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(4); builder.addAccessPoint(scanResult1); builder.addAccessPoints(scanResults2and3); builder.addWifiAwarePeer(mac1); @@ -163,6 +166,60 @@ public class WifiRttManagerTest { } /** + * Validate the rtt burst size is set correctly when in range. + */ + @Test + public void testRangingRequestSetBurstSize() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(4); + builder.addAccessPoint(scanResult); + RangingRequest request = builder.build(); + + // confirm rtt burst size is set correctly to default value + assertEquals(request.getRttBurstSize(), 4); + } + + /** + * Validate the rtt burst size cannot be smaller than the minimum. + */ + @Test + public void testRangingRequestMinBurstSizeIsEnforced() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + try { + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(RangingRequest.getMinRttBurstSize() - 1); + fail("RTT burst size was smaller than min value."); + } catch (IllegalArgumentException e) { + // expected + } + } + + /** + * Validate the rtt burst size cannot exceed the maximum. + */ + @Test + public void testRangingRequestMaxBurstSizeIsEnforced() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + try { + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize() + 1); + fail("RTT Burst size exceeded max value."); + } catch (IllegalArgumentException e) { + // expected + } + } + + /** * Validate that can request as many range operation as the upper limit on number of requests. */ @Test @@ -175,7 +232,7 @@ public class WifiRttManagerTest { } MacAddress mac1 = MacAddress.fromString("00:01:02:03:04:05"); - // create request + // create request using max RTT Peers RangingRequest.Builder builder = new RangingRequest.Builder(); builder.addAccessPoint(scanResult); builder.addAccessPoints(scanResultList); @@ -185,6 +242,18 @@ public class WifiRttManagerTest { // verify request request.enforceValidity(true); + // confirm rtt burst size is set correctly to default value + assertEquals(request.getRttBurstSize(), RangingRequest.getDefaultRttBurstSize()); + // confirm the number of peers in the request is the max number of peers + List<ResponderConfig> rttPeers = request.getRttPeers(); + int numRttPeers = rttPeers.size(); + assertEquals(RangingRequest.getMaxPeers(), numRttPeers); + // confirm each peer has the correct mac address + for (int i = 0; i < numRttPeers - 1; ++i) { + assertEquals("AA:BB:CC:DD:EE:FF", rttPeers.get(i).macAddress.toString().toUpperCase()); + } + assertEquals("00:01:02:03:04:05", + rttPeers.get(numRttPeers - 1).macAddress.toString().toUpperCase()); } /** |