diff options
199 files changed, 13488 insertions, 4473 deletions
diff --git a/aidl/mainline_supplicant/Android.bp b/aidl/mainline_supplicant/Android.bp new file mode 100644 index 0000000000..285af3d6cf --- /dev/null +++ b/aidl/mainline_supplicant/Android.bp @@ -0,0 +1,42 @@ +// Copyright (C) 2024 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. + +aidl_interface { + name: "android.system.wifi.mainline_supplicant", + unstable: true, + srcs: [ + "android/system/wifi/mainline_supplicant/*.aidl", + ], + backend: { + java: { + enabled: true, + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], + min_sdk_version: "30", + }, + ndk: { + enabled: true, + apex_available: [ + "//apex_available:platform", + "com.android.wifi", + ], + min_sdk_version: "30", + }, + cpp: { + enabled: false, + }, + }, +} diff --git a/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl new file mode 100644 index 0000000000..2cef28229a --- /dev/null +++ b/aidl/mainline_supplicant/android/system/wifi/mainline_supplicant/IMainlineSupplicant.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 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.system.wifi.mainline_supplicant; + +/** + * Root of the mainline supplicant interface. This is an unstable AIDL interface used + * to interact with the supplicant binary stored in the mainline module. + */ +interface IMainlineSupplicant { + /** + * Terminate the service. + */ + void terminate(); +} diff --git a/apex/Android.bp b/apex/Android.bp index a878695458..f570b8cebd 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -35,6 +35,9 @@ apex_defaults { "ServiceWifiResources", "WifiDialog", ], + jni_libs: [ + "libservice-wifi-jni", + ], defaults: ["r-launched-apex-module"], // Indicates that pre-installed version of this apex can be compressed. // Whether it actually will be compressed is controlled on per-device basis. diff --git a/flags/Android.bp b/flags/Android.bp index 3170e05903..7d1e613cc3 100644 --- a/flags/Android.bp +++ b/flags/Android.bp @@ -54,3 +54,9 @@ java_defaults { "aconfig_storage_reader_java", ], } + +cc_aconfig_library { + name: "wifi_aconfig_flags_c_lib", + aconfig_declarations: "wifi_aconfig_flags", + vendor_available: true, +} diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig index 2da04a5284..c79b700c84 100644 --- a/flags/wifi_flags.aconfig +++ b/flags/wifi_flags.aconfig @@ -9,6 +9,22 @@ flag { } flag { + name: "p2p_ownership" + namespace: "wifi" + description: "Control the P2P group ownership feature" + bug: "215045910" + is_fixed_read_only: true +} + +flag { + name: "p2p_dual" + namespace: "wifi" + description: "Control the dual P2P group feature" + bug: "296063280" + is_fixed_read_only: true +} + +flag { name: "delay_save_to_store" namespace: "wifi" description: "Control the feature delay the save to store in batch to reduce the blocking time" @@ -71,11 +87,14 @@ flag { } flag { - name: "voip_detection" + name: "voip_detection_bugfix" namespace: "wifi" description: "Detect VoIP over Wifi and execute optimization" bug: "295885471" is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } } flag { @@ -85,4 +104,113 @@ flag { description: "Add new API to get BSSID blocklist" bug: "336109216" is_fixed_read_only: true -}
\ No newline at end of file +} + +flag { + name: "delayed_carrier_network_selection" + namespace: "wifi" + description: "Delay network selection for some carrier networks until a delay period has passed" + bug: "329142362" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "local_only_connection_optimization" + namespace: "wifi" + description: "optimize local-only connection API" + bug: "347117408" + is_fixed_read_only: true +} + +flag { + name: "softap_config_store_max_channel_width" + namespace: "wifi" + description: "Store MaxChannelBandwidth to SoftAP config" + bug: "344450923" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "autojoin_restriction_security_types_api" + is_exported: true + namespace: "wifi" + description: "Add new API to set or get Autojoin Restriction security types" + bug: "340351634" + is_fixed_read_only: true +} + +flag { + name: "rsn_overriding" + namespace: "wifi" + description: "Wi-Fi Alliance RSN Overriding feature" + bug: "348669010" + is_fixed_read_only: true +} + +flag { + name: "new_uri_parsing_for_escape_character" + namespace: "wifi" + description: "New parsing logic for Zxing uri format which support escape character" + bug: "342706482" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "aware_pairing" + is_exported: true + namespace: "wifi" + description: "Add new API for Aware pairing" + bug: "354820259" + is_fixed_read_only: true +} + +flag { + name: "wifi_scorer_new_stats_collection" + namespace: "wifi" + description: "Gate WiFi Scorer new stats collection" + bug: "367362809" +} + +flag { + name: "softap_disconnect_reason" + is_exported: true + namespace: "wifi" + description: "Add SoftAP disconnect reason code" + bug: "361651437" + is_fixed_read_only: true +} + +flag { + name: "mainline_supplicant" + namespace: "wifi" + description: "Use the secondary supplicant binary stored in the mainline module" + bug: "365585450" + is_fixed_read_only: true +} + +flag { + name: "mlo_sap" + is_exported: true + namespace: "wifi" + description: "Mlo SoftAp" + bug: "362355566" + is_fixed_read_only: true +} + +flag { + name: "wifi_direct_r2" + is_exported: true + namespace: "wifi" + description: "Wi-Fi Alliance Wi-Fi Direct R2 feature" + bug: "341971059" + is_fixed_read_only: true +} diff --git a/framework/api/current.txt b/framework/api/current.txt index a277bca42c..45ec47ea32 100644 --- a/framework/api/current.txt +++ b/framework/api/current.txt @@ -584,6 +584,7 @@ package android.net.wifi { field public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4; // 0x4 field public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5; // 0x5 field public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_UNKNOWN = 0; // 0x0 + field @FlaggedApi("com.android.wifi.flags.local_only_connection_optimization") public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT = 6; // 0x6 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; // 0x3 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; // 0x4 field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; // 0x7 @@ -846,6 +847,7 @@ package android.net.wifi.aware { public final class AwarePairingConfig implements android.os.Parcelable { method public int describeContents(); method public int getBootstrappingMethods(); + method @FlaggedApi("com.android.wifi.flags.aware_pairing") public int getSupportedCipherSuites(); method public boolean isPairingCacheEnabled(); method public boolean isPairingSetupEnabled(); method public boolean isPairingVerificationEnabled(); @@ -869,6 +871,7 @@ package android.net.wifi.aware { method @NonNull public android.net.wifi.aware.AwarePairingConfig.Builder setPairingCacheEnabled(boolean); method @NonNull public android.net.wifi.aware.AwarePairingConfig.Builder setPairingSetupEnabled(boolean); method @NonNull public android.net.wifi.aware.AwarePairingConfig.Builder setPairingVerificationEnabled(boolean); + method @FlaggedApi("com.android.wifi.flags.aware_pairing") @NonNull public android.net.wifi.aware.AwarePairingConfig.Builder setSupportedCipherSuites(int); } public final class AwareResources implements android.os.Parcelable { diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index d06e48ac5e..4bbf111b32 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -13,6 +13,71 @@ package android.net.wifi { field public static final int POWER_CAP_NONE = 2147483647; // 0x7fffffff } + @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public final class DeauthenticationReasonCode { + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_AKMP_NOT_VALID = 20; // 0x14 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_AUTHORIZED_ACCESS_LIMIT_REACHED = 46; // 0x2e + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_BAD_CIPHER_OR_AKM = 29; // 0x1d + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_BSS_TRANSITION_DISASSOC = 12; // 0xc + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CIPHER_SUITE_REJECTED = 24; // 0x18 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6; // 0x6 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7; // 0x7 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DEAUTH_LEAVING = 3; // 0x3 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_AP_BUSY = 5; // 0x5 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_DUE_TO_INACTIVITY = 4; // 0x4 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_LOW_ACK = 34; // 0x22 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_DISASSOC_STA_HAS_LEFT = 8; // 0x8 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_END_TS_BA_DLS = 37; // 0x25 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_EXCEEDED_TXOP = 35; // 0x23 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_EXTERNAL_SERVICE_REQUIREMENTS = 47; // 0x2f + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15; // 0xf + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_GROUP_CIPHER_NOT_VALID = 18; // 0x12 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_GROUP_KEY_UPDATE_TIMEOUT = 16; // 0x10 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_IEEE_802_1X_AUTH_FAILED = 23; // 0x17 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_IE_IN_4WAY_DIFFERS = 17; // 0x11 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_FTE = 51; // 0x33 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_FT_ACTION_FRAME_COUNT = 48; // 0x30 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_IE = 13; // 0xd + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_MDE = 50; // 0x32 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_PMKID = 49; // 0x31 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_INVALID_RSN_IE_CAPAB = 22; // 0x16 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64; // 0x40 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65; // 0x41 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66; // 0x42 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CLOSE_RCVD = 55; // 0x37 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CONFIG_POLICY_VIOLATION = 54; // 0x36 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_CONFIRM_TIMEOUT = 57; // 0x39 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INCONSISTENT_PARAMS = 59; // 0x3b + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INVALID_GTK = 58; // 0x3a + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_INVALID_SECURITY_CAP = 60; // 0x3c + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_MAX_PEERS = 53; // 0x35 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_MAX_RETRIES = 56; // 0x38 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_DEST_UNREACHABLE = 63; // 0x3f + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO = 62; // 0x3e + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PATH_ERROR_NO_PROXY_INFO = 61; // 0x3d + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MESH_PEERING_CANCELLED = 52; // 0x34 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_MICHAEL_MIC_FAILURE = 14; // 0xe + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NOT_AUTHORIZED_THIS_LOCATION = 30; // 0x1e + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NOT_ENOUGH_BANDWIDTH = 33; // 0x21 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_NO_SSP_ROAMING_AGREEMENT = 28; // 0x1c + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PAIRWISE_CIPHER_NOT_VALID = 19; // 0x13 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PEERKEY_MISMATCH = 45; // 0x2d + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PREV_AUTH_NOT_VALID = 2; // 0x2 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_PWR_CAPABILITY_NOT_VALID = 10; // 0xa + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SERVICE_CHANGE_PRECLUDES_TS = 31; // 0x1f + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SSP_REQUESTED_DISASSOC = 27; // 0x1b + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_STA_LEAVING = 36; // 0x24 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9; // 0x9 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_SUPPORTED_CHANNEL_NOT_VALID = 11; // 0xb + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TDLS_TEARDOWN_UNREACHABLE = 25; // 0x19 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TDLS_TEARDOWN_UNSPECIFIED = 26; // 0x1a + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_TIMEOUT = 39; // 0x27 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNKNOWN = 0; // 0x0 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNKNOWN_TS_BA = 38; // 0x26 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSPECIFIED = 1; // 0x1 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSPECIFIED_QOS_REASON = 32; // 0x20 + field @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public static final int REASON_UNSUPPORTED_RSN_IE_VERSION = 21; // 0x15 + } + public abstract class EasyConnectStatusCallback { ctor public EasyConnectStatusCallback(); method public void onBootstrapUriGenerated(@NonNull android.net.Uri); @@ -529,6 +594,7 @@ package android.net.wifi { public final class WifiClient implements android.os.Parcelable { method public int describeContents(); + method @FlaggedApi("com.android.wifi.flags.softap_disconnect_reason") public int getDisconnectReason(); method @NonNull public android.net.MacAddress getMacAddress(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiClient> CREATOR; @@ -719,6 +785,7 @@ 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 @FlaggedApi("com.android.wifi.flags.autojoin_restriction_security_types_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void getAutojoinDisallowedSecurityTypes(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<int[]>); method @FlaggedApi("com.android.wifi.flags.get_bssid_blocklist_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void getBssidBlocklist(@NonNull java.util.List<android.net.wifi.WifiSsid>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.net.MacAddress>>); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getCountryCode(); method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork(); @@ -784,6 +851,7 @@ package android.net.wifi { method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void retrieveWifiBackupData(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>); 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 @FlaggedApi("com.android.wifi.flags.autojoin_restriction_security_types_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION}) public void setAutojoinDisallowedSecurityTypes(@NonNull int[]); 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.List<android.net.wifi.CoexUnsafeChannel>, int); method @FlaggedApi("com.android.wifi.flags.android_v_wifi_api") @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void setD2dAllowedWhenInfraStaDisabled(boolean); diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt index f1b4000737..598c014b71 100644 --- a/framework/jarjar-rules.txt +++ b/framework/jarjar-rules.txt @@ -86,7 +86,15 @@ 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 com.android.wifi.flags.** com.android.wifi.x.@0 +# Repackage generated flag classes. +# Need to specify the rule on classes to avoid transform the literals +rule com.android.wifi.flags.*FeatureFlags* com.android.wifi.x.@0 +rule com.android.wifi.flags.FeatureFlags* com.android.wifi.x.@0 +rule com.android.wifi.flags.Flags com.android.wifi.x.@0 + +rule android.net.wifi.flags.*FeatureFlags* com.android.wifi.x.@0 +rule android.net.wifi.flags.FeatureFlags* com.android.wifi.x.@0 +rule android.net.wifi.flags.Flags com.android.wifi.x.@0 # Use our statically linked bouncy castle library rule org.bouncycastle.** com.android.wifi.x.@0 diff --git a/framework/java/android/net/wifi/BaseWifiService.java b/framework/java/android/net/wifi/BaseWifiService.java deleted file mode 100644 index 5f58810584..0000000000 --- a/framework/java/android/net/wifi/BaseWifiService.java +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * Copyright (c) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.net.DhcpInfo; -import android.net.DhcpOption; -import android.net.Network; -import android.net.TetheringManager; -import android.net.wifi.hotspot2.IProvisioningCallback; -import android.net.wifi.hotspot2.OsuProvider; -import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.twt.TwtRequest; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.WorkSource; - -import com.android.modules.utils.ParceledListSlice; - -import java.util.List; -import java.util.Map; - -/** - * Empty concrete class implementing IWifiManager with stub methods throwing runtime exceptions. - * - * This class is meant to be extended by real implementations of IWifiManager in order to facilitate - * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of - * deprecated APIs, or the migration of existing API signatures. - * - * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl - * immediately and marked as @Deprecated first in this class. Children inheriting this class are - * then given a short grace period to update themselves before the @Deprecated stub is removed for - * good. If the API scheduled for removal has a replacement or an overload (signature change), - * these should be introduced before the stub is removed to allow children to migrate. - * - * When a new API is added to IWifiManager.aidl, a stub should be added in BaseWifiService as - * well otherwise compilation will fail. - * - * @hide - */ -public class BaseWifiService extends IWifiManager.Stub { - - private static final String TAG = BaseWifiService.class.getSimpleName(); - - @Override - public long getSupportedFeatures() { - throw new UnsupportedOperationException(); - } - - @Override - public void getWifiActivityEnergyInfoAsync(IOnWifiActivityEnergyInfoListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public ParceledListSlice getConfiguredNetworks(String packageName, String featureId, - boolean callerNetworksOnly) { - throw new UnsupportedOperationException(); - } - - @Override - public ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId, - Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public WifiConfiguration getPrivilegedConnectedNetwork( - String packageName, String featureId, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void setNetworkSelectionConfig(WifiNetworkSelectionConfig nsConfig) { - throw new UnsupportedOperationException(); - } - - @Override - public void getNetworkSelectionConfig(@NonNull IWifiNetworkSelectionConfigListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setThirdPartyAppEnablingWifiConfirmationDialogEnabled(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isThirdPartyAppEnablingWifiConfirmationDialogEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void setScreenOnScanSchedule(int[] scanScheduleSeconds, int[] scanType) { - throw new UnsupportedOperationException(); - } - - @Override - public void setOneShotScreenOnConnectivityScanDelayMillis(int delayMs) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<String, Map<Integer, List<ScanResult>>> getAllMatchingFqdnsForScanResults( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public void setSsidsAllowlist(String packageName, List<WifiSsid> ssids) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiSsid> getSsidsAllowlist(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { - throw new UnsupportedOperationException(); - } - - @Override - public int addOrUpdateNetwork(WifiConfiguration config, String packageName, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged(WifiConfiguration config, - String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean addOrUpdatePasspointConfiguration( - PasspointConfiguration config, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removePasspointConfiguration(String fqdn, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { - throw new UnsupportedOperationException(); - } - - @Override - public void queryPasspointIcon(long bssid, String fileName) { - throw new UnsupportedOperationException(); - } - - @Override - public int matchProviderWithCurrentNetwork(String fqdn) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeNetwork(int netId, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean removeNonCallerConfiguredNetworks(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean disableNetwork(int netId, String packageName) { - throw new UnsupportedOperationException(); - } - - /** TO BE REMOVED */ - public void allowAutojoinGlobal(boolean choice) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoinGlobal(boolean choice, String packageName, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void queryAutojoinGlobal(@NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoin(int netId, boolean choice) { - throw new UnsupportedOperationException(); - } - - @Override - public void allowAutojoinPasspoint(String fqdn, boolean enableAutoJoin) { - throw new UnsupportedOperationException(); - } - - @Override - public void getBssidBlocklist(ParceledListSlice<WifiSsid> ssids, - IMacAddressListListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setMacRandomizationSettingPasspointEnabled(String fqdn, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPasspointMeteredOverride(String fqdn, int meteredOverride) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean startScan(String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public ParceledListSlice getScanResults(String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void getChannelData(@NonNull IListListener listener, String packageName, - Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean disconnect(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean reconnect(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean reassociate(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public WifiInfo getConnectionInfo(String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiEnabled(String packageName, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerSubsystemRestartCallback(ISubsystemRestartCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterSubsystemRestartCallback(ISubsystemRestartCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void addWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeWifiNetworkStateChangedListener(IWifiNetworkStateChangedListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void restartWifiSubsystem() { - throw new UnsupportedOperationException(); - } - - @Override - public int getWifiEnabledState() { - throw new UnsupportedOperationException(); - } - - @Override - public void registerDriverCountryCodeChangedListener( - @NonNull IOnWifiDriverCountryCodeChangedListener listener, - @Nullable String packageName, @Nullable String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterDriverCountryCodeChangedListener( - @NonNull IOnWifiDriverCountryCodeChangedListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public String getCountryCode(String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void setOverrideCountryCode(@NonNull String countryCode) { - throw new UnsupportedOperationException(); - } - - @Override - public void clearOverrideCountryCode() { - throw new UnsupportedOperationException(); - } - - @Override - public void setDefaultCountryCode(@NonNull String countryCode) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is24GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is5GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is6GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean is60GHzBandSupported() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWifiStandardSupported(int standard) { - throw new UnsupportedOperationException(); - } - - @Override - public DhcpInfo getDhcpInfo(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void setScanAlwaysAvailable(boolean isAvailable, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isScanAlwaysAvailable() { - throw new UnsupportedOperationException(); - } - - /** - * Following method is deprecated with - * {@link BaseWifiService#acquireWifiLock(IBinder, int, String, WorkSource, String, Bundle)} - * @deprecated This is no longer supported. - */ - @Deprecated - public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws, - String packageName, Bundle extras) { - throw new UnsupportedOperationException(); - } - - /** - * Following method is deprecated with - * {@link BaseWifiService#updateWifiLockWorkSource(IBinder, WorkSource, String, Bundle)} - * @deprecated This is no longer supported. - */ - @Deprecated - public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateWifiLockWorkSource(IBinder lock, WorkSource ws, String packageName, - Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean releaseWifiLock(IBinder lock) { - throw new UnsupportedOperationException(); - } - - @Override - public void initializeMulticastFiltering() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isMulticastEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void acquireMulticastLock(IBinder binder, String tag) { - throw new UnsupportedOperationException(); - } - - @Override - public void releaseMulticastLock(String tag) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateInterfaceIpState(String ifaceName, int mode) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isDefaultCoexAlgorithmEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void setCoexUnsafeChannels(List<CoexUnsafeChannel> unsafeChannels, int restrictions) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerCoexCallback(ICoexCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterCoexCallback(ICoexCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean startSoftAp(WifiConfiguration wifiConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - /** - * Following method is deprecated with - * {@link #startTetheredHotspotRequest(TetheringManager.TetheringRequest, String)} - * @deprecated This is no longer supported. - */ - @Deprecated - @Override - public boolean startTetheredHotspot(SoftApConfiguration softApConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void startTetheredHotspotRequest(TetheringManager.TetheringRequest request, - ISoftApCallback callback, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean stopSoftAp() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean validateSoftApConfiguration(SoftApConfiguration config) { - throw new UnsupportedOperationException(); - } - - @Override - public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName, - String featureId, SoftApConfiguration customConfig, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopLocalOnlyHotspot() { - throw new UnsupportedOperationException(); - } - - @Override - public void registerLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterLocalOnlyHotspotSoftApCallback(ISoftApCallback callback, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void startWatchLocalOnlyHotspot(ILocalOnlyHotspotCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopWatchLocalOnlyHotspot() { - throw new UnsupportedOperationException(); - } - - @Override - public int getWifiApEnabledState() { - throw new UnsupportedOperationException(); - } - - @Override - public WifiConfiguration getWifiApConfiguration() { - throw new UnsupportedOperationException(); - } - - @Override - public SoftApConfiguration getSoftApConfiguration() { - throw new UnsupportedOperationException(); - } - - @Override - public void queryLastConfiguredTetheredApPassphraseSinceBoot(IStringListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setSoftApConfiguration(SoftApConfiguration softApConfig, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void notifyUserOfApBandConversion(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdls(String remoteIPAddress, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdlsWithRemoteIpAddress(String remoteIPAddress, boolean enable, - @NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableTdlsWithRemoteMacAddress(String remoteMacAddress, boolean enable, - @NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void isTdlsOperationCurrentlyAvailable(@NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void getMaxSupportedConcurrentTdlsSessions(@NonNull IIntegerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void getNumberOfEnabledTdlsSessions(@NonNull IIntegerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public String getCurrentNetworkWpsNfcConfigurationToken() { - throw new UnsupportedOperationException(); - } - - @Override - public void enableVerboseLogging(int verbose) { - throw new UnsupportedOperationException(); - } - - @Override - public int getVerboseLoggingLevel() { - throw new UnsupportedOperationException(); - } - - @Override - public void disableEphemeralNetwork(String SSID, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void factoryReset(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public Network getCurrentNetwork() { - throw new UnsupportedOperationException(); - } - - @Override - public void retrieveWifiBackupData(@NonNull IByteArrayListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void restoreWifiBackupData(byte[] data) { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] retrieveBackupData() { - throw new UnsupportedOperationException(); - } - - @Override - public void restoreBackupData(byte[] data) { - throw new UnsupportedOperationException(); - } - - @Override - public byte[] retrieveSoftApBackupData() { - throw new UnsupportedOperationException(); - } - - @Override - public SoftApConfiguration restoreSoftApBackupData(byte[] data) { - throw new UnsupportedOperationException(); - } - - @Override - public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { - throw new UnsupportedOperationException(); - } - - @Override - public void startSubscriptionProvisioning( - OsuProvider provider, IProvisioningCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void addWifiVerboseLoggingStatusChangedListener( - IWifiVerboseLoggingStatusChangedListener callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeWifiVerboseLoggingStatusChangedListener( - IWifiVerboseLoggingStatusChangedListener callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerSoftApCallback(ISoftApCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterSoftApCallback(ISoftApCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerTrafficStateCallback(ITrafficStateCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterTrafficStateCallback(ITrafficStateCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterNetworkRequestMatchCallback(INetworkRequestMatchCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public int addNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, - String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public int removeNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, int action) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiNetworkSuggestion> getNetworkSuggestions(String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void setCarrierNetworkOffloadEnabled(int subId, boolean merged, boolean enabled) - throws RemoteException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isCarrierNetworkOffloadEnabled(int subId, boolean merged) - throws RemoteException { - throw new UnsupportedOperationException(); - } - - @Override - public String[] getFactoryMacAddresses() { - throw new UnsupportedOperationException(); - } - - @Override - public void setDeviceMobilityState(int state) { - throw new UnsupportedOperationException(); - } - - @Override - public void startDppAsConfiguratorInitiator(IBinder binder, String packageName, - String enrolleeUri, int selectedNetworkId, int netRole, IDppCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void startDppAsEnrolleeInitiator(IBinder binder, String configuratorUri, - IDppCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void startDppAsEnrolleeResponder(IBinder binder, String deviceInfo, - int curve, IDppCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopDppSession() throws RemoteException { - throw new UnsupportedOperationException(); - } - - @Override - public void addOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeOnWifiUsabilityStatsListener(IOnWifiUsabilityStatsListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) { - throw new UnsupportedOperationException(); - } - - /** TO BE REMOVED */ - public void connect(WifiConfiguration config, int netId, IActionListener callback) { - throw new UnsupportedOperationException(); - } - - /** TO BE REMOVED */ - public void connect(WifiConfiguration config, int netId, IActionListener callback, - @NonNull String packageName) { - throw new UnsupportedOperationException(); - } - @Override - public void connect(WifiConfiguration config, int netId, IActionListener callback, - @NonNull String packageName, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void startRestrictingAutoJoinToSubscriptionId(int subId) { - throw new UnsupportedOperationException(); - } - - @Override - public void stopRestrictingAutoJoinToSubscriptionId() { - throw new UnsupportedOperationException(); - } - - /** TO BE REMOVED */ - public void save(WifiConfiguration config, IActionListener callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void save(WifiConfiguration config, IActionListener callback, - @NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void forget(int netId, IActionListener callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerScanResultsCallback(IScanResultsCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterScanResultsCallback(IScanResultsCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public void registerSuggestionConnectionStatusListener( - ISuggestionConnectionStatusListener listener, String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void unregisterSuggestionConnectionStatusListener( - ISuggestionConnectionStatusListener listener, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public int calculateSignalLevel(int rssi) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle, - String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public void setExternalPnoScanRequest(@NonNull IBinder binder, - @NonNull IPnoScanResultsCallback callback, - @NonNull List<WifiSsid> ssids, @NonNull int[] frequencies, - @NonNull String packageName, @NonNull String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void clearExternalPnoScanRequest() { - throw new UnsupportedOperationException(); - } - - @Override - public void getLastCallerInfoForApi(int apiType, @NonNull ILastCallerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiConnectedNetworkScorer(IBinder binder, - IWifiConnectedNetworkScorer scorer) { - throw new UnsupportedOperationException(); - } - - @Override - public void clearWifiConnectedNetworkScorer() { - throw new UnsupportedOperationException(); - } - - @Override - public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - List<WifiNetworkSuggestion> networkSuggestions, - List<ScanResult> scanResults, - String callingPackage, String callingFeatureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void setScanThrottleEnabled(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isScanThrottleEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { - throw new UnsupportedOperationException(); - } - - @Override - public void setAutoWakeupEnabled(boolean enable) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isAutoWakeupEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void addSuggestionUserApprovalStatusListener( - ISuggestionUserApprovalStatusListener listener, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeSuggestionUserApprovalStatusListener( - ISuggestionUserApprovalStatusListener listener, String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void setEmergencyScanRequestInProgress(boolean inProgress) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeAppState(int targetAppUid, @NonNull String targetAppPackageName) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setWifiScoringEnabled(boolean enabled) { - throw new UnsupportedOperationException(); - } - - @Override - public void flushPasspointAnqpCache(@NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - /** TO BE REMOVED */ - public List<WifiAvailableChannel> getUsableChannels( - int band, int mode, int filter) { - throw new UnsupportedOperationException(); - } - - @Override - public List<WifiAvailableChannel> getUsableChannels( - int band, int mode, int filter, String packageName, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isWifiPasspointEnabled() { - throw new UnsupportedOperationException(); - } - - @Override - public void setWifiPasspointEnabled(boolean enabled) { - throw new UnsupportedOperationException(); - } - - @Override - public @WifiManager.WifiMultiInternetMode int getStaConcurrencyForMultiInternetMode() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean setStaConcurrencyForMultiInternetMode( - @WifiManager.WifiMultiInternetMode int mode) { - throw new UnsupportedOperationException(); - } - - @Override - public void notifyMinimumRequiredWifiSecurityLevelChanged(int level) { - throw new UnsupportedOperationException(); - } - - @Override - public void notifyWifiSsidPolicyChanged(int policyType, @NonNull List<WifiSsid> ssids) { - throw new UnsupportedOperationException(); - } - - @Override - public String[] getOemPrivilegedWifiAdminPackages() { - throw new UnsupportedOperationException(); - } - - @Override - public void replyToP2pInvitationReceivedDialog( - int dialogId, boolean accepted, @Nullable String optionalPin) { - throw new UnsupportedOperationException(); - } - - @Override - public void replyToSimpleDialog(int dialogId, int button) { - throw new UnsupportedOperationException(); - } - - @Override - public void addCustomDhcpOptions(WifiSsid ssid, byte[] oui, @NonNull List<DhcpOption> options) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeCustomDhcpOptions(WifiSsid ssid, byte[] oui) { - throw new UnsupportedOperationException(); - } - - @Override - public void reportCreateInterfaceImpact(String packageName, int interfaceType, - boolean requireNewInterface, IInterfaceCreationInfoCallback callback) { - throw new UnsupportedOperationException(); - } - - @Override - public int getMaxNumberOfChannelsPerRequest() { - throw new UnsupportedOperationException(); - } - - @Override - public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, - @NonNull IBinder binder, @NonNull String packageName, @NonNull IListListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeQosPolicies(@NonNull int[] policyIdList, @NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeAllQosPolicies(@NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void addLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener, - String packageName, String featureId) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeLocalOnlyConnectionStatusListener(ILocalOnlyConnectionStatusListener listener, - String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void setLinkLayerStatsPollingInterval(int intervalMs) { - throw new UnsupportedOperationException(); - } - - @Override - public void getLinkLayerStatsPollingInterval(@NonNull IIntegerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setMloMode(@WifiManager.MloMode int mode, IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void getMloMode(IIntegerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void addWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void removeWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void getMaxMloAssociationLinkCount(IIntegerListener listener, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void getMaxMloStrLinkCount(IIntegerListener listener, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void getSupportedSimultaneousBandCombinations(IWifiBandsListener listener, - Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void setWepAllowed(boolean isAllowed) { - throw new UnsupportedOperationException(); - } - - @Override - public void queryWepAllowed(@NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void enableMscs(@NonNull MscsParams mscsParams) { - throw new UnsupportedOperationException(); - } - - @Override - public void disableMscs() { - throw new UnsupportedOperationException(); - } - - @Override - public void setSendDhcpHostnameRestriction(@NonNull String packageName, - @WifiManager.SendDhcpHostnameRestriction int restriction) { - throw new UnsupportedOperationException(); - } - - @Override - public void querySendDhcpHostnameRestriction(@NonNull String packageName, - @NonNull IIntegerListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setPerSsidRoamingMode(WifiSsid ssid, @WifiManager.RoamingMode int roamingMode, - @NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void removePerSsidRoamingMode(WifiSsid ssid, @NonNull String packageName) { - throw new UnsupportedOperationException(); - } - - @Override - public void getPerSsidRoamingModes(@NonNull String packageName, IMapListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public void setupTwtSession(TwtRequest twtRequest, ITwtCallback iTwtCallback, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void getTwtCapabilities(ITwtCapabilitiesListener listener, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void getStatsTwtSession(int sessionId, ITwtStatsListener iTwtStatsListener, - Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void teardownTwtSession(int sessionId, Bundle extras) { - throw new UnsupportedOperationException(); - } - - @Override - public void setD2dAllowedWhenInfraStaDisabled(boolean isAllowed) { - throw new UnsupportedOperationException(); - } - - @Override - public void queryD2dAllowedWhenInfraStaDisabled(@NonNull IBooleanListener listener) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean isPnoSupported() { - throw new UnsupportedOperationException(); - } -} diff --git a/framework/java/android/net/wifi/DeauthenticationReasonCode.java b/framework/java/android/net/wifi/DeauthenticationReasonCode.java new file mode 100644 index 0000000000..229ab45709 --- /dev/null +++ b/framework/java/android/net/wifi/DeauthenticationReasonCode.java @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2024 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.FlaggedApi; +import android.annotation.SystemApi; + +import com.android.wifi.flags.Flags; + +/** + * Defines integer constants for Soft AP deauthentication reason codes. + * + * <p>These reason codes provide information about why a client was disconnected from a Soft AP. + * Refer to Section 9.4.1.7 and Table 9-45 of the IEEE 802.11-2016 standard for more information. + * @hide + */ +@SystemApi +@FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) +public final class DeauthenticationReasonCode { + /** Disconnected for an unknown reason. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_UNKNOWN = 0; + + /** Disconnected for an unspecified reason. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_UNSPECIFIED = 1; + + /** Disconnected because the previous authentication is no longer valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_PREV_AUTH_NOT_VALID = 2; + + /** Disconnected because the client is being de-authenticated. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_DEAUTH_LEAVING = 3; + + /** Disconnected due to inactivity. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_DISASSOC_DUE_TO_INACTIVITY = 4; + + /** Disconnected because the AP is unable to handle all currently associated stations. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_DISASSOC_AP_BUSY = 5; + + /** Disconnected because of a Class 2 frame received from a non-authenticated station. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6; + + /** Disconnected because of a Class 3 frame received from a non-associated station. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7; + + /** Disconnected because the STA has left the network. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_DISASSOC_STA_HAS_LEFT = 8; + + /** Disconnected because the STA requested association without authentication. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9; + + /** Disconnected because the power capability element is not valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_PWR_CAPABILITY_NOT_VALID = 10; + + /** Disconnected because the supported channel element is not valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_SUPPORTED_CHANNEL_NOT_VALID = 11; + + /** Disconnected due to a BSS transition disassociation. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_BSS_TRANSITION_DISASSOC = 12; + + /** Disconnected because of an invalid information element. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_IE = 13; + + /** Disconnected because of a message integrity code failure. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MICHAEL_MIC_FAILURE = 14; + + /** Disconnected due to a four-way handshake timeout. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15; + + /** Disconnected due to a group key handshake timeout. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_GROUP_KEY_UPDATE_TIMEOUT = 16; + + /** Disconnected because an information element in the 4-way handshake differs. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_IE_IN_4WAY_DIFFERS = 17; + + /** Disconnected because the group cipher is not valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_GROUP_CIPHER_NOT_VALID = 18; + + /** Disconnected because the pairwise cipher is not valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_PAIRWISE_CIPHER_NOT_VALID = 19; + + /** Disconnected because the authentication and key management protocol is not valid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_AKMP_NOT_VALID = 20; + + /** Disconnected because the robust security network IE version is not supported. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_UNSUPPORTED_RSN_IE_VERSION = 21; + + /** Disconnected because the robust security network IE capabilities are invalid. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_RSN_IE_CAPAB = 22; + + /** Disconnected because the IEEE 802.1X authentication failed. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_IEEE_802_1X_AUTH_FAILED = 23; + + /** Disconnected because the cipher suite was rejected. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_CIPHER_SUITE_REJECTED = 24; + + /** Disconnected because the Tunneled Direct Link Setup teardown is unreachable. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_TDLS_TEARDOWN_UNREACHABLE = 25; + + /** Disconnected because of a Tunneled Direct Link Setup teardown for an unspecified reason. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_TDLS_TEARDOWN_UNSPECIFIED = 26; + + /** Disconnected because an session security protocol requested disassociation. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_SSP_REQUESTED_DISASSOC = 27; + + /** Disconnected because there is no session security protocol roaming agreement. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_NO_SSP_ROAMING_AGREEMENT = 28; + + /** Disconnected because of an unsupported cipher or authentication key management method. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_BAD_CIPHER_OR_AKM = 29; + + /** Disconnected because the client is not authorized at this location. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_NOT_AUTHORIZED_THIS_LOCATION = 30; + + /** Disconnected because a service change precludes traffic specification. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_SERVICE_CHANGE_PRECLUDES_TS = 31; + + /** Disconnected for an unspecified quality of service related reason. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_UNSPECIFIED_QOS_REASON = 32; + + /** Disconnected because there is not enough bandwidth. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_NOT_ENOUGH_BANDWIDTH = 33; + + /** Disconnected due to low acknowledgment rate. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_DISASSOC_LOW_ACK = 34; + + /** Disconnected for exceeding the transmission opportunity. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_EXCEEDED_TXOP = 35; + + /** Disconnected because the station is leaving the network. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_STA_LEAVING = 36; + + /** Disconnected because of the end of a traffic specification, block ack, or DLS session. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_END_TS_BA_DLS = 37; + + /** Disconnected because of an unknown traffic specification or block ack. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_UNKNOWN_TS_BA = 38; + + /** Disconnected due to a timeout. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_TIMEOUT = 39; + + /** Disconnected because of a peerkey mismatch. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_PEERKEY_MISMATCH = 45; + + /** Disconnected because the authorized access limit has been reached. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_AUTHORIZED_ACCESS_LIMIT_REACHED = 46; + + /** Disconnected due to external service requirements. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_EXTERNAL_SERVICE_REQUIREMENTS = 47; + + /** Disconnected because of an invalid fast transition action frame count. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_FT_ACTION_FRAME_COUNT = 48; + + /** Disconnected because of an invalid pairwise master key identifier. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_PMKID = 49; + + /** Disconnected because of an invalid management downlink endpoint. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_MDE = 50; + + /** Disconnected because of an invalid fast transition endpoint. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_INVALID_FTE = 51; + + /** Disconnected because mesh peering was cancelled. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_PEERING_CANCELLED = 52; + + /** Disconnected because the maximum number of mesh peers has been reached. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_MAX_PEERS = 53; + + /** Disconnected because of a mesh configuration policy violation. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_CONFIG_POLICY_VIOLATION = 54; + + /** Disconnected because a mesh close message was received. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_CLOSE_RCVD = 55; + + /** Disconnected because the maximum number of mesh retries has been reached. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_MAX_RETRIES = 56; + + /** Disconnected due to a mesh confirmation timeout. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_CONFIRM_TIMEOUT = 57; + + /** Disconnected because of an invalid mesh group temporal key. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_INVALID_GTK = 58; + + /** Disconnected because of inconsistent mesh parameters. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_INCONSISTENT_PARAMS = 59; + + /** Disconnected because of an invalid mesh security capability. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_INVALID_SECURITY_CAP = 60; + + /** Disconnected because of a mesh path error: no proxy information. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_PATH_ERROR_NO_PROXY_INFO = 61; + + /** Disconnected because of a mesh path error: no forwarding information. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO = 62; + + /** Disconnected because of a mesh path error: destination unreachable. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_PATH_ERROR_DEST_UNREACHABLE = 63; + + /** Disconnected because the MAC address already exists in the mesh basic service set. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64; + + /** Disconnected due to a mesh channel switch due to regulatory requirements. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ = 65; + + /** Disconnected due to a mesh channel switch for an unspecified reason. */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + public static final int REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66; + + private DeauthenticationReasonCode() {} // Private constructor to prevent instantiation +} diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl index 0a6e210249..55dd392f78 100644 --- a/framework/java/android/net/wifi/IWifiManager.aidl +++ b/framework/java/android/net/wifi/IWifiManager.aidl @@ -16,10 +16,6 @@ package android.net.wifi; -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.DhcpOption; import android.net.Network; @@ -34,14 +30,13 @@ import android.net.wifi.IIntegerListener; import android.net.wifi.IInterfaceCreationInfoCallback; import android.net.wifi.ILastCallerListener; import android.net.wifi.IListListener; -import android.net.wifi.ILocalOnlyHotspotCallback; import android.net.wifi.ILocalOnlyConnectionStatusListener; +import android.net.wifi.ILocalOnlyHotspotCallback; +import android.net.wifi.IMacAddressListListener; import android.net.wifi.IMapListener; import android.net.wifi.INetworkRequestMatchCallback; import android.net.wifi.IOnWifiActivityEnergyInfoListener; import android.net.wifi.IOnWifiDriverCountryCodeChangedListener; -import android.net.wifi.IWifiNetworkStateChangedListener; -import android.net.wifi.IMacAddressListListener; import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.IPnoScanResultsCallback; import android.net.wifi.IScanResultsCallback; @@ -58,6 +53,7 @@ import android.net.wifi.IWifiBandsListener; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.IWifiLowLatencyLockListener; import android.net.wifi.IWifiNetworkSelectionConfigListener; +import android.net.wifi.IWifiNetworkStateChangedListener; import android.net.wifi.IWifiVerboseLoggingStatusChangedListener; import android.net.wifi.MscsParams; import android.net.wifi.QosPolicyParams; @@ -70,24 +66,24 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSelectionConfig; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiSsid; - +import android.net.wifi.hotspot2.IProvisioningCallback; +import android.net.wifi.hotspot2.OsuProvider; +import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.twt.TwtRequest; - import android.os.Bundle; import android.os.Messenger; import android.os.ResultReceiver; import android.os.WorkSource; - import com.android.modules.utils.ParceledListSlice; +import com.android.modules.utils.StringParceledListSlice; /** * Interface that allows controlling and querying Wi-Fi connectivity. * * {@hide} */ -interface IWifiManager -{ - long getSupportedFeatures(); +interface IWifiManager { + boolean isFeatureSupported(int feature); oneway void getWifiActivityEnergyInfoAsync(in IOnWifiActivityEnergyInfoListener listener); @@ -103,33 +99,36 @@ interface IWifiManager void setOneShotScreenOnConnectivityScanDelayMillis(int delayMs); - ParceledListSlice getConfiguredNetworks(String packageName, String featureId, boolean callerNetworksOnly); - - ParceledListSlice getPrivilegedConfiguredNetworks(String packageName, String featureId, in Bundle extras); + ParceledListSlice getConfiguredNetworks( + String packageName, String featureId, boolean callerNetworksOnly); - WifiConfiguration getPrivilegedConnectedNetwork(String packageName, String featureId, in Bundle extras); + ParceledListSlice getPrivilegedConfiguredNetworks( + String packageName, String featureId, in Bundle extras); - Map getAllMatchingFqdnsForScanResults(in List<ScanResult> scanResult); + WifiConfiguration getPrivilegedConnectedNetwork( + String packageName, String featureId, in Bundle extras); - void setSsidsAllowlist(String packageName, in List<WifiSsid> ssids); + void setSsidsAllowlist(String packageName, in ParceledListSlice<WifiSsid> ssids); - List getSsidsAllowlist(String packageName); + ParceledListSlice getSsidsAllowlist(String packageName); - Map getMatchingOsuProviders(in List<ScanResult> scanResult); + Map getMatchingOsuProviders(in ParceledListSlice<ScanResult> scanResult); - Map getMatchingPasspointConfigsForOsuProviders(in List<OsuProvider> osuProviders); + Map getMatchingPasspointConfigsForOsuProviders(in ParceledListSlice<OsuProvider> osuProviders); int addOrUpdateNetwork(in WifiConfiguration config, String packageName, in Bundle extras); - WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged(in WifiConfiguration config, String packageName); + WifiManager.AddNetworkResult addOrUpdateNetworkPrivileged( + in WifiConfiguration config, String packageName); boolean addOrUpdatePasspointConfiguration(in PasspointConfiguration config, String packageName); boolean removePasspointConfiguration(in String fqdn, String packageName); - List<PasspointConfiguration> getPasspointConfigurations(in String packageName); + ParceledListSlice<PasspointConfiguration> getPasspointConfigurations(in String packageName); - List<WifiConfiguration> getWifiConfigsForPasspointProfiles(in List<String> fqdnList); + ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles( + in StringParceledListSlice fqdnList); void queryPasspointIcon(long bssid, String fileName); @@ -161,7 +160,8 @@ interface IWifiManager void getChannelData(in IListListener listener, String packageName, in Bundle extras); - void getBssidBlocklist(in ParceledListSlice<WifiSsid> ssids, in IMacAddressListListener listener); + void getBssidBlocklist( + in ParceledListSlice<WifiSsid> ssids, in IMacAddressListListener listener); boolean disconnect(String packageName); @@ -210,9 +210,11 @@ interface IWifiManager boolean isScanAlwaysAvailable(); - boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws, in String packageName, in Bundle extras); + boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws, + in String packageName, in Bundle extras); - void updateWifiLockWorkSource(IBinder lock, in WorkSource ws, in String packageName, in Bundle extras); + void updateWifiLockWorkSource( + IBinder lock, in WorkSource ws, in String packageName, in Bundle extras); boolean releaseWifiLock(IBinder lock); @@ -222,13 +224,14 @@ interface IWifiManager void acquireMulticastLock(IBinder binder, String tag); - void releaseMulticastLock(String tag); + void releaseMulticastLock(IBinder binder, String tag); void updateInterfaceIpState(String ifaceName, int mode); boolean isDefaultCoexAlgorithmEnabled(); - void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions); + void setCoexUnsafeChannels( + in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions); void registerCoexCallback(in ICoexCallback callback); @@ -238,14 +241,15 @@ interface IWifiManager boolean startTetheredHotspot(in SoftApConfiguration softApConfig, String packageName); - void startTetheredHotspotRequest(in TetheringRequest request, in ISoftApCallback callback, String packageName); + void startTetheredHotspotRequest( + in TetheringRequest request, in ISoftApCallback callback, String packageName); boolean stopSoftAp(); boolean validateSoftApConfiguration(in SoftApConfiguration config); int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName, - String featureId, in SoftApConfiguration customConfig, in Bundle extras); + String featureId, in SoftApConfiguration customConfig, in Bundle extras); void stopLocalOnlyHotspot(); @@ -257,11 +261,9 @@ interface IWifiManager void stopWatchLocalOnlyHotspot(); - @UnsupportedAppUsage - int getWifiApEnabledState(); + @UnsupportedAppUsage int getWifiApEnabledState(); - @UnsupportedAppUsage - WifiConfiguration getWifiApConfiguration(); + @UnsupportedAppUsage WifiConfiguration getWifiApConfiguration(); SoftApConfiguration getSoftApConfiguration(); @@ -271,15 +273,15 @@ interface IWifiManager boolean setSoftApConfiguration(in SoftApConfiguration softApConfig, String packageName); - void notifyUserOfApBandConversion(String packageName); - void enableTdls(String remoteIPAddress, boolean enable); - void enableTdlsWithRemoteIpAddress(String remoteIPAddress, boolean enable, in IBooleanListener listener); + void enableTdlsWithRemoteIpAddress( + String remoteIPAddress, boolean enable, in IBooleanListener listener); void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable); - void enableTdlsWithRemoteMacAddress(String remoteMacAddress, boolean enable, in IBooleanListener listener); + void enableTdlsWithRemoteMacAddress( + String remoteMacAddress, boolean enable, in IBooleanListener listener); void isTdlsOperationCurrentlyAvailable(in IBooleanListener listener); @@ -297,8 +299,7 @@ interface IWifiManager void factoryReset(String packageName); - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - Network getCurrentNetwork(); + @UnsupportedAppUsage(maxTargetSdk=30, trackingBug=170729553) Network getCurrentNetwork(); byte[] retrieveBackupData(); @@ -316,9 +317,11 @@ interface IWifiManager void unregisterSoftApCallback(in ISoftApCallback callback); - void addWifiVerboseLoggingStatusChangedListener(in IWifiVerboseLoggingStatusChangedListener listener); + void addWifiVerboseLoggingStatusChangedListener( + in IWifiVerboseLoggingStatusChangedListener listener); - void removeWifiVerboseLoggingStatusChangedListener(in IWifiVerboseLoggingStatusChangedListener listener); + void removeWifiVerboseLoggingStatusChangedListener( + in IWifiVerboseLoggingStatusChangedListener listener); void addOnWifiUsabilityStatsListener(in IOnWifiUsabilityStatsListener listener); @@ -332,33 +335,36 @@ interface IWifiManager void unregisterNetworkRequestMatchCallback(in INetworkRequestMatchCallback callback); - int addNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName, - in String featureId); + int addNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, + in String packageName, in String featureId); - int removeNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName, int action); + int removeNetworkSuggestions(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, + in String packageName, int action); - List<WifiNetworkSuggestion> getNetworkSuggestions(in String packageName); + ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions(in String packageName); String[] getFactoryMacAddresses(); void setDeviceMobilityState(int state); void startDppAsConfiguratorInitiator(in IBinder binder, in String packageName, - in String enrolleeUri, int selectedNetworkId, int netRole, in IDppCallback callback); + in String enrolleeUri, int selectedNetworkId, int netRole, in IDppCallback callback); - void startDppAsEnrolleeInitiator(in IBinder binder, in String configuratorUri, - in IDppCallback callback); + 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 startDppAsEnrolleeResponder( + in IBinder binder, in String deviceInfo, int curve, in IDppCallback callback); void stopDppSession(); void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec); - oneway void connect(in WifiConfiguration config, int netId, in IActionListener listener, in String packageName, in Bundle extras); + oneway void connect(in WifiConfiguration config, int netId, in IActionListener listener, + in String packageName, in Bundle extras); - oneway void save(in WifiConfiguration config, in IActionListener listener, in String packageName); + oneway void save( + in WifiConfiguration config, in IActionListener listener, in String packageName); oneway void forget(int netId, in IActionListener listener); @@ -366,25 +372,32 @@ interface IWifiManager void unregisterScanResultsCallback(in IScanResultsCallback callback); - void registerSuggestionConnectionStatusListener(in ISuggestionConnectionStatusListener listener, String packageName, String featureId); + void registerSuggestionConnectionStatusListener( + in ISuggestionConnectionStatusListener listener, String packageName, String featureId); - void unregisterSuggestionConnectionStatusListener(in ISuggestionConnectionStatusListener listener, String packageName); + void unregisterSuggestionConnectionStatusListener( + in ISuggestionConnectionStatusListener listener, String packageName); - void addLocalOnlyConnectionStatusListener(in ILocalOnlyConnectionStatusListener listener, String packageName, String featureId); + void addLocalOnlyConnectionStatusListener( + in ILocalOnlyConnectionStatusListener listener, String packageName, String featureId); - void removeLocalOnlyConnectionStatusListener(in ILocalOnlyConnectionStatusListener listener, String packageName); + void removeLocalOnlyConnectionStatusListener( + in ILocalOnlyConnectionStatusListener listener, String packageName); int calculateSignalLevel(int rssi); - List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(in List<ScanResult> scanResults); + ParceledListSlice<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + in ParceledListSlice<ScanResult> scanResults); boolean setWifiConnectedNetworkScorer(in IBinder binder, in IWifiConnectedNetworkScorer scorer); void clearWifiConnectedNetworkScorer(); - void setExternalPnoScanRequest(in IBinder binder, in IPnoScanResultsCallback callback, in List<WifiSsid> ssids, in int[] frequencies, String packageName, String featureId); + void setExternalPnoScanRequest(in IBinder binder, in IPnoScanResultsCallback callback, + in List<WifiSsid> ssids, in int[] frequencies, String packageName, String featureId); - void setPnoScanEnabled(boolean enabled, boolean enablePnoScanAfterWifiToggle, String packageName); + void setPnoScanEnabled( + boolean enabled, boolean enablePnoScanAfterWifiToggle, String packageName); void clearExternalPnoScanRequest(); @@ -393,13 +406,15 @@ interface IWifiManager /** * Return the Map of {@link WifiNetworkSuggestion} and the list of <ScanResult> */ - Map getMatchingScanResults(in List<WifiNetworkSuggestion> networkSuggestions, in List<ScanResult> scanResults, String callingPackage, String callingFeatureId); + Map getMatchingScanResults(in ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, + in ParceledListSlice<ScanResult> scanResults, String callingPackage, + String callingFeatureId); void setScanThrottleEnabled(boolean enable); boolean isScanThrottleEnabled(); - Map getAllMatchingPasspointProfilesForScanResults(in List<ScanResult> scanResult); + Map getAllMatchingPasspointProfilesForScanResults(in ParceledListSlice<ScanResult> scanResult); void setAutoWakeupEnabled(boolean enable); @@ -419,9 +434,11 @@ interface IWifiManager void restartWifiSubsystem(); - void addSuggestionUserApprovalStatusListener(in ISuggestionUserApprovalStatusListener listener, String packageName); + void addSuggestionUserApprovalStatusListener( + in ISuggestionUserApprovalStatusListener listener, String packageName); - void removeSuggestionUserApprovalStatusListener(in ISuggestionUserApprovalStatusListener listener, String packageName); + void removeSuggestionUserApprovalStatusListener( + in ISuggestionUserApprovalStatusListener listener, String packageName); void setEmergencyScanRequestInProgress(boolean inProgress); @@ -431,7 +448,8 @@ interface IWifiManager void flushPasspointAnqpCache(String packageName); - List<WifiAvailableChannel> getUsableChannels(int band, int mode, int filter, String packageName, in Bundle extras); + List<WifiAvailableChannel> getUsableChannels( + int band, int mode, int filter, String packageName, in Bundle extras); boolean isWifiPasspointEnabled(); @@ -443,7 +461,7 @@ interface IWifiManager void notifyMinimumRequiredWifiSecurityLevelChanged(int level); - void notifyWifiSsidPolicyChanged(int policyType, in List<WifiSsid> ssids); + void notifyWifiSsidPolicyChanged(int policyType, in ParceledListSlice<WifiSsid> ssids); String[] getOemPrivilegedWifiAdminPackages(); @@ -451,15 +469,18 @@ interface IWifiManager void replyToSimpleDialog(int dialogId, int reply); - void addCustomDhcpOptions(in WifiSsid ssid, in byte[] oui, in List<DhcpOption> options); + void addCustomDhcpOptions( + in WifiSsid ssid, in byte[] oui, in ParceledListSlice<DhcpOption> options); void removeCustomDhcpOptions(in WifiSsid ssid, in byte[] oui); - void reportCreateInterfaceImpact(String packageName, int interfaceType, boolean requireNewInterface, in IInterfaceCreationInfoCallback callback); + void reportCreateInterfaceImpact(String packageName, int interfaceType, + boolean requireNewInterface, in IInterfaceCreationInfoCallback callback); int getMaxNumberOfChannelsPerRequest(); - void addQosPolicies(in List<QosPolicyParams> policyParamsList, in IBinder binder, String packageName, in IListListener callback); + void addQosPolicies(in ParceledListSlice<QosPolicyParams> policyParamsList, in IBinder binder, + String packageName, in IListListener callback); void removeQosPolicies(in int[] policyIdList, String packageName); @@ -499,7 +520,7 @@ interface IWifiManager void removePerSsidRoamingMode(in WifiSsid ssid, String packageName); - void getPerSsidRoamingModes(String packageName,in IMapListener listener); + void getPerSsidRoamingModes(String packageName, in IMapListener listener); void getTwtCapabilities(in ITwtCapabilitiesListener listener, in Bundle extras); @@ -518,4 +539,8 @@ interface IWifiManager void restoreWifiBackupData(in byte[] data); boolean isPnoSupported(); + + void setAutojoinDisallowedSecurityTypes(int restrictions, in Bundle extras); + + void getAutojoinDisallowedSecurityTypes(in IIntegerListener listener, in Bundle extras); } diff --git a/framework/java/android/net/wifi/IWifiScannerListener.aidl b/framework/java/android/net/wifi/IWifiScannerListener.aidl index 04b5e41cc8..bd19ac2d0f 100644 --- a/framework/java/android/net/wifi/IWifiScannerListener.aidl +++ b/framework/java/android/net/wifi/IWifiScannerListener.aidl @@ -43,4 +43,8 @@ oneway interface IWifiScannerListener * Invoked when one of the PNO networks are found in scan results. */ void onPnoNetworkFound(in ScanResult[] results); + /** + * reports full scan result for all access points found in scan + */ + void onFullResults(in List<ScanResult> scanResult); }
\ No newline at end of file diff --git a/framework/java/android/net/wifi/WifiAnnotations.java b/framework/java/android/net/wifi/WifiAnnotations.java index 2a92c31361..7013b2b94d 100644 --- a/framework/java/android/net/wifi/WifiAnnotations.java +++ b/framework/java/android/net/wifi/WifiAnnotations.java @@ -176,4 +176,71 @@ public final class WifiAnnotations { UriParserResults.URI_SCHEME_DPP, }) public @interface UriScheme {} + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"REASON_"}, value = { + DeauthenticationReasonCode.REASON_UNKNOWN, + DeauthenticationReasonCode.REASON_UNSPECIFIED, + DeauthenticationReasonCode.REASON_PREV_AUTH_NOT_VALID, + DeauthenticationReasonCode.REASON_DEAUTH_LEAVING, + DeauthenticationReasonCode.REASON_DISASSOC_DUE_TO_INACTIVITY, + DeauthenticationReasonCode.REASON_DISASSOC_AP_BUSY, + DeauthenticationReasonCode.REASON_CLASS2_FRAME_FROM_NONAUTH_STA, + DeauthenticationReasonCode.REASON_CLASS3_FRAME_FROM_NONASSOC_STA, + DeauthenticationReasonCode.REASON_DISASSOC_STA_HAS_LEFT, + DeauthenticationReasonCode.REASON_STA_REQ_ASSOC_WITHOUT_AUTH, + DeauthenticationReasonCode.REASON_PWR_CAPABILITY_NOT_VALID, + DeauthenticationReasonCode.REASON_SUPPORTED_CHANNEL_NOT_VALID, + DeauthenticationReasonCode.REASON_BSS_TRANSITION_DISASSOC, + DeauthenticationReasonCode.REASON_INVALID_IE, + DeauthenticationReasonCode.REASON_MICHAEL_MIC_FAILURE, + DeauthenticationReasonCode.REASON_FOURWAY_HANDSHAKE_TIMEOUT, + DeauthenticationReasonCode.REASON_GROUP_KEY_UPDATE_TIMEOUT, + DeauthenticationReasonCode.REASON_IE_IN_4WAY_DIFFERS, + DeauthenticationReasonCode.REASON_GROUP_CIPHER_NOT_VALID, + DeauthenticationReasonCode.REASON_PAIRWISE_CIPHER_NOT_VALID, + DeauthenticationReasonCode.REASON_AKMP_NOT_VALID, + DeauthenticationReasonCode.REASON_UNSUPPORTED_RSN_IE_VERSION, + DeauthenticationReasonCode.REASON_INVALID_RSN_IE_CAPAB, + DeauthenticationReasonCode.REASON_IEEE_802_1X_AUTH_FAILED, + DeauthenticationReasonCode.REASON_CIPHER_SUITE_REJECTED, + DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNREACHABLE, + DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNSPECIFIED, + DeauthenticationReasonCode.REASON_SSP_REQUESTED_DISASSOC, + DeauthenticationReasonCode.REASON_NO_SSP_ROAMING_AGREEMENT, + DeauthenticationReasonCode.REASON_BAD_CIPHER_OR_AKM, + DeauthenticationReasonCode.REASON_NOT_AUTHORIZED_THIS_LOCATION, + DeauthenticationReasonCode.REASON_SERVICE_CHANGE_PRECLUDES_TS, + DeauthenticationReasonCode.REASON_UNSPECIFIED_QOS_REASON, + DeauthenticationReasonCode.REASON_NOT_ENOUGH_BANDWIDTH, + DeauthenticationReasonCode.REASON_DISASSOC_LOW_ACK, + DeauthenticationReasonCode.REASON_EXCEEDED_TXOP, + DeauthenticationReasonCode.REASON_STA_LEAVING, + DeauthenticationReasonCode.REASON_END_TS_BA_DLS, + DeauthenticationReasonCode.REASON_UNKNOWN_TS_BA, + DeauthenticationReasonCode.REASON_TIMEOUT, + DeauthenticationReasonCode.REASON_PEERKEY_MISMATCH, + DeauthenticationReasonCode.REASON_AUTHORIZED_ACCESS_LIMIT_REACHED, + DeauthenticationReasonCode.REASON_EXTERNAL_SERVICE_REQUIREMENTS, + DeauthenticationReasonCode.REASON_INVALID_FT_ACTION_FRAME_COUNT, + DeauthenticationReasonCode.REASON_INVALID_PMKID, + DeauthenticationReasonCode.REASON_INVALID_MDE, + DeauthenticationReasonCode.REASON_INVALID_FTE, + DeauthenticationReasonCode.REASON_MESH_PEERING_CANCELLED, + DeauthenticationReasonCode.REASON_MESH_MAX_PEERS, + DeauthenticationReasonCode.REASON_MESH_CONFIG_POLICY_VIOLATION, + DeauthenticationReasonCode.REASON_MESH_CLOSE_RCVD, + DeauthenticationReasonCode.REASON_MESH_MAX_RETRIES, + DeauthenticationReasonCode.REASON_MESH_CONFIRM_TIMEOUT, + DeauthenticationReasonCode.REASON_MESH_INVALID_GTK, + DeauthenticationReasonCode.REASON_MESH_INCONSISTENT_PARAMS, + DeauthenticationReasonCode.REASON_MESH_INVALID_SECURITY_CAP, + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_PROXY_INFO, + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO, + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_DEST_UNREACHABLE, + DeauthenticationReasonCode.REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS, + DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ, + DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED, + }) + public @interface SoftApDisconnectReason {} } diff --git a/framework/java/android/net/wifi/WifiClient.java b/framework/java/android/net/wifi/WifiClient.java index c69b039e9e..03fcd92561 100644 --- a/framework/java/android/net/wifi/WifiClient.java +++ b/framework/java/android/net/wifi/WifiClient.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -24,6 +25,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Log; +import com.android.wifi.flags.Flags; + import java.util.Objects; /** @hide */ @@ -38,6 +41,15 @@ public final class WifiClient implements Parcelable { private final String mApInstanceIdentifier; /** + * Reason for disconnection, if known. + * + * <p>This field is only meaningful when a client disconnects. + * It will not be updated while a client is connected. + */ + @WifiAnnotations.SoftApDisconnectReason + private final int mDisconnectReason; + + /** * The mac address of this client. */ @NonNull @@ -58,13 +70,35 @@ public final class WifiClient implements Parcelable { return mApInstanceIdentifier; } + /** + * Get the reason the client disconnected from the AP. + * + * <p>This field is only populated when the WifiClient is returned via + * {@code SoftApCallback#onClientsDisconnected}. + * The value {@link DeauthenticationReasonCode#REASON_UNKNOWN} is used as the default value + * and in the case where a client connects. + * @return a disconnection reason code to provide information on why the disconnect happened. + */ + @FlaggedApi(Flags.FLAG_SOFTAP_DISCONNECT_REASON) + @WifiAnnotations.SoftApDisconnectReason + public int getDisconnectReason() { + return mDisconnectReason; + } + private WifiClient(Parcel in) { mMacAddress = in.readParcelable(null); mApInstanceIdentifier = in.readString(); + mDisconnectReason = in.readInt(); } /** @hide */ public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) { + this(macAddress, apInstanceIdentifier, DeauthenticationReasonCode.REASON_UNKNOWN); + } + + /** @hide */ + public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier, + @WifiAnnotations.SoftApDisconnectReason int disconnectReason) { if (macAddress == null) { Log.wtf(TAG, "Null MacAddress provided"); this.mMacAddress = WifiManager.ALL_ZEROS_MAC_ADDRESS; @@ -72,6 +106,7 @@ public final class WifiClient implements Parcelable { this.mMacAddress = macAddress; } this.mApInstanceIdentifier = apInstanceIdentifier; + this.mDisconnectReason = disconnectReason; } @Override @@ -83,6 +118,7 @@ public final class WifiClient implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mMacAddress, flags); dest.writeString(mApInstanceIdentifier); + dest.writeInt(mDisconnectReason); } @NonNull @@ -102,20 +138,21 @@ public final class WifiClient implements Parcelable { return "WifiClient{" + "mMacAddress=" + mMacAddress + "mApInstanceIdentifier=" + mApInstanceIdentifier + + "mDisconnectReason=" + mDisconnectReason + '}'; } @Override public boolean equals(@Nullable Object o) { if (this == o) return true; - if (!(o instanceof WifiClient)) return false; - WifiClient client = (WifiClient) o; + if (!(o instanceof WifiClient client)) return false; return Objects.equals(mMacAddress, client.mMacAddress) - && mApInstanceIdentifier.equals(client.mApInstanceIdentifier); + && mApInstanceIdentifier.equals(client.mApInstanceIdentifier) + && mDisconnectReason == client.mDisconnectReason; } @Override public int hashCode() { - return Objects.hash(mMacAddress, mApInstanceIdentifier); + return Objects.hash(mMacAddress, mApInstanceIdentifier, mDisconnectReason); } } diff --git a/framework/java/android/net/wifi/WifiInfo.java b/framework/java/android/net/wifi/WifiInfo.java index 8e233d74d6..11be2118d4 100644 --- a/framework/java/android/net/wifi/WifiInfo.java +++ b/framework/java/android/net/wifi/WifiInfo.java @@ -794,8 +794,9 @@ public class WifiInfo implements TransportInfo, Parcelable { * @return the SSID. */ public String getSSID() { - if (mWifiSsid != null) { - String ssidString = mWifiSsid.toString(); + WifiSsid ssid = mWifiSsid; + if (ssid != null) { + String ssidString = ssid.toString(); if (!TextUtils.isEmpty(ssidString)) { return ssidString; } diff --git a/framework/java/android/net/wifi/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java index 7bd0c0d591..3a07ca4c6a 100644 --- a/framework/java/android/net/wifi/WifiManager.java +++ b/framework/java/android/net/wifi/WifiManager.java @@ -93,6 +93,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.ParceledListSlice; +import com.android.modules.utils.StringParceledListSlice; import com.android.modules.utils.build.SdkLevel; import com.android.wifi.flags.Flags; @@ -339,9 +340,14 @@ public class WifiManager { */ public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND = 4; /** - * Reason code if local-only network connection attempt failed with AP not responding + * Reason code if local-only network connection attempt failed with AP not responding. */ public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE = 5; + /** + * Reason code if local-only network request rejected by the user. + */ + @FlaggedApi(Flags.FLAG_LOCAL_ONLY_CONNECTION_OPTIMIZATION) + public static final int STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT = 6; /** @hide */ @IntDef(prefix = {"STATUS_LOCAL_ONLY_CONNECTION_FAILURE_"}, @@ -350,7 +356,8 @@ public class WifiManager { STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION, STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING, STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NOT_FOUND, - STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE + STATUS_LOCAL_ONLY_CONNECTION_FAILURE_NO_RESPONSE, + STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT }) @Retention(RetentionPolicy.SOURCE) public @interface LocalOnlyConnectionStatusCode {} @@ -2388,13 +2395,15 @@ public class WifiManager { List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); try { Map<String, Map<Integer, List<ScanResult>>> results = - mService.getAllMatchingPasspointProfilesForScanResults(scanResults); + mService.getAllMatchingPasspointProfilesForScanResults( + new ParceledListSlice<>(scanResults)); if (results.isEmpty()) { return configs; } List<WifiConfiguration> wifiConfigurations = mService.getWifiConfigsForPasspointProfiles( - new ArrayList<>(results.keySet())); + new StringParceledListSlice(new ArrayList<>(results.keySet()))) + .getList(); for (WifiConfiguration configuration : wifiConfigurations) { Map<Integer, List<ScanResult>> scanResultsPerNetworkType = results.get(configuration.getProfileKey()); @@ -2695,7 +2704,8 @@ public class WifiManager { public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( @NonNull List<ScanResult> scanResults) { try { - return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults); + return mService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(scanResults)).getList(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -2722,7 +2732,8 @@ public class WifiManager { throw new IllegalArgumentException(TAG + ": ssids can not be null"); } try { - mService.setSsidsAllowlist(mContext.getOpPackageName(), new ArrayList<>(ssids)); + mService.setSsidsAllowlist(mContext.getOpPackageName(), + new ParceledListSlice<>(new ArrayList<>(ssids))); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2743,7 +2754,7 @@ public class WifiManager { public @NonNull Set<WifiSsid> getSsidsAllowlist() { try { return new ArraySet<WifiSsid>( - mService.getSsidsAllowlist(mContext.getOpPackageName())); + mService.getSsidsAllowlist(mContext.getOpPackageName()).getList()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2771,7 +2782,7 @@ public class WifiManager { return new HashMap<>(); } try { - return mService.getMatchingOsuProviders(scanResults); + return mService.getMatchingOsuProviders(new ParceledListSlice<>(scanResults)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2799,7 +2810,7 @@ public class WifiManager { @NonNull Set<OsuProvider> osuProviders) { try { return mService.getMatchingPasspointConfigsForOsuProviders( - new ArrayList<>(osuProviders)); + new ParceledListSlice<>(new ArrayList<>(osuProviders))); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3402,8 +3413,8 @@ public class WifiManager { public @NetworkSuggestionsStatusCode int addNetworkSuggestions( @NonNull List<WifiNetworkSuggestion> networkSuggestions) { try { - return mService.addNetworkSuggestions( - networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag()); + return mService.addNetworkSuggestions(new ParceledListSlice<>(networkSuggestions), + mContext.getOpPackageName(), mContext.getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3455,7 +3466,7 @@ public class WifiManager { @NonNull List<WifiNetworkSuggestion> networkSuggestions, @ActionAfterRemovingSuggestion int action) { try { - return mService.removeNetworkSuggestions(networkSuggestions, + return mService.removeNetworkSuggestions(new ParceledListSlice<>(networkSuggestions), mContext.getOpPackageName(), action); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -3471,7 +3482,7 @@ public class WifiManager { @RequiresPermission(ACCESS_WIFI_STATE) public @NonNull List<WifiNetworkSuggestion> getNetworkSuggestions() { try { - return mService.getNetworkSuggestions(mContext.getOpPackageName()); + return mService.getNetworkSuggestions(mContext.getOpPackageName()).getList(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -3570,7 +3581,7 @@ public class WifiManager { @Deprecated public List<PasspointConfiguration> getPasspointConfigurations() { try { - return mService.getPasspointConfigurations(mContext.getOpPackageName()); + return mService.getPasspointConfigurations(mContext.getOpPackageName()).getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3841,208 +3852,204 @@ public class WifiManager { } /** @hide */ - public static final long WIFI_FEATURE_INFRA = 1L << 0; // Basic infrastructure mode + public static final int WIFI_FEATURE_INFRA = 0; // Basic infrastructure mode /** @hide */ - public static final long WIFI_FEATURE_PASSPOINT = 1L << 2; // Support for GAS/ANQP + public static final int WIFI_FEATURE_PASSPOINT = 2; // Support for GAS/ANQP /** @hide */ - public static final long WIFI_FEATURE_P2P = 1L << 3; // Wifi-Direct + public static final int WIFI_FEATURE_P2P = 3; // Wifi-Direct /** @hide */ - public static final long WIFI_FEATURE_MOBILE_HOTSPOT = 1L << 4; // Soft AP + public static final int WIFI_FEATURE_MOBILE_HOTSPOT = 4; // Soft AP /** @hide */ - public static final long WIFI_FEATURE_SCANNER = 1L << 5; // WifiScanner APIs + public static final int WIFI_FEATURE_SCANNER = 5; // WifiScanner APIs /** @hide */ - public static final long WIFI_FEATURE_AWARE = 1L << 6; // Wi-Fi Aware networking + public static final int WIFI_FEATURE_AWARE = 6; // Wi-Fi Aware networking /** @hide */ - public static final long WIFI_FEATURE_D2D_RTT = 1L << 7; // Device-to-device RTT + public static final int WIFI_FEATURE_D2D_RTT = 7; // Device-to-device RTT /** @hide */ - public static final long WIFI_FEATURE_D2AP_RTT = 1L << 8; // Device-to-AP RTT + public static final int WIFI_FEATURE_D2AP_RTT = 8; // Device-to-AP RTT /** @hide */ - public static final long WIFI_FEATURE_PNO = 1L << 10; // Preferred network offload + public static final int WIFI_FEATURE_PNO = 10; // Preferred network offload /** @hide */ - public static final long WIFI_FEATURE_TDLS = 1L << 12; // Tunnel directed link setup + public static final int WIFI_FEATURE_TDLS = 12; // Tunnel directed link setup /** @hide */ - public static final long WIFI_FEATURE_TDLS_OFFCHANNEL = 1L << 13; // TDLS off channel + public static final int WIFI_FEATURE_TDLS_OFFCHANNEL = 13; // TDLS off channel /** @hide */ - public static final long WIFI_FEATURE_AP_STA = 1L << 15; // AP STA Concurrency + public static final int WIFI_FEATURE_AP_STA = 15; // AP STA Concurrency /** @hide */ - public static final long WIFI_FEATURE_LINK_LAYER_STATS = 1L << 16; // Link layer stats + public static final int WIFI_FEATURE_LINK_LAYER_STATS = 16; // Link layer stats /** @hide */ - public static final long WIFI_FEATURE_LOGGER = 1L << 17; // WiFi Logger + public static final int WIFI_FEATURE_LOGGER = 17; // WiFi Logger /** @hide */ - public static final long WIFI_FEATURE_RSSI_MONITOR = 1L << 19; // RSSI Monitor + public static final int WIFI_FEATURE_RSSI_MONITOR = 19; // RSSI Monitor /** @hide */ - public static final long WIFI_FEATURE_MKEEP_ALIVE = 1L << 20; // mkeep_alive + public static final int WIFI_FEATURE_MKEEP_ALIVE = 20; // mkeep_alive /** @hide */ - public static final long WIFI_FEATURE_CONFIG_NDO = 1L << 21; // ND offload + public static final int WIFI_FEATURE_CONFIG_NDO = 21; // ND offload /** @hide */ - public static final long WIFI_FEATURE_CONTROL_ROAMING = 1L << 23; // Control firmware roaming + public static final int WIFI_FEATURE_CONTROL_ROAMING = 23; // Control firmware roaming /** @hide */ - public static final long WIFI_FEATURE_IE_WHITELIST = 1L << 24; // Probe IE white listing + public static final int WIFI_FEATURE_IE_WHITELIST = 24; // Probe IE white listing /** @hide */ - public static final long WIFI_FEATURE_SCAN_RAND = 1L << 25; // Random MAC & Probe seq + public static final int WIFI_FEATURE_SCAN_RAND = 25; // Random MAC & Probe seq /** @hide */ - public static final long WIFI_FEATURE_TX_POWER_LIMIT = 1L << 26; // Set Tx power limit + public static final int WIFI_FEATURE_TX_POWER_LIMIT = 26; // Set Tx power limit /** @hide */ - public static final long WIFI_FEATURE_WPA3_SAE = 1L << 27; // WPA3-Personal SAE + public static final int WIFI_FEATURE_WPA3_SAE = 27; // WPA3-Personal SAE /** @hide */ - public static final long WIFI_FEATURE_WPA3_SUITE_B = 1L << 28; // WPA3-Enterprise Suite-B + public static final int WIFI_FEATURE_WPA3_SUITE_B = 28; // WPA3-Enterprise Suite-B /** @hide */ - public static final long WIFI_FEATURE_OWE = 1L << 29; // Enhanced Open + public static final int WIFI_FEATURE_OWE = 29; // Enhanced Open /** @hide */ - public static final long WIFI_FEATURE_LOW_LATENCY = 1L << 30; // Low Latency modes + public static final int WIFI_FEATURE_LOW_LATENCY = 30; // Low Latency modes /** @hide */ - public static final long WIFI_FEATURE_DPP = 1L << 31; // DPP (Easy-Connect) + public static final int WIFI_FEATURE_DPP = 31; // DPP (Easy-Connect) /** @hide */ - public static final long WIFI_FEATURE_P2P_RAND_MAC = 1L << 32; // Random P2P MAC + public static final int WIFI_FEATURE_P2P_RAND_MAC = 32; // Random P2P MAC /** @hide */ - public static final long WIFI_FEATURE_CONNECTED_RAND_MAC = 1L << 33; // Random STA MAC + public static final int WIFI_FEATURE_CONNECTED_RAND_MAC = 33; // Random STA MAC /** @hide */ - public static final long WIFI_FEATURE_AP_RAND_MAC = 1L << 34; // Random AP MAC + public static final int WIFI_FEATURE_AP_RAND_MAC = 34; // Random AP MAC /** @hide */ - public static final long WIFI_FEATURE_MBO = 1L << 35; // MBO Support + public static final int WIFI_FEATURE_MBO = 35; // MBO Support /** @hide */ - public static final long WIFI_FEATURE_OCE = 1L << 36; // OCE Support + public static final int WIFI_FEATURE_OCE = 36; // OCE Support /** @hide */ - public static final long WIFI_FEATURE_WAPI = 1L << 37; // WAPI + public static final int WIFI_FEATURE_WAPI = 37; // WAPI /** @hide */ - public static final long WIFI_FEATURE_FILS_SHA256 = 1L << 38; // FILS-SHA256 + public static final int WIFI_FEATURE_FILS_SHA256 = 38; // FILS-SHA256 /** @hide */ - public static final long WIFI_FEATURE_FILS_SHA384 = 1L << 39; // FILS-SHA384 + public static final int WIFI_FEATURE_FILS_SHA384 = 39; // FILS-SHA384 /** @hide */ - public static final long WIFI_FEATURE_SAE_PK = 1L << 40; // SAE-PK + public static final int WIFI_FEATURE_SAE_PK = 40; // SAE-PK /** @hide */ - public static final long WIFI_FEATURE_STA_BRIDGED_AP = 1L << 41; // STA + Bridged AP + public static final int WIFI_FEATURE_STA_BRIDGED_AP = 41; // STA + Bridged AP /** @hide */ - public static final long WIFI_FEATURE_BRIDGED_AP = 1L << 42; // Bridged AP + public static final int WIFI_FEATURE_BRIDGED_AP = 42; // Bridged AP /** @hide */ - public static final long WIFI_FEATURE_INFRA_60G = 1L << 43; // 60 GHz Band Support + public static final int WIFI_FEATURE_INFRA_60G = 43; // 60 GHz Band Support /** * Support for 2 STA's for the local-only (peer to peer) connection + internet connection * concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 1L << 44; + public static final int WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY = 44; /** * Support for 2 STA's for the make before break concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_MBB = 1L << 45; + public static final int WIFI_FEATURE_ADDITIONAL_STA_MBB = 45; /** * Support for 2 STA's for the restricted connection + internet connection concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 1L << 46; + public static final int WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED = 46; /** * DPP (Easy-Connect) Enrollee Responder mode support * @hide */ - public static final long WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 1L << 47; + public static final int WIFI_FEATURE_DPP_ENROLLEE_RESPONDER = 47; /** * Passpoint Terms and Conditions feature support * @hide */ - public static final long WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 1L << 48; + public static final int WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS = 48; /** @hide */ - public static final long WIFI_FEATURE_SAE_H2E = 1L << 49; // Hash-to-Element + public static final int WIFI_FEATURE_SAE_H2E = 49; // Hash-to-Element /** @hide */ - public static final long WIFI_FEATURE_WFD_R2 = 1L << 50; // Wi-Fi Display R2 + public static final int WIFI_FEATURE_WFD_R2 = 50; // Wi-Fi Display R2 /** * RFC 7542 decorated identity support * @hide */ - public static final long WIFI_FEATURE_DECORATED_IDENTITY = 1L << 51; + public static final int WIFI_FEATURE_DECORATED_IDENTITY = 51; /** * Trust On First Use support for WPA Enterprise network * @hide */ - public static final long WIFI_FEATURE_TRUST_ON_FIRST_USE = 1L << 52; + public static final int WIFI_FEATURE_TRUST_ON_FIRST_USE = 52; /** * Support for 2 STA's multi internet concurrency. * @hide */ - public static final long WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 1L << 53; + public static final int WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET = 53; /** * Support for DPP (Easy-Connect) AKM. * @hide */ - public static final long WIFI_FEATURE_DPP_AKM = 1L << 54; + public static final int WIFI_FEATURE_DPP_AKM = 54; /** * Support for setting TLS minimum version. * @hide */ - public static final long WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 1L << 55; + public static final int WIFI_FEATURE_SET_TLS_MINIMUM_VERSION = 55; /** * Support for TLS v.13. * @hide */ - public static final long WIFI_FEATURE_TLS_V1_3 = 1L << 56; + public static final int WIFI_FEATURE_TLS_V1_3 = 56; /** * Support for Dual Band Simultaneous (DBS) operation. * @hide */ - public static final long WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 1L << 57; + public static final int WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS = 57; /** * Support for TID-To-Link Mapping negotiation. * @hide */ - public static final long WIFI_FEATURE_T2LM_NEGOTIATION = 1L << 58; + public static final int WIFI_FEATURE_T2LM_NEGOTIATION = 58; /** * Support for WEP Wi-Fi Network * @hide */ - public static final long WIFI_FEATURE_WEP = 1L << 59; + public static final int WIFI_FEATURE_WEP = 59; /** * Support for WPA PERSONAL Wi-Fi Network * @hide */ - public static final long WIFI_FEATURE_WPA_PERSONAL = 1L << 60; + public static final int WIFI_FEATURE_WPA_PERSONAL = 60; /** * Support for Roaming Mode * @hide */ - public static final long WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 1L << 61; + public static final int WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT = 61; /** * Supports device-to-device connections when infra STA is disabled. * @hide */ - public static final long WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 1L << 62; + public static final int WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED = 62; - private long getSupportedFeatures() { + private boolean isFeatureSupported(int feature) { try { - return mService.getSupportedFeatures(); + return mService.isFeatureSupported(feature); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - private boolean isFeatureSupported(long feature) { - return (getSupportedFeatures() & feature) == feature; - } - /** * @return true if this adapter supports Passpoint * @hide @@ -4567,7 +4574,8 @@ public class WifiManager { } try { return mService.getMatchingScanResults( - networkSuggestionsToMatch, scanResults, + new ParceledListSlice<>(networkSuggestionsToMatch), + new ParceledListSlice<>(scanResults), mContext.getOpPackageName(), mContext.getAttributionTag()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -5158,8 +5166,9 @@ public class WifiManager { * <li>Device Owner (DO), Profile Owner (PO) and system apps. * </ul> * - * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO/COPE may set - * a user restriction (DISALLOW_CHANGE_WIFI_STATE) to only allow DO/PO to use this API. + * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, DO and a profile owner of + * an organization owned device may set a user restriction (DISALLOW_CHANGE_WIFI_STATE) + * to only allow DO/PO to use this API. */ @Deprecated public boolean setWifiEnabled(boolean enabled) { @@ -8269,7 +8278,7 @@ public class WifiManager { mService.acquireMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - mService.releaseMulticastLock(mTag); + mService.releaseMulticastLock(mBinder, mTag); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -8311,7 +8320,7 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - mService.releaseMulticastLock(mTag); + mService.releaseMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -11320,8 +11329,8 @@ public class WifiManager { } try { if (policy != null) { - mService.notifyWifiSsidPolicyChanged( - policy.getPolicyType(), new ArrayList<>(policy.getSsids())); + mService.notifyWifiSsidPolicyChanged(policy.getPolicyType(), + new ParceledListSlice<>(new ArrayList<>(policy.getSsids()))); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -11634,7 +11643,7 @@ public class WifiManager { public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, @NonNull List<DhcpOption> options) { try { - mService.addCustomDhcpOptions(ssid, oui, options); + mService.addCustomDhcpOptions(ssid, oui, new ParceledListSlice<>(options)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -11894,7 +11903,8 @@ public class WifiManager { Objects.requireNonNull(executor, "executor cannot be null"); Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); try { - mService.addQosPolicies(policyParamsList, new Binder(), mContext.getOpPackageName(), + mService.addQosPolicies(new ParceledListSlice<>(policyParamsList), + new Binder(), mContext.getOpPackageName(), new IListListener.Stub() { @Override public void onResult(List value) { @@ -12441,18 +12451,19 @@ public class WifiManager { /** * This API allows a privileged application to set roaming mode per SSID. * - * Available for DO/COPE apps. + * Available for Device Owner (DO) and profile owner of an organization owned device. * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. * * @param ssid SSID to be mapped to apply roaming policy - * @param roamingMode refer {@link RoamingMode} for supported modes. - * @throws IllegalArgumentException if mode value is not in {@link RoamingMode}. + * @param roamingMode One of the {@code ROAMING_MODE_} values. + * @throws IllegalArgumentException if input is invalid. * @throws NullPointerException if the caller provided a null input. * @throws SecurityException if caller does not have the required permission. - * @throws UnsupportedOperationException if the set operation is not supported on this SDK or - * if the feature is not available - * {@link #isAggressiveRoamingModeSupported()}. + * @throws UnsupportedOperationException if the API is not supported on this SDK version or + * {@link #isAggressiveRoamingModeSupported()} returns + * false, but input roaming mode is + * {@code ROAMING_MODE_AGGRESSIVE}. */ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) @@ -12473,16 +12484,14 @@ public class WifiManager { * This API allows a privileged application to remove roaming mode policy * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. * - * Available for DO/COPE apps. + * Available for Device Owner (DO) and profile owner of an organization owned device. * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. * * @param ssid SSID to be removed from the roaming mode policy. * @throws NullPointerException if the caller provided a null input. * @throws SecurityException if caller does not have the required permission. - * @throws UnsupportedOperationException if the set operation is not supported on this SDK or - * if the feature is not available - * {@link #isAggressiveRoamingModeSupported()}. + * @throws UnsupportedOperationException if the API is not supported on this SDK version. */ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) @@ -12500,7 +12509,7 @@ public class WifiManager { * This API allows a privileged application to get roaming mode policies * configured using the {@link #setPerSsidRoamingMode(WifiSsid, int)}. * - * Available for DO/COPE apps. + * Available for Device Owner (DO) and profile owner of an organization owned device. * Other apps require {@code android.Manifest.permission#NETWORK_SETTINGS} or * {@code android.Manifest.permission#MANAGE_WIFI_NETWORK_SELECTION} permission. * @@ -12508,9 +12517,7 @@ public class WifiManager { * @param resultsCallback An asynchronous callback that will return the corresponding * roaming policies for the API caller. * @throws SecurityException if caller does not have the required permission. - * @throws UnsupportedOperationException if the get operation is not supported on this SDK or - * if the feature is not available - * {@link #isAggressiveRoamingModeSupported()}. + * @throws UnsupportedOperationException if the API is not supported on this SDK version. */ @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM) @@ -12857,4 +12864,120 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } + + /** + * Disallow Wi-Fi autojoin on ScanResults matching the selected security types. + * This does not restrict manual connections. + * + * @param restrictions An array of {@code WifiInfo.SECURITY_TYPE_*} values to disallow autojoin. + * An empty array will clear all restrictions. Note, certain combinations of + * restricted security types are not valid. + * 1. restrictions contains WifiInfo.SECURITY_TYPE_OWE, + * but not WifiInfo.SECURITY_TYPE_OPEN. + * 2. restrictions contains WifiInfo.SECURITY_TYPE_SAE, + * but not WifiInfo.SECURITY_TYPE_PSK. + * 3. restrictions contains WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, + * but not WifiInfo.SECURITY_TYPE_EAP. + * + * Usage example: + * <pre> + * To disallow autojoin to Wi-Fi networks with security type, OPEN, WEP + * or OWE, use following argument. + * + * {@code + * int[] restrictions = { + * WifiInfo.SECURITY_TYPE_OPEN, + * WifiInfo.SECURITY_TYPE_WEP, + * WifiInfo.SECURITY_TYPE_OWE }; + * wifiManager.setAutojoinDisallowedSecurityTypes(restrictions); + * } + * + * To clear autojoin restriction on all security types, use following + * argument. + * + * {@code + * wifiManager.setAutojoinDisallowedSecurityTypes(new int[0]); + * } + * </pre> + * @throws UnsupportedOperationException if the API is not supported. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API) + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + MANAGE_WIFI_NETWORK_SELECTION + }) + public void setAutojoinDisallowedSecurityTypes( + @NonNull @WifiAnnotations.SecurityType int[] restrictions) { + if (!SdkLevel.isAtLeastT()) { + throw new UnsupportedOperationException(); + } + Objects.requireNonNull(restrictions, "restrictions cannot be null"); + try { + Bundle extras = new Bundle(); + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + int restrictionBitmap = 0; + for (int securityType : restrictions) { + restrictionBitmap |= 0x1 << securityType; + } + mService.setAutojoinDisallowedSecurityTypes(restrictionBitmap, extras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves the autojoin disallowed Wi-Fi security types currently set for the device. + * + * @param executor The executor to run the callback on. + * @param resultsCallback The callback to receive the result. It will be called with an array + * of autojoin disallowedse security types from + * {@code WifiInfo.SECURITY_TYPE_*}. + * @throws UnsupportedOperationException if the API is not supported. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_AUTOJOIN_RESTRICTION_SECURITY_TYPES_API) + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + MANAGE_WIFI_NETWORK_SELECTION + }) + public void getAutojoinDisallowedSecurityTypes(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<int[]> resultsCallback) { + if (!SdkLevel.isAtLeastT()) { + throw new UnsupportedOperationException(); + } + Objects.requireNonNull(executor, "executor cannot be null"); + Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); + try { + Bundle extras = new Bundle(); + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + mService.getAutojoinDisallowedSecurityTypes(new IIntegerListener.Stub() { + @Override + public void onResult(int value) { + Binder.clearCallingIdentity(); + executor.execute(() -> { + List<Integer> restrictions = new ArrayList<>(); + for (int i = 0; i < Integer.SIZE; i++) { + if (((0x1 << i) & value) != 0) { + restrictions.add(i); + } + } + int[] results = new int[restrictions.size()]; + for (int i = 0; i < restrictions.size(); i++) { + results[i] = restrictions.get(i); + } + resultsCallback.accept(results); + }); + } + }, extras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework/java/android/net/wifi/WifiNetworkSpecifier.java b/framework/java/android/net/wifi/WifiNetworkSpecifier.java index a137b220fb..199969d9c7 100644 --- a/framework/java/android/net/wifi/WifiNetworkSpecifier.java +++ b/framework/java/android/net/wifi/WifiNetworkSpecifier.java @@ -829,6 +829,7 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc .append(", BSSID Match pattern=").append(bssidPatternMatcher) .append(", SSID=").append(wifiConfiguration.SSID) .append(", BSSID=").append(wifiConfiguration.BSSID) + .append(", channels=").append(Arrays.toString(mChannelFreqs)) .append(", band=").append(mBand) .append("]") .toString(); diff --git a/framework/java/android/net/wifi/WifiScanner.java b/framework/java/android/net/wifi/WifiScanner.java index b9c6f428d3..1dffa8a3c7 100644 --- a/framework/java/android/net/wifi/WifiScanner.java +++ b/framework/java/android/net/wifi/WifiScanner.java @@ -375,6 +375,7 @@ public class WifiScanner { */ @Override public void onFullResult(ScanResult fullScanResult) { + Log.i(TAG, "onFullResult"); if (mActionListener == null) return; if (!(mActionListener instanceof ScanListener)) return; ScanListener scanListener = (ScanListener) mActionListener; @@ -383,6 +384,20 @@ public class WifiScanner { () -> scanListener.onFullResult(fullScanResult)); } + /** + * reports full scan result for all access points found in scan + */ + @Override + public void onFullResults(List<ScanResult> fullScanResult) { + Log.i(TAG, "onFullResults"); + if (mActionListener == null) return; + if (!(mActionListener instanceof ScanListener)) return; + ScanListener scanListener = (ScanListener) mActionListener; + Binder.clearCallingIdentity(); + mExecutor.execute( + () -> fullScanResult.forEach(scanListener::onFullResult)); + } + @Override public void onSingleScanCompleted() { if (DBG) Log.d(TAG, "single scan completed"); @@ -431,6 +446,16 @@ public class WifiScanner { passive = false; dwellTimeMS = 0; } + + /** + * @hide + * Todo: add it to the sdk + */ + public ChannelSpec(int frequency, boolean passive, int dwellTimeMS) { + this.frequency = frequency; + this.passive = passive; + this.dwellTimeMS = dwellTimeMS; + } } /** @@ -732,6 +757,44 @@ public class WifiScanner { return mVendorIes; } + public ScanSettings() {} + + /** + * @hide + * Todo: add it to the sdk + */ + public ScanSettings(@NonNull ScanSettings that) { + this.band = that.band; + this.periodInMs = that.periodInMs; + this.reportEvents = that.reportEvents; + this.numBssidsPerScan = that.numBssidsPerScan; + this.maxScansToCache = that.maxScansToCache; + this.maxPeriodInMs = that.maxPeriodInMs; + this.stepCount = that.stepCount; + this.isPnoScan = that.isPnoScan; + this.type = that.type; + this.ignoreLocationSettings = that.ignoreLocationSettings; + this.hideFromAppOps = that.hideFromAppOps; + this.mRnrSetting = that.mRnrSetting; + this.mEnable6GhzPsc = that.mEnable6GhzPsc; + if (that.channels != null) { + this.channels = new ChannelSpec[that.channels.length]; + for (int i = 0; i < that.channels.length; i++) { + ChannelSpec spec = new ChannelSpec(that.channels[i].frequency, + that.channels[i].passive, that.channels[i].dwellTimeMS); + this.channels[i] = spec; + } + } else { + this.channels = new ChannelSpec[0]; + } + for (HiddenNetwork hiddenNetwork : that.hiddenNetworks) { + this.hiddenNetworks.add(new HiddenNetwork(hiddenNetwork.ssid)); + } + for (ScanResult.InformationElement ie : that.mVendorIes) { + this.mVendorIes.add(new ScanResult.InformationElement(ie.id, ie.idExt, ie.bytes)); + } + } + /** Implement the Parcelable interface {@hide} */ public int describeContents() { return 0; diff --git a/framework/java/android/net/wifi/WifiUriParser.java b/framework/java/android/net/wifi/WifiUriParser.java index ada1fa97ba..1d42ae5ada 100644 --- a/framework/java/android/net/wifi/WifiUriParser.java +++ b/framework/java/android/net/wifi/WifiUriParser.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.SystemApi; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import androidx.annotation.VisibleForTesting; @@ -68,6 +69,7 @@ public class WifiUriParser { static final String PREFIX_ZXING_TRANSITION_DISABLE = "R:"; static final String DELIMITER_QR_CODE = ";"; + static final char URI_DELIMITER_CHAR = ';'; // Ignores password if security is SECURITY_NO_PASSWORD or absent static final String SECURITY_NO_PASSWORD = "nopass"; // open network or OWE @@ -80,6 +82,14 @@ public class WifiUriParser { private WifiUriParser() {} /** + * @hide + */ + @VisibleForTesting + public static boolean mockableIsFlagNewUriParsingForEscapeCharacterEnabled() { + return Flags.newUriParsingForEscapeCharacter(); + } + + /** * Returns parsed result from given uri. * * @param uri URI of the configuration that was obtained out of band(QR code scanning, BLE). @@ -117,26 +127,73 @@ public class WifiUriParser { } /** Parses ZXing reader library's Wi-Fi Network config format */ - private static UriParserResults parseZxingWifiUriParser(String uri) + private static UriParserResults parseZxingWifiUriParser(@NonNull String uri) throws IllegalArgumentException { - List<String> keyValueList = - getKeyValueList(uri, PREFIX_ZXING_WIFI_NETWORK_CONFIG, DELIMITER_QR_CODE); WifiConfiguration config = null; - String security = getValueOrNull(keyValueList, PREFIX_ZXING_SECURITY); - String ssid = getValueOrNull(keyValueList, PREFIX_ZXING_SSID); - String password = getValueOrNull(keyValueList, PREFIX_ZXING_PASSWORD); - String hiddenSsidString = getValueOrNull(keyValueList, PREFIX_ZXING_HIDDEN_SSID); - String transitionDisabledValue = getValueOrNull(keyValueList, - PREFIX_ZXING_TRANSITION_DISABLE); + String security = null; + String ssid = null; + String password = null; + String hiddenSsidString = null; + String transitionDisabledValue = null; + if (mockableIsFlagNewUriParsingForEscapeCharacterEnabled()) { + String wifiQr = uri.substring(PREFIX_ZXING_WIFI_NETWORK_CONFIG.length()); + Pair<Integer, String> zxingUriElement; + int start = 0; + while (start < wifiQr.length()) { + String value = wifiQr.substring(start); + char ch = wifiQr.charAt(start); + if (value.startsWith(PREFIX_ZXING_SSID)) { + zxingUriElement = getZxingUriElement(value, PREFIX_ZXING_SSID); + ssid = zxingUriElement.second; + start = start + zxingUriElement.first + PREFIX_ZXING_SSID.length(); + } else if (value.startsWith(PREFIX_ZXING_SECURITY)) { + zxingUriElement = getZxingUriElement(value, PREFIX_ZXING_SECURITY); + security = zxingUriElement.second; + start = start + zxingUriElement.first + PREFIX_ZXING_SECURITY.length(); + } else if (value.startsWith(PREFIX_ZXING_PASSWORD)) { + zxingUriElement = getZxingUriElement(value, PREFIX_ZXING_PASSWORD); + password = zxingUriElement.second; + start = start + zxingUriElement.first + PREFIX_ZXING_PASSWORD.length(); + } else if (value.startsWith(PREFIX_ZXING_HIDDEN_SSID)) { + zxingUriElement = getZxingUriElement(value, PREFIX_ZXING_HIDDEN_SSID); + hiddenSsidString = zxingUriElement.second; + start = start + zxingUriElement.first + + PREFIX_ZXING_HIDDEN_SSID.length(); + } else if (value.startsWith(PREFIX_ZXING_TRANSITION_DISABLE)) { + zxingUriElement = getZxingUriElement(value, + PREFIX_ZXING_TRANSITION_DISABLE); + transitionDisabledValue = zxingUriElement.second; + start = start + zxingUriElement.first + + PREFIX_ZXING_TRANSITION_DISABLE.length(); + } else if (Character.isWhitespace(ch) || ch == URI_DELIMITER_CHAR) { + // Skip space and DELIMITER_QR_CODE in URI when detecting prefix + start++; + } else { + zxingUriElement = getZxingUriElement(value, "" /* empty prefix */); + String unsupportedUriPrefix = zxingUriElement.second; + Log.i(TAG, "UnsupportedUriPrefix Found:" + unsupportedUriPrefix); + start = start + zxingUriElement.first; + } + } + } else { + List<String> keyValueList = + getKeyValueList(uri, PREFIX_ZXING_WIFI_NETWORK_CONFIG, DELIMITER_QR_CODE); + security = getValueOrNull(keyValueList, PREFIX_ZXING_SECURITY); + ssid = getValueOrNull(keyValueList, PREFIX_ZXING_SSID); + password = getValueOrNull(keyValueList, PREFIX_ZXING_PASSWORD); + hiddenSsidString = getValueOrNull(keyValueList, PREFIX_ZXING_HIDDEN_SSID); + transitionDisabledValue = getValueOrNull(keyValueList, + PREFIX_ZXING_TRANSITION_DISABLE); + + // "\", ";", "," and ":" are escaped with a backslash "\", should remove at first + security = removeBackSlash(security); + ssid = removeBackSlash(ssid); + password = removeBackSlash(password); + } boolean hiddenSsid = "true".equalsIgnoreCase(hiddenSsidString); boolean isTransitionDisabled = "1".equalsIgnoreCase(transitionDisabledValue); - - // "\", ";", "," and ":" are escaped with a backslash "\", should remove at first - security = removeBackSlash(security); - ssid = removeBackSlash(ssid); - password = removeBackSlash(password); if (isValidConfig(security, ssid, password)) { - config = generatetWifiConfiguration( + config = generateWifiConfiguration( security, ssid, password, hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID, isTransitionDisabled); } @@ -148,6 +205,36 @@ public class WifiUriParser { null, null, config); } + private static Pair<Integer, String> getZxingUriElement(@NonNull String uriSubString, + @NonNull String prefixString) { + StringBuilder sb = new StringBuilder(); + int numberOfCharHandled = 0; + boolean isPreviousCharEscaped = false; + for (int i = prefixString.length(); i < uriSubString.length(); i++) { + char ch = uriSubString.charAt(i); + numberOfCharHandled++; + if (ch == '\\') { + if (isPreviousCharEscaped) { + // The '\' is the part of the uri field + sb.append(ch); + isPreviousCharEscaped = false; + continue; + } + isPreviousCharEscaped = true; + } else if (ch == URI_DELIMITER_CHAR) { + if (!isPreviousCharEscaped) { + break; + } + sb.append(ch); + isPreviousCharEscaped = false; + } else { + sb.append(ch); + isPreviousCharEscaped = false; + } + } + return new Pair<>(numberOfCharHandled, sb.toString()); + } + /** * Splits key/value pairs from uri * @@ -203,13 +290,15 @@ public class WifiUriParser { return sb.toString(); } - private static String addQuotationIfNeeded(String input) { + private static String addQuotation(String input) { if (TextUtils.isEmpty(input)) { return ""; } - if (input.length() >= 2 && input.startsWith("\"") && input.endsWith("\"")) { - return input; + if (!mockableIsFlagNewUriParsingForEscapeCharacterEnabled()) { + if (input.length() >= 2 && input.startsWith("\"") && input.endsWith("\"")) { + return input; + } } StringBuilder sb = new StringBuilder(); @@ -236,11 +325,11 @@ public class WifiUriParser { * * @return WifiConfiguration from parsing result */ - private static WifiConfiguration generatetWifiConfiguration( + private static WifiConfiguration generateWifiConfiguration( String security, String ssid, String preSharedKey, boolean hiddenSsid, int networkId, boolean isTransitionDisabled) { final WifiConfiguration wifiConfiguration = new WifiConfiguration(); - wifiConfiguration.SSID = addQuotationIfNeeded(ssid); + wifiConfiguration.SSID = addQuotation(ssid); wifiConfiguration.hiddenSSID = hiddenSsid; wifiConfiguration.networkId = networkId; @@ -263,7 +352,7 @@ public class WifiUriParser { && preSharedKey.matches("[0-9A-Fa-f]*")) { wifiConfiguration.wepKeys[0] = preSharedKey; } else { - wifiConfiguration.wepKeys[0] = addQuotationIfNeeded(preSharedKey); + wifiConfiguration.wepKeys[0] = addQuotation(preSharedKey); } } else if (security.startsWith(SECURITY_WPA_PSK)) { List<SecurityParams> securityParamsList = new ArrayList<>(); @@ -281,17 +370,18 @@ public class WifiUriParser { if (preSharedKey.matches("[0-9A-Fa-f]{64}")) { wifiConfiguration.preSharedKey = preSharedKey; } else { - wifiConfiguration.preSharedKey = addQuotationIfNeeded(preSharedKey); + wifiConfiguration.preSharedKey = addQuotation(preSharedKey); } } else if (security.startsWith(SECURITY_SAE)) { wifiConfiguration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); if (preSharedKey.length() != 0) { - wifiConfiguration.preSharedKey = addQuotationIfNeeded(preSharedKey); + wifiConfiguration.preSharedKey = addQuotation(preSharedKey); } } else if (security.startsWith(SECURITY_ADB)) { - Log.i(TAG, "Specific security key: ADB"); + Log.i(TAG, "Security key: ADB, the ssid and passphrase should NOT add quotation"); + wifiConfiguration.SSID = ssid; if (preSharedKey.length() != 0) { - wifiConfiguration.preSharedKey = addQuotationIfNeeded(preSharedKey); + wifiConfiguration.preSharedKey = preSharedKey; } } else { throw new IllegalArgumentException("Unsupported security"); diff --git a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java index 435bf4fcfe..9a9f16abd0 100644 --- a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java +++ b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java @@ -152,6 +152,38 @@ public final class WifiUsabilityStatsEntry implements Parcelable { /** @see #getTimeSliceDutyCycleInPercent() */ private final int mTimeSliceDutyCycleInPercent; + private final int mWifiLinkCount; + /** Refer to WifiManager.MloMode */ + private @WifiManager.MloMode int mMloMode; + /** The number of tx bytes transmitted on current interface */ + private final long mTxTransmittedBytes; + /** The number of rx bytes transmitted on current interface */ + private final long mRxTransmittedBytes; + /** The total number of LABEL_BAD event happens */ + private final int mLabelBadEventCount; + /** The current WiFi state in framework */ + private final int mWifiFrameworkState; + /** Downstream throughput estimation provided by Network Capabilities */ + private final int mIsNetworkCapabilitiesDownstreamSufficient; + /** Upstream throughput estimation provided by Network Capabilities */ + private final int mIsNetworkCapabilitiesUpstreamSufficient; + /** Downstream throughput estimation used in Network Selection */ + private final int mIsThroughputPredictorDownstreamSufficient; + /** Upstream throughput estimation used in Network Selection */ + private final int mIsThroughputPredictorUpstreamSufficient; + /** If bluetooth is connected */ + private final boolean mIsBluetoothConnected; + /** UWB Adapter state */ + private final int mUwbAdapterState; + /** Low Latency mode state */ + private final boolean mIsLowLatencyActivated; + /** Maximum supported tx link speed in Mbps */ + private final int mMaxSupportedTxLinkSpeed; + /** Maximum supported rx link speed in Mbps */ + private final int mMaxSupportedRxLinkSpeed; + /** WiFi Voip mode state */ + private final int mVoipMode; + /** {@hide} */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"WME_ACCESS_CATEGORY_"}, value = { @@ -265,6 +297,83 @@ public final class WifiUsabilityStatsEntry implements Parcelable { } private final ContentionTimeStats[] mContentionTimeStats; + /** + * Packet statistics. + */ + /** @hide */ + public static final class PacketStats implements Parcelable { + private long mTxSuccess; + private long mTxRetries; + private long mTxBad; + private long mRxSuccess; + + public PacketStats() { + } + + /** + * Constructor function + * @param txSuccess Number of successfully transmitted unicast data pkts (ACK rcvd) + * @param txRetries Number of transmitted unicast data retry pkts + * @param txBad Number of transmitted unicast data pkt losses (no ACK) + * @param rxSuccess Number of received unicast data packets + */ + public PacketStats(long txSuccess, long txRetries, long txBad, long rxSuccess) { + this.mTxSuccess = txSuccess; + this.mTxRetries = txRetries; + this.mTxBad = txBad; + this.mRxSuccess = rxSuccess; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeLong(mTxSuccess); + dest.writeLong(mTxRetries); + dest.writeLong(mTxBad); + dest.writeLong(mRxSuccess); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<PacketStats> CREATOR = + new Creator<PacketStats>() { + public PacketStats createFromParcel(Parcel in) { + PacketStats stats = new PacketStats(); + stats.mTxSuccess = in.readLong(); + stats.mTxRetries = in.readLong(); + stats.mTxBad = in.readLong(); + stats.mRxSuccess = in.readLong(); + return stats; + } + public PacketStats[] newArray(int size) { + return new PacketStats[size]; + } + }; + + /** Number of successfully transmitted unicast data pkts (ACK rcvd) */ + public long getTxSuccess() { + return mTxSuccess; + } + + /** Number of transmitted unicast data retry pkts */ + public long getTxRetries() { + return mTxRetries; + } + + /** Number of transmitted unicast data pkt losses (no ACK) */ + public long getTxBad() { + return mTxBad; + } + + /** Number of received unicast data packets */ + public long getRxSuccess() { + return mRxSuccess; + } + } + /** {@hide} */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"WIFI_PREAMBLE_"}, value = { @@ -481,6 +590,145 @@ public final class WifiUsabilityStatsEntry implements Parcelable { private final RateStats[] mRateStats; /** + * Per peer statistics for WiFi the link + */ + /** @hide */ + public static final class PeerInfo implements Parcelable { + private int mStaCount; + private int mChanUtil; + private RateStats[] mRateStats; + + public PeerInfo() { + } + + /** + * Constructor function. + * @param staCount Station count + * @param chanUtil Channel utilization + * @param rateStats Per rate statistics on this WiFi peer + */ + public PeerInfo(int staCount, int chanUtil, RateStats[] rateStats) { + this.mStaCount = staCount; + this.mChanUtil = chanUtil; + this.mRateStats = rateStats; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mStaCount); + dest.writeInt(mChanUtil); + dest.writeTypedArray(mRateStats, flags); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<PeerInfo> CREATOR = new Creator<PeerInfo>() { + public PeerInfo createFromParcel(Parcel in) { + PeerInfo stats = new PeerInfo(); + stats.mStaCount = in.readInt(); + stats.mChanUtil = in.readInt(); + stats.mRateStats = in.createTypedArray(RateStats.CREATOR); + return stats; + } + public PeerInfo[] newArray(int size) { + return new PeerInfo[size]; + } + }; + + /** Station count */ + public int getStaCount() { + return mStaCount; + } + + /** Channel utilization */ + public int getChanUtil() { + return mChanUtil; + } + + /** Per rate statistics */ + public List<RateStats> getRateStats() { + if (mRateStats != null) { + return Arrays.asList(mRateStats); + } + return Collections.emptyList(); + } + } + + /** + * Scan Results who have the same freq with current WiFi link + */ + /** @hide */ + public static final class ScanResultWithSameFreq implements Parcelable { + private long mScanResultTimestampMicros; + private int mRssi; + private int mFrequencyMhz; + + public ScanResultWithSameFreq() { + } + + /** + * Constructor function. + * @param scanResultTimestampMicros Timestamp in microseconds (since boot) when this result + * was last seen. + * @param rssi The detected signal level in dBm + * @param frequencyMhz The center frequency of the primary 20 MHz frequency + * (in MHz) of the channel + */ + public ScanResultWithSameFreq(long scanResultTimestampMicros, int rssi, int frequencyMhz) { + this.mScanResultTimestampMicros = scanResultTimestampMicros; + this.mRssi = rssi; + this.mFrequencyMhz = frequencyMhz; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeLong(mScanResultTimestampMicros); + dest.writeInt(mRssi); + dest.writeInt(mFrequencyMhz); + } + + /** Implement the Parcelable interface */ + public static final @NonNull Creator<ScanResultWithSameFreq> CREATOR = + new Creator<ScanResultWithSameFreq>() { + public ScanResultWithSameFreq createFromParcel(Parcel in) { + ScanResultWithSameFreq scanResultWithSameFreq = + new ScanResultWithSameFreq(); + scanResultWithSameFreq.mScanResultTimestampMicros = in.readLong(); + scanResultWithSameFreq.mRssi = in.readInt(); + scanResultWithSameFreq.mFrequencyMhz = in.readInt(); + return scanResultWithSameFreq; + } + public ScanResultWithSameFreq[] newArray(int size) { + return new ScanResultWithSameFreq[size]; + } + }; + + /** timestamp in microseconds (since boot) when this result was last seen */ + public long getScanResultTimestampMicros() { + return mScanResultTimestampMicros; + } + + /** The detected signal level in dBm */ + public int getRssi() { + return mRssi; + } + + /** The center frequency of the primary 20 MHz frequency (in MHz) of the channel */ + public int getFrequency() { + return mFrequencyMhz; + } + } + + /** * Wifi link layer radio stats. */ public static final class RadioStats implements Parcelable { @@ -499,6 +747,7 @@ public final class WifiUsabilityStatsEntry implements Parcelable { private long mTotalRoamScanTimeMillis; private long mTotalPnoScanTimeMillis; private long mTotalHotspot2ScanTimeMillis; + private int[] mTxTimeMsPerLevel; /** @hide */ public RadioStats() { @@ -542,6 +791,47 @@ public final class WifiUsabilityStatsEntry implements Parcelable { this.mTotalHotspot2ScanTimeMillis = onTimeHs20Scan; } + /** + * Constructor function + * @param radioId Firmware/Hardware implementation specific persistent value for this + * device, identifying the radio interface for which the stats are produced. + * @param onTime The total time the wifi radio is on in ms counted from the last radio + * chip reset + * @param txTime The total time the wifi radio is transmitting in ms counted from the last + * radio chip reset + * @param rxTime The total time the wifi radio is receiving in ms counted from the last + * radio chip reset + * @param onTimeScan The total time spent on all types of scans in ms counted from the + * last radio chip reset + * @param onTimeNanScan The total time spent on nan scans in ms counted from the last radio + * chip reset + * @param onTimeBackgroundScan The total time spent on background scans in ms counted from + * the last radio chip reset + * @param onTimeRoamScan The total time spent on roam scans in ms counted from the last + * radio chip reset + * @param onTimePnoScan The total time spent on pno scans in ms counted from the last radio + * chip reset + * @param onTimeHs20Scan The total time spent on hotspot2.0 scans and GAS exchange in ms + * counted from the last radio chip reset + * @param txTimeMsPerLevel Time for which the radio is in active tranmission per tx level + */ + /** @hide */ + public RadioStats(int radioId, long onTime, long txTime, long rxTime, long onTimeScan, + long onTimeNanScan, long onTimeBackgroundScan, long onTimeRoamScan, + long onTimePnoScan, long onTimeHs20Scan, int[] txTimeMsPerLevel) { + this.mRadioId = radioId; + this.mTotalRadioOnTimeMillis = onTime; + this.mTotalRadioTxTimeMillis = txTime; + this.mTotalRadioRxTimeMillis = rxTime; + this.mTotalScanTimeMillis = onTimeScan; + this.mTotalNanScanTimeMillis = onTimeNanScan; + this.mTotalBackgroundScanTimeMillis = onTimeBackgroundScan; + this.mTotalRoamScanTimeMillis = onTimeRoamScan; + this.mTotalPnoScanTimeMillis = onTimePnoScan; + this.mTotalHotspot2ScanTimeMillis = onTimeHs20Scan; + this.mTxTimeMsPerLevel = txTimeMsPerLevel; + } + @Override public int describeContents() { return 0; @@ -559,6 +849,7 @@ public final class WifiUsabilityStatsEntry implements Parcelable { dest.writeLong(mTotalRoamScanTimeMillis); dest.writeLong(mTotalPnoScanTimeMillis); dest.writeLong(mTotalHotspot2ScanTimeMillis); + dest.writeIntArray(mTxTimeMsPerLevel); } /** Implement the Parcelable interface */ @@ -576,6 +867,7 @@ public final class WifiUsabilityStatsEntry implements Parcelable { stats.mTotalRoamScanTimeMillis = in.readLong(); stats.mTotalPnoScanTimeMillis = in.readLong(); stats.mTotalHotspot2ScanTimeMillis = in.readLong(); + stats.mTxTimeMsPerLevel = in.createIntArray(); return stats; } public RadioStats[] newArray(int size) { @@ -645,6 +937,13 @@ public final class WifiUsabilityStatsEntry implements Parcelable { public long getTotalHotspot2ScanTimeMillis() { return mTotalHotspot2ScanTimeMillis; } + /** + * Time for which the radio is in active tranmission per tx level + */ + /** @hide */ + public int[] getTxTimeMsPerLevel() { + return mTxTimeMsPerLevel; + } } private final RadioStats[] mRadioStats; private final int mChannelUtilizationRatio; @@ -670,6 +969,16 @@ public final class WifiUsabilityStatsEntry implements Parcelable { private final int mRadioId; /** The RSSI (in dBm) at the sample time */ private final int mRssi; + /** Frequency of the link in MHz */ + private final int mFrequencyMhz; + /** RSSI of management frames on this WiFi link */ + private final int mRssiMgmt; + /** Channel bandwidth on this WiFi link */ + @WifiChannelBandwidth private int mChannelWidth; + /** Center frequency (MHz) first segment on this WiFi link */ + private final int mCenterFreqFirstSegment; + /** Center frequency (MHz) second segment on this WiFi link */ + private final int mCenterFreqSecondSegment; /** Tx Link speed at the sample time in Mbps */ private final int mTxLinkSpeedMbps; /** Rx link speed at the sample time in Mbps */ @@ -697,6 +1006,12 @@ public final class WifiUsabilityStatsEntry implements Parcelable { private final ContentionTimeStats[] mContentionTimeStats; /** Rate information and statistics */ private final RateStats[] mRateStats; + /** Packet statistics */ + private final PacketStats[] mPacketStats; + /** Peer statistics */ + private final PeerInfo[] mPeerInfo; + /** Scan results who have the same frequency with this WiFi link */ + private final ScanResultWithSameFreq[] mScanResultsWithSameFreq; /** @hide */ public LinkStats() { @@ -704,6 +1019,11 @@ public final class WifiUsabilityStatsEntry implements Parcelable { mState = LINK_STATE_UNKNOWN; mRssi = WifiInfo.INVALID_RSSI; mRadioId = RadioStats.INVALID_RADIO_ID; + mFrequencyMhz = 0; + mRssiMgmt = 0; + mChannelWidth = WIFI_BANDWIDTH_20_MHZ; + mCenterFreqFirstSegment = 0; + mCenterFreqSecondSegment = 0; mTxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN; mRxLinkSpeedMbps = WifiInfo.LINK_SPEED_UNKNOWN; mTotalTxSuccess = 0; @@ -716,6 +1036,9 @@ public final class WifiUsabilityStatsEntry implements Parcelable { mTotalRadioOnFreqTimeMillis = 0; mContentionTimeStats = null; mRateStats = null; + mPacketStats = null; + mPeerInfo = null; + mScanResultsWithSameFreq = null; } /** @hide @@ -725,6 +1048,11 @@ public final class WifiUsabilityStatsEntry implements Parcelable { * @param radioId Identifier of the radio on which the link is operating * currently. * @param rssi Link Rssi (in dBm) at sample time. + * @param frequencyMhz Frequency of the link in MHz + * @param rssiMgmt RSSI of management frames on this WiFi link + * @param channelWidth channel width of WiFi link + * @param centerFreqFirstSegment Center frequency (MHz) of first segment + * @param centerFreqSecondSegment Center frequency (MHz) of second segment * @param txLinkSpeedMpbs Transmit link speed in Mpbs at sample time. * @param rxLinkSpeedMpbs Receive link speed in Mbps at sample time. * @param totalTxSuccess Total number of Tx success. @@ -739,16 +1067,29 @@ public final class WifiUsabilityStatsEntry implements Parcelable { * last radio chip reset. * @param contentionTimeStats Data packet contention time statistics. * @param rateStats Rate information. + * @param packetStats Packet statistics. + * @param peerInfo Peer statistics. + * @param scanResultsWithSameFreq Scan results who have the same frequency with this + * WiFi link. */ - public LinkStats(int linkId, int state, int radioId, int rssi, int txLinkSpeedMpbs, - int rxLinkSpeedMpbs, long totalTxSuccess, long totalTxRetries, long totalTxBad, - long totalRxSuccess, long totalBeaconRx, int timeSliceDutyCycleInPercent, - long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, - ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats) { + public LinkStats(int linkId, int state, int radioId, int rssi, int frequencyMhz, + int rssiMgmt, @WifiChannelBandwidth int channelWidth, int centerFreqFirstSegment, + int centerFreqSecondSegment, int txLinkSpeedMpbs, int rxLinkSpeedMpbs, + long totalTxSuccess, long totalTxRetries, long totalTxBad, long totalRxSuccess, + long totalBeaconRx, int timeSliceDutyCycleInPercent, + long totalCcaBusyFreqTimeMillis, long totalRadioOnFreqTimeMillis, + ContentionTimeStats[] contentionTimeStats, RateStats[] rateStats, + PacketStats[] packetStats, PeerInfo[] peerInfo, + ScanResultWithSameFreq[] scanResultsWithSameFreq) { this.mLinkId = linkId; this.mState = state; this.mRadioId = radioId; this.mRssi = rssi; + this.mFrequencyMhz = frequencyMhz; + this.mRssiMgmt = rssiMgmt; + this.mChannelWidth = channelWidth; + this.mCenterFreqFirstSegment = centerFreqFirstSegment; + this.mCenterFreqSecondSegment = centerFreqSecondSegment; this.mTxLinkSpeedMbps = txLinkSpeedMpbs; this.mRxLinkSpeedMbps = rxLinkSpeedMpbs; this.mTotalTxSuccess = totalTxSuccess; @@ -761,6 +1102,9 @@ public final class WifiUsabilityStatsEntry implements Parcelable { this.mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis; this.mContentionTimeStats = contentionTimeStats; this.mRateStats = rateStats; + this.mPacketStats = packetStats; + this.mPeerInfo = peerInfo; + this.mScanResultsWithSameFreq = scanResultsWithSameFreq; } @Override @@ -774,6 +1118,11 @@ public final class WifiUsabilityStatsEntry implements Parcelable { dest.writeInt(mState); dest.writeInt(mRadioId); dest.writeInt(mRssi); + dest.writeInt(mFrequencyMhz); + dest.writeInt(mRssiMgmt); + dest.writeInt(mChannelWidth); + dest.writeInt(mCenterFreqFirstSegment); + dest.writeInt(mCenterFreqSecondSegment); dest.writeInt(mTxLinkSpeedMbps); dest.writeInt(mRxLinkSpeedMbps); dest.writeLong(mTotalTxSuccess); @@ -786,6 +1135,9 @@ public final class WifiUsabilityStatsEntry implements Parcelable { dest.writeLong(mTotalRadioOnFreqTimeMillis); dest.writeTypedArray(mContentionTimeStats, flags); dest.writeTypedArray(mRateStats, flags); + dest.writeTypedArray(mPacketStats, flags); + dest.writeTypedArray(mPeerInfo, flags); + dest.writeTypedArray(mScanResultsWithSameFreq, flags); } /** Implement the Parcelable interface */ @@ -794,11 +1146,15 @@ public final class WifiUsabilityStatsEntry implements Parcelable { new Creator<>() { public LinkStats createFromParcel(Parcel in) { return new LinkStats(in.readInt(), in.readInt(), in.readInt(), in.readInt(), - in.readInt(), in.readInt(), in.readLong(), in.readLong(), - in.readLong(), in.readLong(), in.readLong(), in.readInt(), - in.readLong(), in.readLong(), + in.readInt(), in.readInt(), in.readInt(), in.readInt(), + in.readInt(), in.readInt(), in.readInt(), in.readLong(), + in.readLong(), in.readLong(), in.readLong(), in.readLong(), + in.readInt(), in.readLong(), in.readLong(), in.createTypedArray(ContentionTimeStats.CREATOR), - in.createTypedArray(RateStats.CREATOR)); + in.createTypedArray(RateStats.CREATOR), + in.createTypedArray(PacketStats.CREATOR), + in.createTypedArray(PeerInfo.CREATOR), + in.createTypedArray(ScanResultWithSameFreq.CREATOR)); } public LinkStats[] newArray(int size) { @@ -826,7 +1182,15 @@ public final class WifiUsabilityStatsEntry implements Parcelable { boolean isThroughputSufficient, boolean isWifiScoringEnabled, boolean isCellularDataAvailable, @NetworkType int cellularDataNetworkType, int cellularSignalStrengthDbm, int cellularSignalStrengthDb, - boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats) { + boolean isSameRegisteredCell, SparseArray<LinkStats> linkStats, + int wifiLinkCount, @WifiManager.MloMode int mloMode, + long txTransmittedBytes, long rxTransmittedBytes, int labelBadEventCount, + int wifiFrameworkState, int isNetworkCapabilitiesDownstreamSufficient, + int isNetworkCapabilitiesUpstreamSufficient, + int isThroughputPredictorDownstreamSufficient, + int isThroughputPredictorUpstreamSufficient, boolean isBluetoothConnected, + int uwbAdapterState, boolean isLowLatencyActivated, int maxSupportedTxLinkSpeed, + int maxSupportedRxLinkSpeed, int voipMode) { mTimeStampMillis = timeStampMillis; mRssi = rssi; mLinkSpeedMbps = linkSpeedMbps; @@ -863,6 +1227,22 @@ public final class WifiUsabilityStatsEntry implements Parcelable { mCellularSignalStrengthDb = cellularSignalStrengthDb; mIsSameRegisteredCell = isSameRegisteredCell; mLinkStats = linkStats; + mWifiLinkCount = wifiLinkCount; + mMloMode = mloMode; + mTxTransmittedBytes = txTransmittedBytes; + mRxTransmittedBytes = rxTransmittedBytes; + mLabelBadEventCount = labelBadEventCount; + mWifiFrameworkState = wifiFrameworkState; + mIsNetworkCapabilitiesDownstreamSufficient = isNetworkCapabilitiesDownstreamSufficient; + mIsNetworkCapabilitiesUpstreamSufficient = isNetworkCapabilitiesUpstreamSufficient; + mIsThroughputPredictorDownstreamSufficient = isThroughputPredictorDownstreamSufficient; + mIsThroughputPredictorUpstreamSufficient = isThroughputPredictorUpstreamSufficient; + mIsBluetoothConnected = isBluetoothConnected; + mUwbAdapterState = uwbAdapterState; + mIsLowLatencyActivated = isLowLatencyActivated; + mMaxSupportedTxLinkSpeed = maxSupportedTxLinkSpeed; + mMaxSupportedRxLinkSpeed = maxSupportedRxLinkSpeed; + mVoipMode = voipMode; } /** Implement the Parcelable interface */ @@ -908,6 +1288,22 @@ public final class WifiUsabilityStatsEntry implements Parcelable { dest.writeInt(mCellularSignalStrengthDb); dest.writeBoolean(mIsSameRegisteredCell); dest.writeSparseArray(mLinkStats); + dest.writeInt(mWifiLinkCount); + dest.writeInt(mMloMode); + dest.writeLong(mTxTransmittedBytes); + dest.writeLong(mRxTransmittedBytes); + dest.writeInt(mLabelBadEventCount); + dest.writeInt(mWifiFrameworkState); + dest.writeInt(mIsNetworkCapabilitiesDownstreamSufficient); + dest.writeInt(mIsNetworkCapabilitiesUpstreamSufficient); + dest.writeInt(mIsThroughputPredictorDownstreamSufficient); + dest.writeInt(mIsThroughputPredictorUpstreamSufficient); + dest.writeBoolean(mIsBluetoothConnected); + dest.writeInt(mUwbAdapterState); + dest.writeBoolean(mIsLowLatencyActivated); + dest.writeInt(mMaxSupportedTxLinkSpeed); + dest.writeInt(mMaxSupportedRxLinkSpeed); + dest.writeInt(mVoipMode); } /** Implement the Parcelable interface */ @@ -929,7 +1325,10 @@ public final class WifiUsabilityStatsEntry implements Parcelable { in.readInt(), in.readBoolean(), in.readBoolean(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(), in.readBoolean(), - in.readSparseArray(LinkStats.class.getClassLoader()) + in.readSparseArray(LinkStats.class.getClassLoader()), in.readInt(), + in.readInt(), in.readLong(), in.readLong(), in.readInt(), in.readInt(), + in.readInt(), in.readInt(), in.readInt(), in.readInt(), in.readBoolean(), + in.readInt(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt() ); } @@ -1003,6 +1402,77 @@ public final class WifiUsabilityStatsEntry implements Parcelable { throw new NoSuchElementException("linkId is invalid - " + linkId); } + /** + * Get frequency of specific WiFi link + * + * @param linkId Identifier of the link. + * @return Frequency in Mhz + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + public int getFrequencyMhz(int linkId) { + if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mFrequencyMhz; + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Get RSSI of management frames on this WiFi link + * + * @param linkId Identifier of the link. + * @return RSSI of management frames on this WiFi link + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + public int getRssiMgmt(int linkId) { + if (mLinkStats.contains(linkId)) return mLinkStats.get(linkId).mRssiMgmt; + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Get channel width of this WiFi link + * + * @param linkId Identifier of the link. + * @return channel width of this WiFi link + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + public int getChannelWidth(int linkId) { + if (mLinkStats.contains(linkId)) { + return mLinkStats.get(linkId).mChannelWidth; + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Get center frequency (MHz) of first segment of this WiFi link + * + * @param linkId Identifier of the link. + * @return center frequency (MHz) of first segment of this WiFi link + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + public int getCenterFreqFirstSegment(int linkId) { + if (mLinkStats.contains(linkId)) { + return mLinkStats.get(linkId).mCenterFreqFirstSegment; + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Get center frequency (MHz) of second segment of this WiFi link + * + * @param linkId Identifier of the link. + * @return center frequency (MHz) of second segment of this WiFi link + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + public int getCenterFreqSecondSegment(int linkId) { + if (mLinkStats.contains(linkId)) { + return mLinkStats.get(linkId).mCenterFreqSecondSegment; + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + /** Link speed at the sample time in Mbps. In case of Multi Link Operation (MLO), returned value * is the current link speed of the associated link with the highest RSSI. * @@ -1356,6 +1826,30 @@ public final class WifiUsabilityStatsEntry implements Parcelable { } /** + * Packet statistics of a WiFi link for Access Category. + * + * @param linkId Identifier of the link. + * @param ac The access category, see {@link WmeAccessCategory}. + * @return The packet statistics, see {@link PacketStats}. + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + @NonNull + public PacketStats getPacketStats(int linkId, @WmeAccessCategory int ac) { + if (!mLinkStats.contains(linkId)) { + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + PacketStats[] linkPacketStats = mLinkStats.get( + linkId).mPacketStats; + if (linkPacketStats != null + && linkPacketStats.length == NUM_WME_ACCESS_CATEGORIES) { + return linkPacketStats[ac]; + } + Log.e(TAG, "The PacketStats is not filled out correctly"); + return new PacketStats(); + } + + /** * Rate information and statistics, which are ordered by preamble, modulation and coding scheme * (MCS), and number of spatial streams (NSS). In case of Multi Link Operation (MLO), the * returned rate information is that of the associated link with the highest RSSI. @@ -1407,6 +1901,73 @@ public final class WifiUsabilityStatsEntry implements Parcelable { } /** + * Rate information and statistics, which are ordered by preamble, modulation and coding scheme + * (MCS), and number of spatial streams (NSS) for WiFi peer. + * + * @param linkId Identifier of the link. + * @param peerIndex Identifier of PeerInfo. + * @return A list of rate statistics in the form of a list of {@link RateStats} objects. + * Depending on the link type, the list is created following the order of: + * - HT (IEEE Std 802.11-2020, Section 19): LEGACY rates (1Mbps, ..., 54Mbps), + * HT MCS0, ..., MCS15; + * - VHT (IEEE Std 802.11-2020, Section 21): LEGACY rates (1Mbps, ..., 54Mbps), + * VHT MCS0/NSS1, ..., VHT MCS11/NSS1, VHT MCSO/NSS2, ..., VHT MCS11/NSS2; + * - HE (IEEE Std 802.11ax-2020, Section 27): LEGACY rates (1Mbps, ..., 54Mbps), + * HE MCS0/NSS1, ..., HE MCS11/NSS1, HE MCSO/NSS2, ..., HE MCS11/NSS2. + * - EHT (IEEE std 802.11be-2021, Section 36): Legacy rates (1Mbps, ..., 54Mbps), + * EHT MSC0/NSS1, ..., EHT MCS14/NSS1, EHT MCS0/NSS2, ..., EHT MCS14/NSS2. + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + @NonNull + public List<RateStats> getRateStats(int linkId, int peerIndex) { + if (mLinkStats.contains(linkId)) { + if (getPeerInfo(linkId).size() > 0 && peerIndex < getPeerInfo(linkId).size()) { + RateStats[] rateStats = mLinkStats.get(linkId).mPeerInfo[peerIndex].mRateStats; + if (rateStats != null) return Arrays.asList(rateStats); + } + return Collections.emptyList(); + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Peer information and statistics + * + * @param linkId Identifier of the link. + * @return A list of peer statistics in the form of a list of {@link PeerInfo} objects. + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + @NonNull + public List<PeerInfo> getPeerInfo(int linkId) { + if (mLinkStats.contains(linkId)) { + PeerInfo[] peerInfo = mLinkStats.get(linkId).mPeerInfo; + if (peerInfo != null) return Arrays.asList(peerInfo); + return Collections.emptyList(); + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** + * Scan results who have the same frequency with this WiFi link + * + * @param linkId Identifier of the link. + * @return An array of Scan results who have the same frequency with this WiFi link + * @throws NoSuchElementException if linkId is invalid. + */ + /** @hide */ + @NonNull + public ScanResultWithSameFreq[] getScanResultsWithSameFreq(int linkId) { + if (mLinkStats.contains(linkId)) { + ScanResultWithSameFreq[] scanResultsWithSameFreq = + mLinkStats.get(linkId).mScanResultsWithSameFreq; + return scanResultsWithSameFreq; + } + throw new NoSuchElementException("linkId is invalid - " + linkId); + } + + /** * Radio stats from all the radios, see {@link RadioStats#getRadioId()} * @return A list of Wifi link layer radio stats, see {@link RadioStats} */ @@ -1485,4 +2046,84 @@ public final class WifiUsabilityStatsEntry implements Parcelable { public boolean isSameRegisteredCell() { return mIsSameRegisteredCell; } + + /** @hide */ + public int getWifiLinkCount() { + return mWifiLinkCount; + } + + /** @hide */ + public int getMloMode() { + return mMloMode; + } + + /** @hide */ + public long getTxTransmittedBytes() { + return mTxTransmittedBytes; + } + + /** @hide */ + public long getRxTransmittedBytes() { + return mRxTransmittedBytes; + } + + /** @hide */ + public long getLabelBadEventCount() { + return mLabelBadEventCount; + } + + /** @hide */ + public int getWifiFrameworkState() { + return mWifiFrameworkState; + } + + /** @hide */ + public int isNetworkCapabilitiesDownstreamSufficient() { + return mIsNetworkCapabilitiesDownstreamSufficient; + } + + /** @hide */ + public int isNetworkCapabilitiesUpstreamSufficient() { + return mIsNetworkCapabilitiesUpstreamSufficient; + } + + /** @hide */ + public int isThroughputPredictorDownstreamSufficient() { + return mIsThroughputPredictorDownstreamSufficient; + } + + /** @hide */ + public int isThroughputPredictorUpstreamSufficient() { + return mIsThroughputPredictorUpstreamSufficient; + } + + /** @hide */ + public boolean isBluetoothConnected() { + return mIsBluetoothConnected; + } + + /** @hide */ + public int getUwbAdapterState() { + return mUwbAdapterState; + } + + /** @hide */ + public boolean getLowLatencyModeState() { + return mIsLowLatencyActivated; + } + + /** @hide */ + public int getMaxSupportedTxLinkSpeed() { + return mMaxSupportedTxLinkSpeed; + } + + /** @hide */ + public int getMaxSupportedRxLinkSpeed() { + return mMaxSupportedRxLinkSpeed; + } + + /** @hide */ + public int getVoipMode() { + return mVoipMode; + } } diff --git a/framework/java/android/net/wifi/aware/AwarePairingConfig.java b/framework/java/android/net/wifi/aware/AwarePairingConfig.java index f37174aee2..f677e10271 100644 --- a/framework/java/android/net/wifi/aware/AwarePairingConfig.java +++ b/framework/java/android/net/wifi/aware/AwarePairingConfig.java @@ -16,11 +16,16 @@ package android.net.wifi.aware; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import com.android.wifi.flags.Flags; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -73,6 +78,11 @@ public final class AwarePairingConfig implements Parcelable { * Aware Pairing bootstrapping method NFC reader */ public static final int PAIRING_BOOTSTRAPPING_NFC_READER = 1 << 8; + /** + * This is used for the boundary check and should be the max value of the bitmap + 1. + * @hide + */ + public static final int PAIRING_BOOTSTRAPPING_MAX = 1 << 9; /** @hide */ @@ -96,6 +106,7 @@ public final class AwarePairingConfig implements Parcelable { private final boolean mPairingCache; private final boolean mPairingVerification; private final int mBootstrappingMethods; + private final int mCipherSuites; /** * Check if the NPK/NIK cache is support in the config @@ -129,6 +140,29 @@ public final class AwarePairingConfig implements Parcelable { return mBootstrappingMethods; } + /** + * Get the supported cipher suites in this config. + */ + @FlaggedApi(Flags.FLAG_AWARE_PAIRING) + @Characteristics.WifiAwarePairingCipherSuites + public int getSupportedCipherSuites() { + return mCipherSuites; + } + + /** + * Verifies that the contents of the AwarePairingConfig are valid + * @hide + */ + public boolean assertValid(Characteristics characteristics) { + if (mBootstrappingMethods < 0 || mBootstrappingMethods >= PAIRING_BOOTSTRAPPING_MAX) { + return false; + } + if ((characteristics.getSupportedPairingCipherSuites() & mCipherSuites) == 0) { + return false; + } + return true; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -136,21 +170,24 @@ public final class AwarePairingConfig implements Parcelable { AwarePairingConfig that = (AwarePairingConfig) o; return mPairingSetup == that.mPairingSetup && mPairingCache == that.mPairingCache && mPairingVerification == that.mPairingVerification - && mBootstrappingMethods == that.mBootstrappingMethods; + && mBootstrappingMethods == that.mBootstrappingMethods + && mCipherSuites == that.mCipherSuites; } @Override public int hashCode() { return Objects.hash(mPairingSetup, mPairingCache, mPairingVerification, - mBootstrappingMethods); + mBootstrappingMethods, mCipherSuites); } /** @hide */ - public AwarePairingConfig(boolean setup, boolean cache, boolean verification, int method) { + public AwarePairingConfig(boolean setup, boolean cache, boolean verification, int method, + int cipherSuites) { mPairingSetup = setup; mPairingCache = cache; mPairingVerification = verification; mBootstrappingMethods = method; + mCipherSuites = cipherSuites; } /** @hide */ @@ -159,6 +196,7 @@ public final class AwarePairingConfig implements Parcelable { mPairingCache = in.readBoolean(); mPairingVerification = in.readBoolean(); mBootstrappingMethods = in.readInt(); + mCipherSuites = in.readInt(); } @Override @@ -167,6 +205,7 @@ public final class AwarePairingConfig implements Parcelable { dest.writeBoolean(mPairingCache); dest.writeBoolean(mPairingVerification); dest.writeInt(mBootstrappingMethods); + dest.writeInt(mCipherSuites); } @Override @@ -194,6 +233,7 @@ public final class AwarePairingConfig implements Parcelable { private boolean mPairingCache = false; private boolean mPairingVerification = false; private int mBootStrappingMethods = 0; + private int mCipherSuites = WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128; /** * Set whether enable the Aware Pairing setup @@ -238,13 +278,26 @@ public final class AwarePairingConfig implements Parcelable { } /** + * Set the supported cipher suites. If not set, default will be + * {@link Characteristics#WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128} + * @param cipherSuites cipher suites supported + * @return the current {@link Builder} builder, enabling chaining of builder methods. + */ + @FlaggedApi(Flags.FLAG_AWARE_PAIRING) + @NonNull public Builder setSupportedCipherSuites( + @Characteristics.WifiAwarePairingCipherSuites int cipherSuites) { + mCipherSuites = cipherSuites; + return this; + } + + /** * Build {@link AwarePairingConfig} given the current requests made on the * builder. */ @NonNull public AwarePairingConfig build() { return new AwarePairingConfig(mPairingSetup, mPairingCache, mPairingVerification, - mBootStrappingMethods); + mBootStrappingMethods, mCipherSuites); } } } diff --git a/framework/java/android/net/wifi/aware/PublishConfig.java b/framework/java/android/net/wifi/aware/PublishConfig.java index aa43cdbb99..b429fac63d 100644 --- a/framework/java/android/net/wifi/aware/PublishConfig.java +++ b/framework/java/android/net/wifi/aware/PublishConfig.java @@ -302,6 +302,9 @@ public final class PublishConfig implements Parcelable { if (mPairingConfig != null && !characteristics.isAwarePairingSupported()) { throw new IllegalArgumentException("Aware Pairing is not supported"); } + if (mPairingConfig != null && !mPairingConfig.assertValid(characteristics)) { + throw new IllegalArgumentException("Unsupported pairing config"); + } } if (!rttSupported && mEnableRanging) { diff --git a/framework/java/android/net/wifi/rtt/RangingResult.java b/framework/java/android/net/wifi/rtt/RangingResult.java index 87b1ed9af3..6739291929 100644 --- a/framework/java/android/net/wifi/rtt/RangingResult.java +++ b/framework/java/android/net/wifi/rtt/RangingResult.java @@ -1009,13 +1009,13 @@ public final class RangingResult implements Parcelable { .append(mIs80211mcMeasurement) .append(", frequencyMHz=").append(mFrequencyMHz) .append(", packetBw=").append(mPacketBw) - .append("is80211azNtbMeasurement").append(mIs80211azNtbMeasurement) - .append("ntbMinMeasurementTime").append(mNtbMinMeasurementTime) - .append("ntbMaxMeasurementTime").append(mNtbMaxMeasurementTime) - .append("i2rTxLtfRepetitions").append(mI2rTxLtfRepetitions) - .append("r2iTxLtfRepetitions").append(mR2iTxLtfRepetitions) - .append("txSpatialStreams").append(mNumTxSpatialStreams) - .append("rxSpatialStreams").append(mNumRxSpatialStreams) + .append(", is80211azNtbMeasurement=").append(mIs80211azNtbMeasurement) + .append(", ntbMinMeasurementTimeMicros=").append(mNtbMinMeasurementTime) + .append(", ntbMaxMeasurementTimeMicros=").append(mNtbMaxMeasurementTime) + .append(", i2rTxLtfRepetitions=").append(mI2rTxLtfRepetitions) + .append(", r2iTxLtfRepetitions=").append(mR2iTxLtfRepetitions) + .append(", numTxSpatialStreams=").append(mNumTxSpatialStreams) + .append(", numRxSpatialStreams=").append(mNumRxSpatialStreams) .append(", vendorData=").append(mVendorData) .append("]").toString(); } diff --git a/framework/java/android/net/wifi/util/Environment.java b/framework/java/android/net/wifi/util/Environment.java index f2e8266ed9..f98265845a 100644 --- a/framework/java/android/net/wifi/util/Environment.java +++ b/framework/java/android/net/wifi/util/Environment.java @@ -90,4 +90,13 @@ public class Environment { } return vndkApiLevel > apiLevel; } + + /** + * Check if the device has a SDK >= 36 + * @return True if the SDK >= 36 + */ + public static boolean isSdkAtLeastB() { + return Build.VERSION.CODENAME.equals("Baklava") + || Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA; + } } diff --git a/framework/java/android/net/wifi/util/ScanResultUtil.java b/framework/java/android/net/wifi/util/ScanResultUtil.java index 9851957ffc..ca8d62b3d3 100644 --- a/framework/java/android/net/wifi/util/ScanResultUtil.java +++ b/framework/java/android/net/wifi/util/ScanResultUtil.java @@ -464,9 +464,10 @@ public class ScanResultUtil { } else { rssiInfo = String.format("%9d ", r.level); } + String capabilities = r.capabilities; if ((r.flags & FLAG_PASSPOINT_NETWORK) == FLAG_PASSPOINT_NETWORK) { - r.capabilities += "[PASSPOINT]"; + capabilities += "[PASSPOINT]"; } pw.printf(" %17s %9d %18s %7s %-32s %s\n", r.BSSID, @@ -474,7 +475,7 @@ public class ScanResultUtil { rssiInfo, age, String.format("%1.32s", ssid), - r.capabilities); + capabilities); } } } diff --git a/framework/java/android/net/wifi/util/WifiResourceCache.java b/framework/java/android/net/wifi/util/WifiResourceCache.java index 89d7cb964a..1d987d3fb4 100644 --- a/framework/java/android/net/wifi/util/WifiResourceCache.java +++ b/framework/java/android/net/wifi/util/WifiResourceCache.java @@ -19,7 +19,9 @@ package android.net.wifi.util; import android.content.Context; import java.io.PrintWriter; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -27,31 +29,150 @@ import java.util.Map; * @hide */ public class WifiResourceCache { + private static final String TAG = "WifiResourceCache"; private final Context mContext; - private final Map<String, Boolean> mBooleanResourceMap; - private final Map<String, Integer> mIntegerResourceMap; + private final Map<Integer, Boolean> mBooleanResourceMap; + private final Map<Integer, Integer> mIntegerResourceMap; + private final Map<Integer, String> mStringResourceMap; + private final Map<Integer, String[]> mStringArrayResourceMap; + private final Map<Integer, int[]> mIntArrayResourceMap; + private final List<Map> mValueMapList; + private final Map<String, Integer> mResourceNameMap; + + private int mTempId = -1; + private final Object mLock = new Object(); public WifiResourceCache(Context context) { mContext = context; mBooleanResourceMap = new HashMap<>(); mIntegerResourceMap = new HashMap<>(); + mStringArrayResourceMap = new HashMap<>(); + mIntArrayResourceMap = new HashMap<>(); + mStringResourceMap = new HashMap<>(); + mValueMapList = List.of(mBooleanResourceMap, mIntegerResourceMap, mIntArrayResourceMap, + mStringArrayResourceMap, mStringResourceMap); + mResourceNameMap = new HashMap<>(); } /** * Get and cache the boolean value as {@link android.content.res.Resources#getBoolean(int)} */ - public boolean getBoolean(int resourceId, String resourceName) { - return mBooleanResourceMap.computeIfAbsent(resourceName, - v -> mContext.getResources().getBoolean(resourceId)); + public boolean getBoolean(int resourceId) { + synchronized (mLock) { + if (mBooleanResourceMap.containsKey(resourceId)) { + return mBooleanResourceMap.get(resourceId); + } + + String resourceName = mContext.getResources().getResourceEntryName(resourceId); + if (mResourceNameMap.containsKey(resourceName)) { + int tempId = mResourceNameMap.get(resourceName); + boolean value = mBooleanResourceMap.get(tempId); + mBooleanResourceMap.put(resourceId, value); + mBooleanResourceMap.remove(tempId); + mResourceNameMap.put(resourceName, resourceId); + return value; + } + mResourceNameMap.put(resourceName, resourceId); + return mBooleanResourceMap.computeIfAbsent(resourceId, + v -> mContext.getResources().getBoolean(resourceId)); + } } /** * Get and cache the integer value as {@link android.content.res.Resources#getInteger(int)} */ - public int getInteger(int resourceId, String resourceName) { - return mIntegerResourceMap.computeIfAbsent(resourceName, - v -> mContext.getResources().getInteger(resourceId)); + public int getInteger(int resourceId) { + synchronized (mLock) { + if (mIntegerResourceMap.containsKey(resourceId)) { + return mIntegerResourceMap.get(resourceId); + } + + String resourceName = mContext.getResources().getResourceEntryName(resourceId); + if (mResourceNameMap.containsKey(resourceName)) { + int tempId = mResourceNameMap.get(resourceName); + int value = mIntegerResourceMap.get(tempId); + mIntegerResourceMap.put(resourceId, value); + mIntegerResourceMap.remove(tempId); + mResourceNameMap.put(resourceName, resourceId); + return value; + } + mResourceNameMap.put(resourceName, resourceId); + return mIntegerResourceMap.computeIfAbsent(resourceId, + v -> mContext.getResources().getInteger(resourceId)); + } + } + + /** + * Get and cache the integer value as {@link android.content.res.Resources#getString(int)} + */ + public String getString(int resourceId) { + synchronized (mLock) { + if (mStringResourceMap.containsKey(resourceId)) { + return mStringResourceMap.get(resourceId); + } + + String resourceName = mContext.getResources().getResourceEntryName(resourceId); + if (mResourceNameMap.containsKey(resourceName)) { + int tempId = mResourceNameMap.get(resourceName); + String value = mStringResourceMap.get(tempId); + mStringResourceMap.put(resourceId, value); + mStringResourceMap.remove(tempId); + mResourceNameMap.put(resourceName, resourceId); + return value; + } + mResourceNameMap.put(resourceName, resourceId); + return mStringResourceMap.computeIfAbsent(resourceId, + v -> mContext.getResources().getString(resourceId)); + } + } + + /** + * Get and cache the integer value as {@link android.content.res.Resources#getStringArray(int)} + */ + public String[] getStringArray(int resourceId) { + synchronized (mLock) { + if (mStringArrayResourceMap.containsKey(resourceId)) { + return mStringArrayResourceMap.get(resourceId); + } + + String resourceName = mContext.getResources().getResourceEntryName(resourceId); + if (mResourceNameMap.containsKey(resourceName)) { + int tempId = mResourceNameMap.get(resourceName); + String[] value = mStringArrayResourceMap.get(tempId); + mStringArrayResourceMap.put(resourceId, value); + mStringArrayResourceMap.remove(tempId); + mResourceNameMap.put(resourceName, resourceId); + return value; + } + mResourceNameMap.put(resourceName, resourceId); + return mStringArrayResourceMap.computeIfAbsent(resourceId, + v -> mContext.getResources().getStringArray(resourceId)); + } + } + + /** + * Get and cache the integer value as {@link android.content.res.Resources#getIntArray(int)} + */ + public int[] getIntArray(int resourceId) { + synchronized (mLock) { + if (mIntArrayResourceMap.containsKey(resourceId)) { + return mIntArrayResourceMap.get(resourceId); + } + + String resourceName = mContext.getResources().getResourceEntryName(resourceId); + if (mResourceNameMap.containsKey(resourceName)) { + int tempId = mResourceNameMap.get(resourceName); + int[] value = mIntArrayResourceMap.get(tempId); + mIntArrayResourceMap.put(resourceId, value); + mIntArrayResourceMap.remove(tempId); + mResourceNameMap.put(resourceName, resourceId); + return value; + } + mResourceNameMap.put(resourceName, resourceId); + return mIntArrayResourceMap.computeIfAbsent(resourceId, + v -> mContext.getResources().getIntArray(resourceId)); + } } /** @@ -61,14 +182,19 @@ public class WifiResourceCache { * @param value override to this value */ public void overrideBooleanValue(String resourceName, boolean value) { - mBooleanResourceMap.put(resourceName, value); + synchronized (mLock) { + int resourceId = mResourceNameMap.computeIfAbsent(resourceName, v -> mTempId--); + mBooleanResourceMap.put(resourceId, value); + } } /** * Override the target boolean value */ public void restoreBooleanValue(String resourceName) { - mBooleanResourceMap.remove(resourceName); + synchronized (mLock) { + mBooleanResourceMap.remove(mResourceNameMap.remove(resourceName)); + } } /** @@ -77,14 +203,82 @@ public class WifiResourceCache { * @param value override to this value */ public void overrideIntegerValue(String resourceName, int value) { - mIntegerResourceMap.put(resourceName, value); + synchronized (mLock) { + int resourceId = mResourceNameMap.computeIfAbsent(resourceName, v -> mTempId--); + mIntegerResourceMap.put(resourceId, value); + } } /** * Override the target integer value */ public void restoreIntegerValue(String resourceName) { - mIntegerResourceMap.remove(resourceName); + synchronized (mLock) { + mIntegerResourceMap.remove(mResourceNameMap.remove(resourceName)); + } + } + + /** + * Override the target String value + * @param resourceName the resource overlay name + * @param value override to this value + */ + public void overrideStringValue(String resourceName, String value) { + synchronized (mLock) { + int resourceId = mResourceNameMap.computeIfAbsent(resourceName, v -> mTempId--); + mStringResourceMap.put(resourceId, value); + } + } + + /** + * Override the target integer value + */ + public void restoreStringValue(String resourceName) { + synchronized (mLock) { + mStringResourceMap.remove(mResourceNameMap.remove(resourceName)); + } + } + + /** + * Override the target string array value + * @param resourceName the resource overlay name + * @param value override to this value + */ + public void overrideStringArrayValue(String resourceName, String[] value) { + synchronized (mLock) { + int resourceId = mResourceNameMap.computeIfAbsent(resourceName, v -> mTempId--); + mStringArrayResourceMap.put(resourceId, value); + } + } + + /** + * Override the target string array value + */ + public void restoreStringArrayValue(String resourceName) { + synchronized (mLock) { + mStringArrayResourceMap.remove(mResourceNameMap.remove(resourceName)); + } + } + + /** + * Override the target int array value + * @param resourceName the resource overlay name + * @param value override to this value + */ + public void overrideIntArrayValue(String resourceName, int[] value) { + synchronized (mLock) { + int resourceId = mResourceNameMap.computeIfAbsent(resourceName, v -> mTempId--); + mIntArrayResourceMap.put(resourceId, value); + } + } + + /** + * Override the target int array value + */ + public void restoreIntArrayValue(String resourceName) { + synchronized (mLock) { + mIntArrayResourceMap.remove(mResourceNameMap.remove(resourceName)); + } } /** @@ -93,23 +287,36 @@ public class WifiResourceCache { public void dump(PrintWriter pw) { pw.println("Dump of WifiResourceCache"); pw.println("WifiResourceCache - resource value Begin ----"); - - for (Map.Entry<String, Integer> resourceEntry : mIntegerResourceMap.entrySet()) { - pw.println("Resource Name: " + resourceEntry.getKey() - + ", value: " + resourceEntry.getValue()); - } - for (Map.Entry<String, Boolean> resourceEntry : mBooleanResourceMap.entrySet()) { - pw.println("Resource Name: " + resourceEntry.getKey() - + ", value: " + resourceEntry.getValue()); + synchronized (mLock) { + for (Map.Entry<String, Integer> resourceEntry : mResourceNameMap.entrySet()) { + for (Map m : mValueMapList) { + if (m.containsKey(resourceEntry.getValue())) { + pw.println("Resource Name: " + resourceEntry.getKey() + + ", value: " + valueToString(m.get(resourceEntry.getValue()))); + break; + } + } + } } pw.println("WifiResourceCache - resource value End ----"); } + private String valueToString(Object input) { + if (input instanceof Object[]) { + return Arrays.deepToString((Object[]) input); + } + return input.toString(); + } + /** * Remove all override value and set to default */ public void reset() { - mBooleanResourceMap.clear(); - mIntegerResourceMap.clear(); + synchronized (mLock) { + for (Map m : mValueMapList) { + m.clear(); + } + mResourceNameMap.clear(); + } } } diff --git a/framework/lint-baseline.xml b/framework/lint-baseline.xml index 55c4cfc6c5..a65baa655a 100644 --- a/framework/lint-baseline.xml +++ b/framework/lint-baseline.xml @@ -822,7 +822,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="6786" + line="6800" column="17"/> </issue> @@ -833,7 +833,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="8075" + line="8089" column="37"/> </issue> @@ -844,7 +844,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="8082" + line="8096" column="37"/> </issue> @@ -855,7 +855,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="8089" + line="8103" column="37"/> </issue> @@ -866,7 +866,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="12607" + line="12652" column="37"/> </issue> @@ -877,7 +877,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="12617" + line="12662" column="37"/> </issue> @@ -888,7 +888,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/WifiManager.java" - line="12630" + line="12675" column="37"/> </issue> @@ -921,7 +921,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pGroup.java" - line="456" + line="468" column="47"/> </issue> @@ -932,40 +932,40 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pGroup.java" - line="496" + line="508" column="21"/> </issue> <issue id="FlaggedApi" - message="Method `onStateChanged()` is a flagged API and should be inside an `if (Flags.androidVWifiApi())` check (or annotate the surrounding method `onStateChanged` with `@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) to transfer requirement to caller`)" - errorLine1=" mExecutor.execute(() -> mListener.onStateChanged(p2pEnabled));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + message="Method `onP2pStateChanged()` is a flagged API and should be inside an `if (Flags.androidVWifiApi())` check (or annotate the surrounding method `onP2pStateChanged` with `@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) to transfer requirement to caller`)" + errorLine1=" mExecutor.execute(() -> mListener.onP2pStateChanged(state));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1423" + line="1484" column="37"/> </issue> <issue id="FlaggedApi" message="Method `onDiscoveryStateChanged()` is a flagged API and should be inside an `if (Flags.androidVWifiApi())` check (or annotate the surrounding method `onDiscoveryStateChanged` with `@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) to transfer requirement to caller`)" - errorLine1=" mExecutor.execute(() -> mListener.onDiscoveryStateChanged(started));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" mExecutor.execute(() -> mListener.onDiscoveryStateChanged(state));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1429" + line="1490" column="37"/> </issue> <issue id="FlaggedApi" message="Method `onListenStateChanged()` is a flagged API and should be inside an `if (Flags.androidVWifiApi())` check (or annotate the surrounding method `onListenStateChanged` with `@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) to transfer requirement to caller`)" - errorLine1=" mExecutor.execute(() -> mListener.onListenStateChanged(started));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" mExecutor.execute(() -> mListener.onListenStateChanged(state));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1435" + line="1496" column="37"/> </issue> @@ -976,7 +976,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1441" + line="1502" column="37"/> </issue> @@ -987,7 +987,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1447" + line="1508" column="37"/> </issue> @@ -998,7 +998,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1453" + line="1514" column="37"/> </issue> @@ -1009,7 +1009,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1459" + line="1520" column="37"/> </issue> @@ -1020,18 +1020,18 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1465" + line="1526" column="37"/> </issue> <issue id="FlaggedApi" message="Method `onGroupCreationFailed()` is a flagged API and should be inside an `if (Flags.androidVWifiApi())` check (or annotate the surrounding method `onGroupCreationFailed` with `@FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API) to transfer requirement to caller`)" - errorLine1=" mExecutor.execute(() -> mListener.onGroupCreationFailed());" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + errorLine1=" mExecutor.execute(() -> mListener.onGroupCreationFailed(reason));" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1471" + line="1532" column="37"/> </issue> @@ -1042,7 +1042,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1477" + line="1538" column="37"/> </issue> @@ -1053,7 +1053,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1483" + line="1544" column="37"/> </issue> @@ -1064,7 +1064,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1489" + line="1550" column="37"/> </issue> @@ -1075,7 +1075,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1495" + line="1556" column="37"/> </issue> @@ -1086,7 +1086,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="1501" + line="1562" column="37"/> </issue> @@ -1097,7 +1097,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="2068" + line="2129" column="74"/> </issue> @@ -1108,7 +1108,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="2113" + line="2174" column="74"/> </issue> @@ -1119,7 +1119,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Wifi/framework/java/android/net/wifi/p2p/WifiP2pManager.java" - line="2163" + line="2224" column="74"/> </issue> diff --git a/framework/tests/Android.bp b/framework/tests/Android.bp index 23763a5515..825fdabf2c 100644 --- a/framework/tests/Android.bp +++ b/framework/tests/Android.bp @@ -45,6 +45,7 @@ android_test { "net-tests-utils", "net-utils-framework-common", "truth", + "wifi_aconfig_flags_lib", ], libs: [ diff --git a/framework/tests/src/android/net/wifi/MscsParamsTest.java b/framework/tests/src/android/net/wifi/MscsParamsTest.java index 701511abde..9d0deab18a 100644 --- a/framework/tests/src/android/net/wifi/MscsParamsTest.java +++ b/framework/tests/src/android/net/wifi/MscsParamsTest.java @@ -21,13 +21,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import android.os.Parcel; -import com.android.modules.utils.build.SdkLevel; - -import org.junit.Before; import org.junit.Test; public class MscsParamsTest { @@ -37,11 +33,6 @@ public class MscsParamsTest { private static final int TEST_USER_PRIORITY_LIMIT = 5; private static final int TEST_STREAM_TIMEOUT_US = 5550; - @Before - public void setUp() { - assumeTrue(SdkLevel.isAtLeastV()); - } - /** Create an MscsParams object with all fields set to the test values. */ private MscsParams createTestMscsParams() { return new MscsParams.Builder() diff --git a/framework/tests/src/android/net/wifi/OuiKeyedDataTest.java b/framework/tests/src/android/net/wifi/OuiKeyedDataTest.java index 0edd3667a7..e640af3d91 100644 --- a/framework/tests/src/android/net/wifi/OuiKeyedDataTest.java +++ b/framework/tests/src/android/net/wifi/OuiKeyedDataTest.java @@ -21,13 +21,10 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import android.os.Parcel; import android.os.PersistableBundle; -import com.android.modules.utils.build.SdkLevel; - import org.junit.Before; import org.junit.Test; @@ -47,7 +44,6 @@ public class OuiKeyedDataTest { @Before public void setUp() { - assumeTrue(SdkLevel.isAtLeastV()); mTestData = createTestBundle(); } diff --git a/framework/tests/src/android/net/wifi/QosCharacteristicsTest.java b/framework/tests/src/android/net/wifi/QosCharacteristicsTest.java index 4876fc18c6..2cfd9605ed 100644 --- a/framework/tests/src/android/net/wifi/QosCharacteristicsTest.java +++ b/framework/tests/src/android/net/wifi/QosCharacteristicsTest.java @@ -25,13 +25,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import android.os.Parcel; -import com.android.modules.utils.build.SdkLevel; - -import org.junit.Before; import org.junit.Test; public class QosCharacteristicsTest { @@ -48,10 +44,6 @@ public class QosCharacteristicsTest { private static final int TEST_DELIVERY_RATIO = QosCharacteristics.DELIVERY_RATIO_99; private static final int TEST_COUNT_EXPONENT = 5; - @Before - public void setUp() { - assumeTrue(SdkLevel.isAtLeastV()); - } /** * Get a Builder with the mandatory fields set to the default test values. diff --git a/framework/tests/src/android/net/wifi/QosPolicyParamsTest.java b/framework/tests/src/android/net/wifi/QosPolicyParamsTest.java index fe40e2158c..bf053615b8 100644 --- a/framework/tests/src/android/net/wifi/QosPolicyParamsTest.java +++ b/framework/tests/src/android/net/wifi/QosPolicyParamsTest.java @@ -20,14 +20,12 @@ package android.net.wifi; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import android.net.DscpPolicy; import android.os.Parcel; import com.android.modules.utils.build.SdkLevel; -import org.junit.Before; import org.junit.Test; import java.net.InetAddress; @@ -47,11 +45,6 @@ public class QosPolicyParamsTest { private static final String TEST_SOURCE_ADDRESS = "127.0.0.1"; private static final String TEST_DESTINATION_ADDRESS = "127.0.0.2"; - @Before - public void setUp() { - assumeTrue(SdkLevel.isAtLeastU()); - } - private InetAddress getInetAddress(String addr) { try { return InetAddress.getByName(addr); diff --git a/framework/tests/src/android/net/wifi/WifiClientTest.java b/framework/tests/src/android/net/wifi/WifiClientTest.java index 704656320a..2fa0d3c04c 100644 --- a/framework/tests/src/android/net/wifi/WifiClientTest.java +++ b/framework/tests/src/android/net/wifi/WifiClientTest.java @@ -34,17 +34,19 @@ import org.junit.Test; @SmallTest public class WifiClientTest { private static final String INTERFACE_NAME = "wlan0"; + private static final String INTERFACE_NAME_1 = "wlan1"; private static final String MAC_ADDRESS_STRING = "00:0a:95:9d:68:16"; private static final MacAddress MAC_ADDRESS = MacAddress.fromString(MAC_ADDRESS_STRING); + private static final int DISCONNECT_REASON = DeauthenticationReasonCode.REASON_DEAUTH_LEAVING; /** * Verify parcel write/read with WifiClient. */ @Test public void testWifiClientParcelWriteRead() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON); - assertParcelSane(writeWifiClient, 2); + assertParcelSane(writeWifiClient, 3); } /** @@ -52,19 +54,20 @@ public class WifiClientTest { */ @Test public void testWifiClientEquals() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); - WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON); + WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, + DISCONNECT_REASON); assertEquals(writeWifiClient, writeWifiClientEquals); assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode()); - assertFieldCountEquals(2, WifiClient.class); + assertFieldCountEquals(3, WifiClient.class); } /** - * Verify not-equals with WifiClient. + * Verify not-equals for 2 WifiClients with different mac address. */ @Test - public void testWifiClientNotEquals() throws Exception { + public void testWifiClientEqualsFailsWhenMacAddressIsDifferent() throws Exception { final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00"); WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME); @@ -72,4 +75,51 @@ public class WifiClientTest { assertNotEquals(writeWifiClient, writeWifiClientNotEquals); assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); } + + /** + * Verify not-equals for 2 WifiClients with different interface name. + */ + @Test + public void testWifiClientEqualsFailsWhenInstanceIsDifferent() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClientNotEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME_1); + + assertNotEquals(writeWifiClient, writeWifiClientNotEquals); + assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); + } + + /** + * Verify not-equals for 2 WifiClients with different disconnect reason. + */ + @Test + public void testWifiClientEqualsFailsWhenDisconnectReasonIsDifferent() throws Exception { + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON); + WifiClient writeWifiClientNotEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, + DeauthenticationReasonCode.REASON_AKMP_NOT_VALID); + + assertNotEquals(writeWifiClient, writeWifiClientNotEquals); + assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); + } + + /** + * Verify that getDisconnectReason() returns REASON_UNKNOWN as the default value. + */ + @Test + public void testWifiClientGetDefaultDisconnectReason() throws Exception { + WifiClient wifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + assertEquals(wifiClient.getDisconnectReason(), DeauthenticationReasonCode.REASON_UNKNOWN); + } + + /** + * Verify that all getter methods in WifiClient (getMacAddress(), + * getApInstanceIdentifier(), getDisconnectReason()) return the + * expected values when a WifiClient object is created with specific data. + */ + @Test + public void testWifiClientGetMethods() throws Exception { + WifiClient wifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME, DISCONNECT_REASON); + assertEquals(wifiClient.getMacAddress(), MAC_ADDRESS); + assertEquals(wifiClient.getApInstanceIdentifier(), INTERFACE_NAME); + assertEquals(wifiClient.getDisconnectReason(), DISCONNECT_REASON); + } } diff --git a/framework/tests/src/android/net/wifi/WifiManagerTest.java b/framework/tests/src/android/net/wifi/WifiManagerTest.java index b18a4f9f3c..bf1b0f2e9b 100644 --- a/framework/tests/src/android/net/wifi/WifiManagerTest.java +++ b/framework/tests/src/android/net/wifi/WifiManagerTest.java @@ -30,6 +30,7 @@ import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHA import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED; import static android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener; +import static android.net.wifi.WifiManager.PASSPOINT_HOME_NETWORK; import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL; import static android.net.wifi.WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; import static android.net.wifi.WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION; @@ -52,10 +53,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_AKM; import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; import static android.net.wifi.WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS; import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; -import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P; -import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT; import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS; -import static android.net.wifi.WifiManager.WIFI_FEATURE_SCANNER; import static android.net.wifi.WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION; import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WEP; @@ -120,8 +118,11 @@ import android.net.wifi.WifiManager.TrafficStateCallback; import android.net.wifi.WifiManager.WifiConnectedNetworkScorer; import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats; import android.net.wifi.WifiUsabilityStatsEntry.LinkStats; +import android.net.wifi.WifiUsabilityStatsEntry.PacketStats; +import android.net.wifi.WifiUsabilityStatsEntry.PeerInfo; import android.net.wifi.WifiUsabilityStatsEntry.RadioStats; import android.net.wifi.WifiUsabilityStatsEntry.RateStats; +import android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq; import android.net.wifi.twt.TwtRequest; import android.net.wifi.twt.TwtSessionCallback; import android.os.Build; @@ -138,6 +139,7 @@ import androidx.test.filters.SmallTest; import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.build.SdkLevel; +import com.android.wifi.x.com.android.modules.utils.ParceledListSlice; import org.junit.Before; import org.junit.Test; @@ -778,12 +780,12 @@ public class WifiManagerTest { List<WifiSsid> expectedSsids = new ArrayList<>(); expectedSsids.add(WifiSsid.fromString("\"TEST_SSID\"")); mWifiManager.setSsidsAllowlist(new ArraySet<>(expectedSsids)); - verify(mWifiService).setSsidsAllowlist(any(), eq(expectedSsids)); + verify(mWifiService).setSsidsAllowlist(any(), + argThat(a -> a.getList().equals(expectedSsids))); // test empty set - mWifiManager.setSsidsAllowlist(Collections.EMPTY_SET); - verify(mWifiService).setSsidsAllowlist(any(), - eq(Collections.EMPTY_LIST)); + mWifiManager.setSsidsAllowlist(Collections.emptySet()); + verify(mWifiService).setSsidsAllowlist(any(), argThat(a -> a.getList().isEmpty())); } /** @@ -2367,16 +2369,20 @@ public class WifiManagerTest { */ @Test public void testGetAllMatchingWifiConfigs() throws Exception { - Map<String, List<ScanResult>> passpointProfiles = new HashMap<>(); - passpointProfiles.put("www.test.com_987a69bca26", new ArrayList<>()); + Map<String, Map<Integer, List<ScanResult>>> passpointProfiles = new HashMap<>(); + Map<Integer, List<ScanResult>> matchingResults = new HashMap<>(); + matchingResults.put(PASSPOINT_HOME_NETWORK, new ArrayList<>()); + passpointProfiles.put("www.test.com_987a69bca26", matchingResults); when(mWifiService.getAllMatchingPasspointProfilesForScanResults( - any(List.class))).thenReturn(passpointProfiles); + any())).thenReturn(passpointProfiles); + when(mWifiService.getWifiConfigsForPasspointProfiles(any())) + .thenReturn(new ParceledListSlice<>(Collections.emptyList())); InOrder inOrder = inOrder(mWifiService); mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>()); - inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any(List.class)); - inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any(List.class)); + inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any()); + inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any()); } /** @@ -2387,7 +2393,7 @@ public class WifiManagerTest { public void testGetMatchingOsuProviders() throws Exception { mWifiManager.getMatchingOsuProviders(new ArrayList<>()); - verify(mWifiService).getMatchingOsuProviders(any(List.class)); + verify(mWifiService).getMatchingOsuProviders(any()); } /** @@ -2398,16 +2404,16 @@ public class WifiManagerTest { @Test public void addGetRemoveNetworkSuggestions() throws Exception { List<WifiNetworkSuggestion> testList = new ArrayList<>(); - when(mWifiService.addNetworkSuggestions(any(List.class), anyString(), + when(mWifiService.addNetworkSuggestions(any(), anyString(), nullable(String.class))).thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); - when(mWifiService.removeNetworkSuggestions(any(List.class), anyString(), anyInt())) + when(mWifiService.removeNetworkSuggestions(any(), anyString(), anyInt())) .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); when(mWifiService.getNetworkSuggestions(anyString())) - .thenReturn(testList); + .thenReturn(new ParceledListSlice<>(testList)); assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager.addNetworkSuggestions(testList)); - verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME), + verify(mWifiService).addNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), nullable(String.class)); assertEquals(testList, mWifiManager.getNetworkSuggestions()); @@ -2415,17 +2421,17 @@ public class WifiManagerTest { assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager.removeNetworkSuggestions(new ArrayList<>())); - verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME), + verify(mWifiService).removeNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_DISCONNECT)); } @Test public void testRemoveNetworkSuggestionWithAction() throws Exception { - when(mWifiService.removeNetworkSuggestions(anyList(), anyString(), anyInt())) + when(mWifiService.removeNetworkSuggestions(any(), anyString(), anyInt())) .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager .removeNetworkSuggestions(new ArrayList<>(), ACTION_REMOVE_SUGGESTION_LINGER)); - verify(mWifiService).removeNetworkSuggestions(any(List.class), + verify(mWifiService).removeNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_LINGER)); } @@ -2502,27 +2508,40 @@ public class WifiManagerTest { contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8); contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12); contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16); + PacketStats[] packetStats = new PacketStats[4]; + packetStats[0] = new PacketStats(1, 2, 3, 4); + packetStats[1] = new PacketStats(5, 6, 7, 8); + packetStats[2] = new PacketStats(9, 10, 11, 12); + packetStats[3] = new PacketStats(13, 14, 15, 16); RateStats[] rateStats = new RateStats[2]; rateStats[0] = new RateStats(1, 3, 5, 7, 9, 11, 13, 15, 17); rateStats[1] = new RateStats(2, 4, 6, 8, 10, 12, 14, 16, 18); RadioStats[] radioStats = new RadioStats[2]; radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18); - radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28); + radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3}); + PeerInfo[] peerInfo = new PeerInfo[1]; + peerInfo[0] = new PeerInfo(1, 50, rateStats); + ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412); + ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500); SparseArray<LinkStats> linkStats = new SparseArray<>(); linkStats.put(0, - new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_NOT_IN_USE, 0, -50, 300, - 200, - 188, 2, 2, 100, 300, 100, 100, 200, - contentionTimeStats, rateStats)); + new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_NOT_IN_USE, 0, -50, 2412, + -50, 0, 0, 0, 300, 200, 188, 2, 2, 100, 300, 100, 100, 200, + contentionTimeStats, rateStats, packetStats, peerInfo, + scanResultsWithSameFreq2G)); linkStats.put(1, - new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 860, 600, - 388, 2, 2, 200, 400, 100, 100, 200, - contentionTimeStats, rateStats)); + new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 5500, + -40, 1, 0, 0, 860, 600, 388, 2, 2, 200, 400, 100, 100, 200, + contentionTimeStats, rateStats, packetStats, peerInfo, + scanResultsWithSameFreq5G)); callbackCaptor.getValue().onWifiUsabilityStats(1, true, new WifiUsabilityStatsEntry(System.currentTimeMillis(), -50, 100, 10, 0, 5, 5, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1, 100, 10, 100, 27, contentionTimeStats, rateStats, radioStats, 101, true, true, true, - 0, 10, 10, true, linkStats)); + 0, 10, 10, true, linkStats, 1, 0, 10, 20, 1, 2, 1, 1, 1, 1, false, 0, + false, 100, 100, 1)); verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(), any(WifiUsabilityStatsEntry.class)); } @@ -2547,11 +2566,11 @@ public class WifiManagerTest { */ @Test public void testIsEnhancedOpenSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_OWE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_OWE))) + .thenReturn(true); assertTrue(mWifiManager.isEnhancedOpenSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_OWE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_OWE))) + .thenReturn(false); assertFalse(mWifiManager.isEnhancedOpenSupported()); } @@ -2560,11 +2579,11 @@ public class WifiManagerTest { */ @Test public void testIsWpa3SaeSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_WPA3_SAE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SAE))) + .thenReturn(true); assertTrue(mWifiManager.isWpa3SaeSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_WPA3_SAE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SAE))) + .thenReturn(false); assertFalse(mWifiManager.isWpa3SaeSupported()); } @@ -2573,11 +2592,11 @@ public class WifiManagerTest { */ @Test public void testIsWpa3SuiteBSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_WPA3_SUITE_B)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SUITE_B))) + .thenReturn(true); assertTrue(mWifiManager.isWpa3SuiteBSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_WPA3_SUITE_B)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA3_SUITE_B))) + .thenReturn(false); assertFalse(mWifiManager.isWpa3SuiteBSupported()); } @@ -2586,11 +2605,11 @@ public class WifiManagerTest { */ @Test public void testIsEasyConnectSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_DPP)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP))) + .thenReturn(true); assertTrue(mWifiManager.isEasyConnectSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_DPP)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP))) + .thenReturn(false); assertFalse(mWifiManager.isEasyConnectSupported()); } @@ -2599,11 +2618,11 @@ public class WifiManagerTest { */ @Test public void testIsEasyConnectDppAkmSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_DPP_AKM)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_AKM))) + .thenReturn(true); assertTrue(mWifiManager.isEasyConnectDppAkmSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_DPP_AKM)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_AKM))) + .thenReturn(false); assertFalse(mWifiManager.isEasyConnectDppAkmSupported()); } @@ -2613,12 +2632,11 @@ public class WifiManagerTest { @Test public void testIsEasyConnectEnrolleeResponderModeSupported() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); - - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER))) + .thenReturn(true); assertTrue(mWifiManager.isEasyConnectEnrolleeResponderModeSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER))) + .thenReturn(false); assertFalse(mWifiManager.isEasyConnectEnrolleeResponderModeSupported()); } @@ -2627,11 +2645,11 @@ public class WifiManagerTest { */ @Test public void testIsStaApConcurrencyOpenSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_AP_STA)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_AP_STA))) + .thenReturn(true); assertTrue(mWifiManager.isStaApConcurrencySupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_AP_STA)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_AP_STA))) + .thenReturn(false); assertFalse(mWifiManager.isStaApConcurrencySupported()); } @@ -2640,23 +2658,27 @@ public class WifiManagerTest { */ @Test public void testIsStaConcurrencySupported() throws Exception { - when(mWifiService.getSupportedFeatures()).thenReturn(0L); + when(mWifiService.isFeatureSupported(anyInt())).thenReturn(false); assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported()); assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported()); assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported()); assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY))) + .thenReturn(true); assertTrue(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported()); assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported()); assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported()); assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MBB - | WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED - | WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY))) + .thenReturn(false); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MBB))) + .thenReturn(true); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED))) + .thenReturn(true); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET))) + .thenReturn(true); assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported()); assertTrue(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported()); assertTrue(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported()); @@ -2833,30 +2855,6 @@ public class WifiManagerTest { } /** - * Test behavior of {@link WifiManager#getSupportedFeatures()} - */ - @Test - public void testGetSupportedFeatures() throws Exception { - long supportedFeatures = - WIFI_FEATURE_SCANNER - | WIFI_FEATURE_PASSPOINT - | WIFI_FEATURE_P2P; - when(mWifiService.getSupportedFeatures()) - .thenReturn(Long.valueOf(supportedFeatures)); - - assertTrue(mWifiManager.isWifiScannerSupported()); - assertTrue(mWifiManager.isPasspointSupported()); - assertTrue(mWifiManager.isP2pSupported()); - assertFalse(mWifiManager.isPortableHotspotSupported()); - assertFalse(mWifiManager.isDeviceToDeviceRttSupported()); - assertFalse(mWifiManager.isDeviceToApRttSupported()); - assertFalse(mWifiManager.isPreferredNetworkOffloadSupported()); - assertFalse(mWifiManager.isTdlsSupported()); - assertFalse(mWifiManager.isOffChannelTdlsSupported()); - assertFalse(mWifiManager.isEnhancedPowerReportingSupported()); - } - - /** * Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync} * throws an exception. */ @@ -3239,11 +3237,9 @@ public class WifiManagerTest { */ @Test public void testIsWapiSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WifiManager.WIFI_FEATURE_WAPI)); + when(mWifiService.isFeatureSupported(eq(WifiManager.WIFI_FEATURE_WAPI))).thenReturn(true); assertTrue(mWifiManager.isWapiSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI)); + when(mWifiService.isFeatureSupported(eq(WifiManager.WIFI_FEATURE_WAPI))).thenReturn(false); assertFalse(mWifiManager.isWapiSupported()); } @@ -3314,8 +3310,8 @@ public class WifiManagerTest { List<WifiConfiguration> testResults = new ArrayList<>(); testResults.add(new WifiConfiguration()); - when(mWifiService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any(List.class))) - .thenReturn(testResults); + when(mWifiService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any())) + .thenReturn(new ParceledListSlice<>(testResults)); assertEquals(testResults, mWifiManager .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>())); } @@ -3402,7 +3398,7 @@ public class WifiManagerTest { mWifiManager.addCustomDhcpOptions( WifiSsid.fromString(TEST_SSID), TEST_OUI, new ArrayList<DhcpOption>()); verify(mWifiService).addCustomDhcpOptions( - WifiSsid.fromString(TEST_SSID), TEST_OUI, new ArrayList<DhcpOption>()); + eq(WifiSsid.fromString(TEST_SSID)), eq(TEST_OUI), any()); } /** @@ -3569,11 +3565,11 @@ public class WifiManagerTest { */ @Test public void testIsPasspointTermsAndConditionsSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS))) + .thenReturn(true); assertTrue(mWifiManager.isPasspointTermsAndConditionsSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS))) + .thenReturn(false); assertFalse(mWifiManager.isPasspointTermsAndConditionsSupported()); } @@ -3637,11 +3633,11 @@ public class WifiManagerTest { */ @Test public void testIsDecoratedIdentitySupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_DECORATED_IDENTITY)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DECORATED_IDENTITY))) + .thenReturn(true); assertTrue(mWifiManager.isDecoratedIdentitySupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_DECORATED_IDENTITY)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DECORATED_IDENTITY))) + .thenReturn(false); assertFalse(mWifiManager.isDecoratedIdentitySupported()); } @@ -3650,11 +3646,11 @@ public class WifiManagerTest { */ @Test public void testIsTrustOnFirstUseSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_TRUST_ON_FIRST_USE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_TRUST_ON_FIRST_USE))) + .thenReturn(true); assertTrue(mWifiManager.isTrustOnFirstUseSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_TRUST_ON_FIRST_USE)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_TRUST_ON_FIRST_USE))) + .thenReturn(false); assertFalse(mWifiManager.isTrustOnFirstUseSupported()); } @@ -3926,11 +3922,11 @@ public class WifiManagerTest { */ @Test public void testIsStaConcurrencyForMultiInternetSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET))) + .thenReturn(true); assertTrue(mWifiManager.isStaConcurrencyForMultiInternetSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET))) + .thenReturn(false); assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported()); } @@ -3960,11 +3956,11 @@ public class WifiManagerTest { */ @Test public void testIsDualBandSimultaneousSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS))) + .thenReturn(true); assertTrue(mWifiManager.isDualBandSimultaneousSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS))) + .thenReturn(false); assertFalse(mWifiManager.isDualBandSimultaneousSupported()); } /* @@ -3972,9 +3968,11 @@ public class WifiManagerTest { */ @Test public void testIsTidToLinkMappingSupported() throws Exception { - when(mWifiService.getSupportedFeatures()).thenReturn(WIFI_FEATURE_T2LM_NEGOTIATION); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_T2LM_NEGOTIATION))) + .thenReturn(true); assertTrue(mWifiManager.isTidToLinkMappingNegotiationSupported()); - when(mWifiService.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_T2LM_NEGOTIATION); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_T2LM_NEGOTIATION))) + .thenReturn(false); assertFalse(mWifiManager.isTidToLinkMappingNegotiationSupported()); } @@ -4152,11 +4150,11 @@ public class WifiManagerTest { */ @Test public void testIsWepSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_WEP)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WEP))) + .thenReturn(true); assertTrue(mWifiManager.isWepSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_WEP)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WEP))) + .thenReturn(false); assertFalse(mWifiManager.isWepSupported()); } @@ -4165,11 +4163,11 @@ public class WifiManagerTest { */ @Test public void testIsWpaPersonalSupported() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_WPA_PERSONAL)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA_PERSONAL))) + .thenReturn(true); assertTrue(mWifiManager.isWpaPersonalSupported()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_WPA_PERSONAL)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_WPA_PERSONAL))) + .thenReturn(false); assertFalse(mWifiManager.isWpaPersonalSupported()); } @@ -4328,11 +4326,11 @@ public class WifiManagerTest { */ @Test public void testIsD2dSupportedWhenInfraStaDisabled() throws Exception { - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED))) + .thenReturn(true); assertTrue(mWifiManager.isD2dSupportedWhenInfraStaDisabled()); - when(mWifiService.getSupportedFeatures()) - .thenReturn(new Long(~WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED)); + when(mWifiService.isFeatureSupported(eq(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED))) + .thenReturn(false); assertFalse(mWifiManager.isD2dSupportedWhenInfraStaDisabled()); } @@ -4384,4 +4382,67 @@ public class WifiManagerTest { mWifiManager.isPreferredNetworkOffloadSupported(); verify(mWifiService).isPnoSupported(); } + + @Test + public void testSetAutojoinDisallowedSecurityTypesToWifiServiceImpl() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + int[] restrictions = { + WifiInfo.SECURITY_TYPE_OPEN, + WifiInfo.SECURITY_TYPE_WEP, + WifiInfo.SECURITY_TYPE_OWE }; + int restrictionBitmap = (0x1 << WifiInfo.SECURITY_TYPE_OPEN) + | (0x1 << WifiInfo.SECURITY_TYPE_WEP) + | (0x1 << WifiInfo.SECURITY_TYPE_OWE); + ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); + mWifiManager.setAutojoinDisallowedSecurityTypes(restrictions); + verify(mWifiService).setAutojoinDisallowedSecurityTypes(eq(restrictionBitmap), + bundleCaptor.capture()); + assertEquals(mContext.getAttributionSource(), + bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE)); + + // Null argument + assertThrows(NullPointerException.class, + () -> mWifiManager.setAutojoinDisallowedSecurityTypes(null)); + } + + @Test + public void testGetAutojoinDisallowedSecurityTypesToWifiServiceImpl() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + final int[] restrictionToSet = { + WifiInfo.SECURITY_TYPE_OPEN, + WifiInfo.SECURITY_TYPE_WEP, + WifiInfo.SECURITY_TYPE_OWE }; + + final int restrictionBitmap = (0x1 << WifiInfo.SECURITY_TYPE_OPEN) + | (0x1 << WifiInfo.SECURITY_TYPE_WEP) + | (0x1 << WifiInfo.SECURITY_TYPE_OWE); + + SynchronousExecutor executor = mock(SynchronousExecutor.class); + Consumer<int[]> mockResultsCallback = mock(Consumer.class); + + // null executor + assertThrows(NullPointerException.class, + () -> mWifiManager.getAutojoinDisallowedSecurityTypes(null, mockResultsCallback)); + // null resultsCallback + assertThrows(NullPointerException.class, + () -> mWifiManager.getAutojoinDisallowedSecurityTypes(executor, null)); + + ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); + ArgumentCaptor<IIntegerListener.Stub> cbCaptor = ArgumentCaptor.forClass( + IIntegerListener.Stub.class); + + ArgumentCaptor<int[]> resultCaptor = ArgumentCaptor.forClass(int[].class); + + mWifiManager.getAutojoinDisallowedSecurityTypes(new SynchronousExecutor(), + mockResultsCallback); + verify(mWifiService).getAutojoinDisallowedSecurityTypes(cbCaptor.capture(), + bundleCaptor.capture()); + assertEquals(mContext.getAttributionSource(), + bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE)); + + cbCaptor.getValue().onResult(restrictionBitmap); + + verify(mockResultsCallback).accept(resultCaptor.capture()); + assertArrayEquals(restrictionToSet, resultCaptor.getValue()); + } } diff --git a/framework/tests/src/android/net/wifi/WifiUriParserTest.java b/framework/tests/src/android/net/wifi/WifiUriParserTest.java index 396c677676..a01b6b755e 100644 --- a/framework/tests/src/android/net/wifi/WifiUriParserTest.java +++ b/framework/tests/src/android/net/wifi/WifiUriParserTest.java @@ -22,12 +22,18 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; + import com.google.common.collect.ImmutableList; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import org.mockito.MockitoSession; import java.util.Collections; import java.util.List; @@ -42,6 +48,26 @@ public class WifiUriParserTest { private static final String TEST_DPP_URI = "DPP:C:81/1;I:" + TEST_DPP_INFORMATION + ";K:" + TEST_DPP_PUBLIC_KEY + ";;"; + private MockitoSession mSession; + + @Before + public void setUp() throws Exception { + mSession = ExtendedMockito.mockitoSession() + .initMocks(this) + .mockStatic(WifiUriParser.class, CALLS_REAL_METHODS) + .startMocking(); + } + + /** + * Called after each test + */ + @After + public void cleanup() { + if (mSession != null) { + mSession.finishMocking(); + } + } + private void verifyZxParsing( UriParserResults uri, String expectedSSID, @@ -66,6 +92,15 @@ public class WifiUriParserTest { @Test public void testZxParsing() { + ExtendedMockito.when(WifiUriParser.mockableIsFlagNewUriParsingForEscapeCharacterEnabled()) + .thenReturn(false); + testZxParsing(false); + ExtendedMockito.when(WifiUriParser.mockableIsFlagNewUriParsingForEscapeCharacterEnabled()) + .thenReturn(true); + testZxParsing(true); + } + + public void testZxParsing(boolean isNewParserSupported) { // Test no password List<SecurityParams> expectedSecurityParamsList = ImmutableList.of( @@ -88,7 +123,34 @@ public class WifiUriParserTest { expectedSecurityParamsList, null, false); + // Unknown prefix tag & extra ; should keep work. (either new or old parsing) + uri = WifiUriParser.parseUri("WIFI:SSS:456 ;; S: test 123\\;; T:nopass"); + verifyZxParsing( + uri, + "\" test 123;\"", + expectedSecurityParamsList, + null, + false); + if (isNewParserSupported) { + // The \\ in the end of ssid but it should work. + uri = WifiUriParser.parseUri("WIFI:S:testAbC\\\\; T:nopass"); + verifyZxParsing( + uri, + "\"testAbC\\\"", + expectedSecurityParamsList, + null, + false); + + // The \; and \\ in the end of ssid but it should work. + uri = WifiUriParser.parseUri("WIFI:S:test 123\\;\\\\\\;; T:nopass"); + verifyZxParsing( + uri, + "\"test 123;\\;\"", + expectedSecurityParamsList, + null, + false); + } // Test WEP expectedSecurityParamsList = ImmutableList.of( @@ -101,7 +163,7 @@ public class WifiUriParserTest { expectedSecurityParamsList, "\"somepasswo#%^**123rd\"", true); - // invalid code but it should work. + // invalid code (space before pre-fix) but it should work. uri = WifiUriParser.parseUri("WIFI:S:reallyLONGone;T:WEP; P:somepassword"); verifyZxParsing( uri, @@ -110,18 +172,30 @@ public class WifiUriParserTest { "\"somepassword\"", true); - // Test WPA + // Test WPA & space as part of SSID and passphrase. expectedSecurityParamsList = ImmutableList.of( SecurityParams.createSecurityParamsBySecurityType( WifiConfiguration.SECURITY_TYPE_PSK)); - uri = WifiUriParser.parseUri("WIFI:S:anotherone;T:WPA;P:3#=3j9asicla"); + uri = WifiUriParser.parseUri("WIFI:S:another one;T:WPA;P:3#=3j9 asicla"); verifyZxParsing( uri, - "\"anotherone\"", + "\"another one\"", expectedSecurityParamsList, - "\"3#=3j9asicla\"", + "\"3#=3j9 asicla\"", false); + + if (isNewParserSupported) { + // The " in the start and end of ssid but it should work. + uri = WifiUriParser.parseUri("WIFI:S:\"\"\"\"; T:WPA; P:\"\""); + verifyZxParsing( + uri, + "\"\"\"\"\"\"", + expectedSecurityParamsList, + "\"\"\"\"", + false); + } + // invalid code but it should work. uri = WifiUriParser.parseUri("WIFI: S:anotherone;T:WPA;P:abcdefghihklmn"); verifyZxParsing( @@ -155,9 +229,9 @@ public class WifiUriParserTest { uri = WifiUriParser.parseUri("WIFI:T:ADB;S:myname;P:mypass;;"); verifyZxParsing( uri, - "\"myname\"", + "myname", Collections.emptyList(), - "\"mypass\"", + "mypass", false); // Test transition disable value expectedSecurityParamsList = diff --git a/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java b/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java index 972c31099d..d8211978cf 100644 --- a/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java +++ b/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java @@ -23,8 +23,11 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.validateMockitoUsage; import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats; +import android.net.wifi.WifiUsabilityStatsEntry.PacketStats; +import android.net.wifi.WifiUsabilityStatsEntry.PeerInfo; import android.net.wifi.WifiUsabilityStatsEntry.RadioStats; import android.net.wifi.WifiUsabilityStatsEntry.RateStats; +import android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq; import android.os.Parcel; import android.util.SparseArray; @@ -80,37 +83,48 @@ public class WifiUsabilityStatsEntryTest { contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8); contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12); contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16); + PacketStats[] packetStats = new PacketStats[4]; + packetStats[0] = new PacketStats(1, 2, 3, 4); + packetStats[1] = new PacketStats(5, 6, 7, 8); + packetStats[2] = new PacketStats(9, 10, 11, 12); + packetStats[3] = new PacketStats(13, 14, 15, 16); RateStats[] rateStats = new RateStats[2]; rateStats[0] = new RateStats(1, 3, 4, 7, 9, 11, 13, 15, 17); rateStats[1] = new RateStats(2, 2, 3, 8, 10, 12, 14, 16, 18); RadioStats[] radioStats = new RadioStats[2]; radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18); - radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28); + radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3}); + PeerInfo[] peerInfo = new PeerInfo[1]; + peerInfo[0] = new PeerInfo(1, 50, rateStats); + ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412); + ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500); SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>(); linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(0, - WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -50, 300, 200, 188, 2, 2, - 100, - 300, 100, 100, 200, - contentionTimeStats, rateStats)); + WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -50, 2412, -50, 0, 0, 0, + 300, 200, 188, 2, 2, 100, 300, 100, 100, 200, + contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq2G)); linkStats.put(1, new WifiUsabilityStatsEntry.LinkStats(1, - WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -40, 860, 600, 388, 2, 2, - 200, - 400, 100, 150, 300, - contentionTimeStats, rateStats)); + WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN, 0, -40, 5500, -40, 1, 0, 0, + 860, 600, 388, 2, 2, 200, 400, 100, 150, 300, + contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq5G)); WifiUsabilityStatsEntry usabilityStatsEntry = new WifiUsabilityStatsEntry( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 32, contentionTimeStats, rateStats, radioStats, 100, true, - true, true, 23, 24, 25, true, linkStats); + true, true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + false, 36, false, 37, 38, 39); assertEquals(32, usabilityStatsEntry.getTimeSliceDutyCycleInPercent()); WifiUsabilityStatsEntry usabilityStatsEntryWithInvalidDutyCycleValue = new WifiUsabilityStatsEntry( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -1, contentionTimeStats, rateStats, radioStats, 101, true, true, - true, 23, 24, 25, true, linkStats); + true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + true, 36, true, 37, 38, 39); try { usabilityStatsEntryWithInvalidDutyCycleValue.getTimeSliceDutyCycleInPercent(); fail(); @@ -136,27 +150,39 @@ public class WifiUsabilityStatsEntryTest { contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8); contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12); contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16); + PacketStats[] packetStats = new PacketStats[4]; + packetStats[0] = new PacketStats(1, 2, 3, 4); + packetStats[1] = new PacketStats(5, 6, 7, 8); + packetStats[2] = new PacketStats(9, 10, 11, 12); + packetStats[3] = new PacketStats(13, 14, 15, 16); RateStats[] rateStats = new RateStats[2]; rateStats[0] = new RateStats(1, 3, 4, 7, 9, 11, 13, 15, 17); rateStats[1] = new RateStats(2, 2, 3, 8, 10, 12, 14, 16, 18); RadioStats[] radioStats = new RadioStats[2]; radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18); - radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28); + radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28, new int[] {1, 2, 3}); + PeerInfo[] peerInfo = new PeerInfo[1]; + peerInfo[0] = new PeerInfo(1, 50, rateStats); + ScanResultWithSameFreq[] scanResultsWithSameFreq2G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq2G[0] = new ScanResultWithSameFreq(100, -50, 2412); + ScanResultWithSameFreq[] scanResultsWithSameFreq5G = new ScanResultWithSameFreq[1]; + scanResultsWithSameFreq5G[0] = new ScanResultWithSameFreq(100, -50, 5500); SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>(); linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(3, - WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 300, 200, 188, 2, 2, 100, - 300, 100, 100, 200, - contentionTimeStats, rateStats)); + WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 2412, -50, 0, 0, 0, 300, + 200, 188, 2, 2, 100, 300, 100, 100, 200, + contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq2G)); linkStats.put(1, new WifiUsabilityStatsEntry.LinkStats(8, - WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 860, 600, 388, 2, 2, 200, - 400, 100, 150, 300, - contentionTimeStats, rateStats)); + WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 5500, -40, 1, 0, 0, 860, + 600, 388, 2, 2, 200, 400, 100, 150, 300, + contentionTimeStats, rateStats, packetStats, peerInfo, scanResultsWithSameFreq5G)); return new WifiUsabilityStatsEntry( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 50, contentionTimeStats, rateStats, radioStats, 102, true, - true, true, 23, 24, 25, true, linkStats + true, true, 23, 24, 25, true, linkStats, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + true, 36, false, 37, 38, 39 ); } @@ -336,6 +362,13 @@ public class WifiUsabilityStatsEntryTest { for (int link : links) { assertEquals(expected.getRssi(link), actual.getRssi(link)); assertEquals(expected.getRadioId(link), actual.getRadioId(link)); + assertEquals(expected.getFrequencyMhz(link), actual.getFrequencyMhz(link)); + assertEquals(expected.getRssiMgmt(link), actual.getRssiMgmt(link)); + assertEquals(expected.getChannelWidth(link), actual.getChannelWidth(link)); + assertEquals(expected.getCenterFreqFirstSegment(link), + actual.getCenterFreqFirstSegment(link)); + assertEquals(expected.getCenterFreqSecondSegment(link), + actual.getCenterFreqSecondSegment(link)); assertEquals(expected.getTxLinkSpeedMbps(link), actual.getTxLinkSpeedMbps(link)); assertEquals(expected.getRxLinkSpeedMbps(link), @@ -467,6 +500,118 @@ public class WifiUsabilityStatsEntryTest { actual.getContentionTimeStats(link, WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) .getContentionNumSamples()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxRetries(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxRetries()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxBad(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getTxBad()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getRxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE) + .getRxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxRetries(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxRetries()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxBad(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getTxBad()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getRxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK) + .getRxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxRetries(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxRetries()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxBad(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getTxBad()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getRxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI) + .getRxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxSuccess()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxRetries(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxRetries()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxBad(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getTxBad()); + assertEquals( + expected.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getRxSuccess(), + actual.getPacketStats(link, + WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO) + .getRxSuccess()); for (int j = 0; j < expected.getRateStats(link).size(); j++) { RateStats expectedStats = expected.getRateStats(link).get(j); @@ -483,9 +628,34 @@ public class WifiUsabilityStatsEntryTest { assertEquals(expectedStats.getMpduLost(), actualStats.getMpduLost()); assertEquals(expectedStats.getRetries(), actualStats.getRetries()); } - + for (int j = 0; j < expected.getPeerInfo(link).size(); j++) { + PeerInfo expectedStats = expected.getPeerInfo(link).get(j); + PeerInfo actualStats = actual.getPeerInfo(link).get(j); + assertEquals(expectedStats.getStaCount(), actualStats.getStaCount()); + assertEquals(expectedStats.getChanUtil(), actualStats.getChanUtil()); + } + for (int j = 0; j < expected.getScanResultsWithSameFreq(link).length; j++) { + assertEquals(expected.getScanResultsWithSameFreq(link)[j] + .getScanResultTimestampMicros(), + actual.getScanResultsWithSameFreq(link)[j] + .getScanResultTimestampMicros()); + assertEquals(expected.getScanResultsWithSameFreq(link)[j].getRssi(), + actual.getScanResultsWithSameFreq(link)[j].getRssi()); + assertEquals(expected.getScanResultsWithSameFreq(link)[j].getFrequency(), + actual.getScanResultsWithSameFreq(link)[j].getFrequency()); + } } } + assertEquals(expected.getWifiLinkCount(), actual.getWifiLinkCount()); + assertEquals(expected.isNetworkCapabilitiesDownstreamSufficient(), + actual.isNetworkCapabilitiesDownstreamSufficient()); + assertEquals(expected.isNetworkCapabilitiesUpstreamSufficient(), + actual.isNetworkCapabilitiesUpstreamSufficient()); + assertEquals(expected.isThroughputPredictorDownstreamSufficient(), + actual.isThroughputPredictorDownstreamSufficient()); + assertEquals(expected.isThroughputPredictorUpstreamSufficient(), + actual.isThroughputPredictorUpstreamSufficient()); + assertEquals(expected.isBluetoothConnected(), actual.isBluetoothConnected()); } /** @@ -496,14 +666,14 @@ public class WifiUsabilityStatsEntryTest { SparseArray<WifiUsabilityStatsEntry.LinkStats> linkStats = new SparseArray<>(); linkStats.put(0, new WifiUsabilityStatsEntry.LinkStats(0, - WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 300, 200, 188, 2, 2, 100, - 300, 100, 100, 200, - null, null)); + WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -50, 2412, -50, 0, 0, 0, 300, + 200, 188, 2, 2, 100, 300, 100, 100, 200, + null, null, null, null, null)); WifiUsabilityStatsEntry usabilityStatsEntry = new WifiUsabilityStatsEntry( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 32, null, null, null, 100, true, - true, true, 23, 24, 25, true, linkStats); + 32, null, null, null, 100, true, true, true, 23, 24, 25, true, linkStats, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, true, 36, true, 37, 38, 39); assertThrows("linkId is invalid - " + MloLink.INVALID_MLO_LINK_ID, NoSuchElementException.class, diff --git a/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java b/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java index 4a485c06ab..5a51ac6e5f 100644 --- a/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java +++ b/framework/tests/src/android/net/wifi/util/ScanResultUtilTest.java @@ -363,6 +363,33 @@ public class ScanResultUtilTest { } /** + * Test that a network configured in WPA3-Compatibility mode is detected as WPA3-transition mode + */ + @Test + public void testWPA3CompatibilityModeNetwork() { + final String ssid = "WPA3-Compatibility"; + String caps = "[WPA2-PSK-CCMP][RSN-PSK-CCMP][RSN-SAE-CCMP][MFPC][RSNO]"; + + ScanResult input = new ScanResult.Builder(WifiSsid.fromUtf8Text(ssid), + "ab:cd:01:ef:45:89") + .setHessid(1245) + .setCaps(caps) + .setRssi(-78) + .setFrequency(2450) + .setTsf(1025) + .setDistanceCm(22) + .setDistanceSdCm(33) + .setIs80211McRTTResponder(true) + .build(); + + input.informationElements = new InformationElement[] { + createIE(InformationElement.EID_SSID, ssid.getBytes(StandardCharsets.UTF_8)) + }; + + assertTrue(ScanResultUtil.isScanResultForPskSaeTransitionNetwork(input)); + } + + /** * Test that a PSK network is not detected as transition mode */ @Test diff --git a/framework/tests/src/android/net/wifi/util/WifiResourceCacheTest.java b/framework/tests/src/android/net/wifi/util/WifiResourceCacheTest.java index 54f9add266..f1a7578211 100644 --- a/framework/tests/src/android/net/wifi/util/WifiResourceCacheTest.java +++ b/framework/tests/src/android/net/wifi/util/WifiResourceCacheTest.java @@ -16,91 +16,168 @@ package android.net.wifi.util; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.res.Resources; import android.net.wifi.WifiContext; +import android.text.TextUtils; import androidx.test.filters.SmallTest; +import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.io.PrintWriter; +import java.io.StringWriter; + @SmallTest public class WifiResourceCacheTest { private static final int TEST_ID = 12345; private static final String TEST_NAME = "test_name"; private static final int VALUE_1 = 10; private static final int VALUE_2 = 20; + private static final String STRING_1 = "string_1"; + private static final String STRING_2 = "string_2"; + private static final int[] INT_ARRAY_1 = {1, 2, 3, 4, 5}; + private static final int[] INT_ARRAY_2 = {5, 4, 3, 2, 1}; + private static final String[] STRINGS_1 = {"1", "2", "3", "4", "5"}; + private static final String[] STRINGS_2 = {"5", "4", "3", "2", "1"}; @Mock WifiContext mWifiContext; @Mock Resources mResources; private WifiResourceCache mWifiResourceCache; + @Captor + ArgumentCaptor<Integer> mIntegerArgumentCaptor; @Before public void setup() { MockitoAnnotations.initMocks(this); when(mWifiContext.getResources()).thenReturn(mResources); mWifiResourceCache = new WifiResourceCache(mWifiContext); + doAnswer(v -> String.valueOf(v.getArguments()[0])).when(mResources) + .getResourceEntryName(anyInt()); + } + + @After + public void teardown() { + StringWriter sw = new StringWriter(); + mWifiResourceCache.dump(new PrintWriter(sw)); + assertFalse(TextUtils.isEmpty(sw.toString())); + Mockito.framework().clearInlineMocks(); } @Test public void testGetBooleanResource() { when(mResources.getBoolean(TEST_ID)).thenReturn(true); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); verify(mResources).getBoolean(TEST_ID); } @Test public void testGetIntegerResource() { when(mResources.getInteger(TEST_ID)).thenReturn(VALUE_1); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID)); verify(mResources).getInteger(TEST_ID); } @Test + public void testGetStringResource() { + when(mResources.getString(TEST_ID)).thenReturn(STRING_1); + assertEquals(STRING_1, mWifiResourceCache.getString(TEST_ID)); + assertEquals(STRING_1, mWifiResourceCache.getString(TEST_ID)); + verify(mResources).getString(TEST_ID); + } + + @Test public void testOverrideBooleanResource() { + mWifiResourceCache.restoreBooleanValue(String.valueOf(TEST_ID)); when(mResources.getBoolean(TEST_ID)).thenReturn(true); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); - mWifiResourceCache.overrideBooleanValue(TEST_NAME, false); - assertFalse(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); - mWifiResourceCache.restoreBooleanValue(TEST_NAME); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); + mWifiResourceCache.overrideBooleanValue(String.valueOf(TEST_ID), false); + assertFalse(mWifiResourceCache.getBoolean(TEST_ID)); + mWifiResourceCache.restoreBooleanValue(String.valueOf(TEST_ID)); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); verify(mResources, times(2)).getBoolean(TEST_ID); } @Test public void testOverrideIntegerResource() { + mWifiResourceCache.restoreIntegerValue(String.valueOf(TEST_ID)); when(mResources.getInteger(TEST_ID)).thenReturn(VALUE_1); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); - mWifiResourceCache.overrideIntegerValue(TEST_NAME, VALUE_2); - assertEquals(VALUE_2, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); - mWifiResourceCache.restoreIntegerValue(TEST_NAME); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID)); + mWifiResourceCache.overrideIntegerValue(String.valueOf(TEST_ID), VALUE_2); + assertEquals(VALUE_2, mWifiResourceCache.getInteger(TEST_ID)); + mWifiResourceCache.restoreIntegerValue(String.valueOf(TEST_ID)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID)); verify(mResources, times(2)).getInteger(TEST_ID); } @Test + public void testOverrideStringResource() { + mWifiResourceCache.restoreStringValue(String.valueOf(TEST_ID)); + when(mResources.getString(TEST_ID)).thenReturn(STRING_1); + assertEquals(STRING_1, mWifiResourceCache.getString(TEST_ID)); + mWifiResourceCache.overrideStringValue(String.valueOf(TEST_ID), STRING_2); + assertEquals(STRING_2, mWifiResourceCache.getString(TEST_ID)); + mWifiResourceCache.restoreStringValue(String.valueOf(TEST_ID)); + assertEquals(STRING_1, mWifiResourceCache.getString(TEST_ID)); + verify(mResources, times(2)).getString(TEST_ID); + } + + @Test + public void testOverrideIntArrayResource() { + mWifiResourceCache.restoreIntArrayValue(String.valueOf(TEST_ID)); + when(mResources.getIntArray(TEST_ID)).thenReturn(INT_ARRAY_1); + assertEquals(INT_ARRAY_1, mWifiResourceCache.getIntArray(TEST_ID)); + mWifiResourceCache.overrideIntArrayValue(String.valueOf(TEST_ID), INT_ARRAY_2); + assertArrayEquals(INT_ARRAY_2, mWifiResourceCache.getIntArray(TEST_ID)); + mWifiResourceCache.restoreIntArrayValue(String.valueOf(TEST_ID)); + mWifiResourceCache.restoreIntArrayValue(String.valueOf(TEST_ID)); + assertEquals(INT_ARRAY_1, mWifiResourceCache.getIntArray(TEST_ID)); + verify(mResources, times(2)).getIntArray(TEST_ID); + } + + @Test + public void testOverrideStringArrayResource() { + mWifiResourceCache.restoreStringArrayValue(String.valueOf(TEST_ID)); + when(mResources.getStringArray(TEST_ID)).thenReturn(STRINGS_1); + assertEquals(STRINGS_1, mWifiResourceCache.getStringArray(TEST_ID)); + mWifiResourceCache.overrideStringArrayValue(String.valueOf(TEST_ID), STRINGS_2); + assertEquals(STRINGS_2, mWifiResourceCache.getStringArray(TEST_ID)); + mWifiResourceCache.restoreStringArrayValue(String.valueOf(TEST_ID)); + assertEquals(STRINGS_1, mWifiResourceCache.getStringArray(TEST_ID)); + verify(mResources, times(2)).getStringArray(TEST_ID); + } + + + @Test public void testReset() { when(mResources.getBoolean(TEST_ID)).thenReturn(true); - when(mResources.getInteger(TEST_ID)).thenReturn(VALUE_1); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); - mWifiResourceCache.overrideBooleanValue(TEST_NAME, false); - mWifiResourceCache.overrideIntegerValue(TEST_NAME, VALUE_2); - assertEquals(VALUE_2, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); - assertFalse(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); + when(mResources.getInteger(TEST_ID + 1)).thenReturn(VALUE_1); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID + 1)); + mWifiResourceCache.overrideBooleanValue(String.valueOf(TEST_ID), false); + mWifiResourceCache.overrideIntegerValue(String.valueOf(TEST_ID + 1), VALUE_2); + assertEquals(VALUE_2, mWifiResourceCache.getInteger(TEST_ID + 1)); + assertFalse(mWifiResourceCache.getBoolean(TEST_ID)); mWifiResourceCache.reset(); - assertTrue(mWifiResourceCache.getBoolean(TEST_ID, TEST_NAME)); - assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID, TEST_NAME)); + assertTrue(mWifiResourceCache.getBoolean(TEST_ID)); + assertEquals(VALUE_1, mWifiResourceCache.getInteger(TEST_ID + 1)); verify(mResources, times(2)).getBoolean(TEST_ID); - verify(mResources, times(2)).getInteger(TEST_ID); + verify(mResources, times(2)).getInteger(TEST_ID + 1); } } diff --git a/jni/Android.bp b/jni/Android.bp new file mode 100644 index 0000000000..d67c6aaf3f --- /dev/null +++ b/jni/Android.bp @@ -0,0 +1,17 @@ +cc_library_shared { + name: "libservice-wifi-jni", + min_sdk_version: "30", + cflags: [ + "-Wall", + "-Werror", + ], + srcs: [ + "com_android_server_ServiceManagerWrapper.cpp", + ], + shared_libs: [ + "libbinder_ndk", + ], + apex_available: [ + "com.android.wifi", + ], +} diff --git a/jni/com_android_server_ServiceManagerWrapper.cpp b/jni/com_android_server_ServiceManagerWrapper.cpp new file mode 100644 index 0000000000..b13346b092 --- /dev/null +++ b/jni/com_android_server_ServiceManagerWrapper.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024 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. + */ + +#include <android/binder_auto_utils.h> +#include <android/binder_ibinder_jni.h> +#include <android/binder_manager.h> +#include <jni.h> + +namespace android { + +// nativeWaitForService +extern "C" JNIEXPORT jobject JNICALL + Java_com_android_server_wifi_mainline_1supplicant_ServiceManagerWrapper_nativeWaitForService__Ljava_lang_String_2( + JNIEnv* env, jobject /* clazz */, jstring serviceNameJni) { + // AServiceManager_isDeclared and AServiceManager_waitForService were added in Android 31. + // Because this method will only be called on 35+, we can suppress the availability warning. + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunguarded-availability" + const char* serviceName = env->GetStringUTFChars(serviceNameJni, nullptr); + return AIBinder_toJavaBinder(env, AServiceManager_waitForService(serviceName)); + #pragma clang diagnostic pop +} + +}; // namespace android diff --git a/service/Android.bp b/service/Android.bp index ae9e40cd85..e66820010f 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -65,6 +65,7 @@ java_library { "framework-location.stubs.module_lib", "framework-statsd.stubs.module_lib", "framework-tethering.stubs.module_lib", + "framework-uwb.stubs.module_lib", "unsupportedappusage", "app-compat-annotations", "auto_value_annotations", @@ -76,9 +77,9 @@ java_library { static_libs: [ // Types-only package shared across the HALs - "android.hardware.wifi.common-V1-java", + "android.hardware.wifi.common-V2-java", // AIDL vendor hal implementation - "android.hardware.wifi-V2-java", + "android.hardware.wifi-V3-java", // HIDL vendor hal implementation "android.hardware.wifi-V1.0-java", "android.hardware.wifi-V1.1-java", @@ -88,14 +89,14 @@ java_library { "android.hardware.wifi-V1.5-java", "android.hardware.wifi-V1.6-java", // AIDL hostapd implementation - "android.hardware.wifi.hostapd-V2-java", + "android.hardware.wifi.hostapd-V3-java", // HIDL hostapd implementation "android.hardware.wifi.hostapd-V1.0-java", "android.hardware.wifi.hostapd-V1.1-java", "android.hardware.wifi.hostapd-V1.2-java", "android.hardware.wifi.hostapd-V1.3-java", // AIDL supplicant implementation - "android.hardware.wifi.supplicant-V3-java", + "android.hardware.wifi.supplicant-V4-java", // HIDL supplicant implementation "android.hardware.wifi.supplicant-V1.0-java", "android.hardware.wifi.supplicant-V1.1-java", diff --git a/service/ServiceWifiResources/res/values-fr-rCA-feminine/strings.xml b/service/ServiceWifiResources/res/values-fr-rCA-feminine/strings.xml new file mode 100644 index 0000000000..e90236a14b --- /dev/null +++ b/service/ServiceWifiResources/res/values-fr-rCA-feminine/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2019 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. + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="wifi_eap_error_message_code_32763_carrier_overrides"> + <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g><xliff:g id="SSID">%1$s</xliff:g> : vous êtes déjà connectée à Verizon Wi-Fi Access. (Erreur = 32763)"</item> + </string-array> + <string name="wifi_ca_cert_dialog_preT_continue_text" msgid="9118713368838029797">"Rester connectée"</string> +</resources> diff --git a/service/ServiceWifiResources/res/values-fr-rCA-masculine/strings.xml b/service/ServiceWifiResources/res/values-fr-rCA-masculine/strings.xml new file mode 100644 index 0000000000..6d357d7e41 --- /dev/null +++ b/service/ServiceWifiResources/res/values-fr-rCA-masculine/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2019 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. + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="wifi_eap_error_message_code_32763_carrier_overrides"> + <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g><xliff:g id="SSID">%1$s</xliff:g> : vous êtes déjà connecté à Verizon Wi-Fi Access. (Erreur = 32763)"</item> + </string-array> + <string name="wifi_ca_cert_dialog_preT_continue_text" msgid="9118713368838029797">"Rester connecté"</string> +</resources> diff --git a/service/ServiceWifiResources/res/values-fr-rCA-neuter/strings.xml b/service/ServiceWifiResources/res/values-fr-rCA-neuter/strings.xml new file mode 100644 index 0000000000..1c3e4f2f68 --- /dev/null +++ b/service/ServiceWifiResources/res/values-fr-rCA-neuter/strings.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2019 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. + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string-array name="wifi_eap_error_message_code_32763_carrier_overrides"> + <item msgid="591026649262091217">"<xliff:g id="CARRIER_ID_PREFIX">:::1839:::</xliff:g><xliff:g id="SSID">%1$s</xliff:g> : votre connexion à Verizon Wi-Fi Access est déjà établie. (Erreur = 32763)"</item> + </string-array> + <string name="wifi_ca_cert_dialog_preT_continue_text" msgid="9118713368838029797">"Rester connecté·e"</string> +</resources> diff --git a/service/ServiceWifiResources/res/values/config.xml b/service/ServiceWifiResources/res/values/config.xml index ab73f3ac90..043bd11ee3 100644 --- a/service/ServiceWifiResources/res/values/config.xml +++ b/service/ServiceWifiResources/res/values/config.xml @@ -216,6 +216,11 @@ <!-- boolean indicating whether or not to auto-upgrade band setting configuration to dual bands during cloud configuration restore when device supported --> <bool translatable="false" name ="config_wifiSoftapAutoUpgradeToBridgedConfigWhenSupported">true</bool> + <!-- boolean indicating whether or not to temporarily auto-upgrade tethering softap to + 2.4 + 5GHz Bridged if it is currently available and the usable configured bands only + contain 2.4 or 5Ghz.--> + <bool translatable="false" name ="config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset">false</bool> + <!-- List of allowed channels in 2GHz band for softap. If the device doesn't want to restrict channels this should be empty. Values is a comma separated channel string and/or channel range string like '1-6,11'. --> @@ -1099,6 +1104,14 @@ it as low priority when disconnected, allowing it to be deleted to create other interfaces. A negative value disables this behavior. --> <integer translatable="false" name="config_disconnectedP2pIfaceLowPriorityTimeoutMs">-1</integer> + <!-- list of package names that the framework will allow to use P2P/Aware concurrency. If this + list is empty, then all packages are allowed --> + <string-array translatable="false" name="config_wifiP2pAwareConcurrencyAllowlist"> + <!-- Below is a sample configuration for this list: + <item>com.company1.example.test.name1</item> + <item>com.company2.example.test.name2</item> + --> + </string-array> <!-- boolean indicating whether the Easy Connect (DPP) AKM is supported --> <bool translatable="false" name ="config_wifiDppAkmSupported">false</bool> <!-- Indicates the number of octets to mask for each BSSID in the SecurityLog output. @@ -1331,7 +1344,19 @@ --> </integer-array> - <!-- Wi-Fi chip supports single link MLO SoftAp instances in the bridged mode --> + + <!-- integer indicating the maximum number of MLDs supported for multi-link operation (MLO) + SoftAp. Each multi-link device (AP MLD) can be operated with multiple links or single link. + It is required to configure it at least 1 for multiple links MLO SoftAp. Default value 0 is + treated as device does NOT support multiple links MLO SoftAp and the maximum + number of MLDs is decided by configuration, config_wifiSoftApSingleLinkMloInBridgedModeSupported. + (i.e. 2 when config_wifiSoftApSingleLinkMloInBridgedModeSupported is true and 1 when + config_wifiSoftApSingleLinkMloInBridgedModeSupported is false.) + --> + <integer translatable="false" name="config_wifiSoftApMaxNumberMLDSupported">0</integer> + + <!-- (Deprecated) Wi-Fi chip supports single link MLO SoftAp instances in the bridged mode. + The value will be used only when config_wifiSoftApMaxNumberMLDSupported isn't configured --> <bool translatable="false" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported">false</bool> <!-- Boolean indicating whether Target Wake Time (TWT) feature is supported or not. This flag @@ -1342,4 +1367,35 @@ --> <bool translatable="false" name="config_wifiTwtSupported">true</bool> + <!-- Boolean indicating whether the WiFi framework network selection should set the target BSSID. --> + <bool translatable="false" name="config_wifiNetworkSelectionSetTargetBssid">false</bool> + + <!-- Array containing carrier IDs whose networks should not auto-connect upon initial discovery. + These networks are eligible to become network selection candidates if they still appear in + the scan results after the delay period has passed. Carriers who have requested this + feature are included in the array by default. + --> + <integer-array translatable="false" name="config_wifiDelayedSelectionCarrierIds"> + + <!-- Below is a sample configuration for this list: + <item>1234</item> + <item>5678</item> + --> + </integer-array> + + <!-- Delay time in milliseconds for delayed carrier network selection. + See also config_wifiDelayedSelectionCarrierIds. + --> + <integer translatable="false" name="config_wifiDelayedCarrierSelectionTimeMs">90000</integer> + + <!-- Boolean indicating whether the device supports Wi-Fi Alliance WPA3 Specification + version 3.3 Section 14 - RSN Overriding. + Enabling this config allows framework to parse the RSNO IE and RSNO2 IE on devices running + Supplicant AIDL interface version lower than 4. Only enable this flag if Supplicant and + driver/firmware supports RSN Overriding. otherwise the connection may fail or downgrade to + WPA2. + If the device is running the AIDL interface version 4 or later, this config item has + no effect. The feature will be enabled/disabled based on the chip capability for RSN + Overriding advertised via Supplicant AIDL wpa driver capability interface --> + <bool translatable="false" name ="config_wifiRsnOverridingEnabled">false</bool> </resources> diff --git a/service/ServiceWifiResources/res/values/overlayable.xml b/service/ServiceWifiResources/res/values/overlayable.xml index e736668dd1..7ca4fb85d2 100644 --- a/service/ServiceWifiResources/res/values/overlayable.xml +++ b/service/ServiceWifiResources/res/values/overlayable.xml @@ -83,6 +83,7 @@ <item type="bool" name="config_wifiSoftapResetAutoShutdownTimerConfig" /> <item type="bool" name="config_wifiSoftapResetMaxClientSettingConfig" /> <item type="bool" name="config_wifiSoftapAutoUpgradeToBridgedConfigWhenSupported" /> + <item type="bool" name="config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset" /> <item type="string" name="config_wifiSoftap2gChannelList" /> <item type="string" name="config_wifiSoftap5gChannelList" /> <item type="string" name="config_wifiSoftap6gChannelList" /> @@ -305,6 +306,7 @@ <item type="array" name="config_wifiExcludedFromUserApprovalForD2dInterfacePriority" /> <item type="bool" name="config_wifiUserApprovalNotRequireForDisconnectedP2p" /> <item type="integer" name="config_disconnectedP2pIfaceLowPriorityTimeoutMs" /> + <item type="array" name="config_wifiP2pAwareConcurrencyAllowlist" /> <item type="bool" name="config_wifiNetworkCentricQosPolicyFeatureEnabled" /> <item type="bool" name="config_wifiApplicationCentricQosPolicyFeatureEnabled" /> <item type="string" name="config_wifiDriverWorldModeCountryCode" /> @@ -342,9 +344,14 @@ <item type="integer" name="config_wifi80211azMaxTimeBetweenNtbMeasurementsMicros"/> <item type="bool" name="config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled" /> <item type="array" name="config_wifiTwtBlockedOuiList" /> + <item type="integer" name="config_wifiSoftApMaxNumberMLDSupported"/> <item type="bool" name="config_wifiSoftApSingleLinkMloInBridgedModeSupported" /> <item type="bool" name="config_wifiTwtSupported" /> + <item type="bool" name="config_wifiNetworkSelectionSetTargetBssid" /> <item type="bool" name="config_wifiWepAllowedControlSupported" /> + <item type="array" name="config_wifiDelayedSelectionCarrierIds" /> + <item type="integer" name="config_wifiDelayedCarrierSelectionTimeMs" /> + <item type="bool" name="config_wifiRsnOverridingEnabled" /> <!-- Params from config.xml that can be overlayed --> diff --git a/service/java/com/android/server/wifi/ActiveModeWarden.java b/service/java/com/android/server/wifi/ActiveModeWarden.java index fc6392c949..4daf2345c2 100644 --- a/service/java/com/android/server/wifi/ActiveModeWarden.java +++ b/service/java/com/android/server/wifi/ActiveModeWarden.java @@ -51,10 +51,12 @@ import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApState; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.DeviceMobilityState; import android.net.wifi.WifiScanner; +import android.net.wifi.util.WifiResourceCache; import android.os.BatteryStatsManager; import android.os.Build; import android.os.Handler; @@ -96,6 +98,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -103,7 +106,6 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -127,7 +129,7 @@ public class ActiveModeWarden { private final WifiInjector mWifiInjector; private final Looper mLooper; private final Handler mHandler; - private final Context mContext; + private final WifiContext mContext; private final WifiDiagnostics mWifiDiagnostics; private final WifiSettingsStore mSettingsStore; private final FrameworkFacade mFacade; @@ -169,7 +171,6 @@ public class ActiveModeWarden { private WorkSource mLastPrimaryClientModeManagerRequestorWs = null; @Nullable private WorkSource mLastScanOnlyClientModeManagerRequestorWs = null; - private AtomicLong mSupportedFeatureSet = new AtomicLong(0); private AtomicInteger mBandsSupported = new AtomicInteger(0); // Mutex lock between service Api binder thread and Wifi main thread private final Object mServiceApiLock = new Object(); @@ -177,6 +178,8 @@ public class ActiveModeWarden { private Network mCurrentNetwork; @GuardedBy("mServiceApiLock") private WifiInfo mCurrentConnectionInfo = new WifiInfo(); + @GuardedBy("mServiceApiLock") + private BitSet mSupportedFeatureSet = new BitSet(); @GuardedBy("mServiceApiLock") private final ArraySet<WorkSource> mRequestWs = new ArraySet<>(); @@ -191,6 +194,7 @@ public class ActiveModeWarden { private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_DISABLED); private ContentObserver mSatelliteModeContentObserver; + private final WifiResourceCache mResourceCache; /** * Method that allows the active ClientModeManager to set the wifi state that is @@ -380,7 +384,7 @@ public class ActiveModeWarden { DefaultClientModeManager defaultClientModeManager, BatteryStatsManager batteryStatsManager, WifiDiagnostics wifiDiagnostics, - Context context, + WifiContext context, WifiSettingsStore settingsStore, FrameworkFacade facade, WifiPermissionsUtil wifiPermissionsUtil, @@ -392,6 +396,7 @@ public class ActiveModeWarden { mLooper = looper; mHandler = new Handler(looper); mContext = context; + mResourceCache = mContext.getResourceCache(); mWifiDiagnostics = wifiDiagnostics; mSettingsStore = settingsStore; mFacade = facade; @@ -601,7 +606,7 @@ public class ActiveModeWarden { return false; } if (clientRole == ROLE_CLIENT_LOCAL_ONLY) { - if (!mContext.getResources().getBoolean( + if (!mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) { return false; } @@ -614,13 +619,13 @@ public class ActiveModeWarden { packageName, Build.VERSION_CODES.S, uid); } if (clientRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { - return mContext.getResources().getBoolean( + return mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled); } if (clientRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { - return mContext.getResources().getBoolean( + return mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled) - || mContext.getResources().getBoolean( + || mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled); } Log.e(TAG, "Unrecognized role=" + clientRole); @@ -640,7 +645,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForLocalOnlyConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled); } @@ -650,7 +655,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMbb() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled); } @@ -660,7 +665,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForRestrictedConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled); } @@ -670,20 +675,20 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMultiInternet() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled); } /** Begin listening to broadcasts and start the internal state machine. */ public void start() { - mContext.registerReceiver(new BroadcastReceiver() { + mContext.registerReceiverForAllUsers(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Location mode has been toggled... trigger with the scan change // update to make sure we are in the correct mode scanAlwaysModeChanged(); } - }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); + }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION), null, mHandler); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -706,7 +711,7 @@ public class ActiveModeWarden { emergencyCallbackModeChanged(emergencyMode); } }, new IntentFilter(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)); - boolean trackEmergencyCallState = mContext.getResources().getBoolean( + boolean trackEmergencyCallState = mResourceCache.getBoolean( R.bool.config_wifi_turn_off_during_emergency_call); if (trackEmergencyCallState) { mContext.registerReceiver(new BroadcastReceiver() { @@ -1490,16 +1495,16 @@ public class ActiveModeWarden { pw.println("STA + STA Concurrency Supported: " + isStaStaConcurrencySupported); if (isStaStaConcurrencySupported) { pw.println(" MBB use-case enabled: " - + mContext.getResources().getBoolean( + + mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)); pw.println(" Local only use-case enabled: " - + mContext.getResources().getBoolean( + + mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)); pw.println(" Restricted use-case enabled: " - + mContext.getResources().getBoolean( + + mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)); pw.println(" Multi internet use-case enabled: " - + mContext.getResources().getBoolean( + + mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)); } pw.println("STA + AP Concurrency Supported: " + mWifiNative.isStaApConcurrencySupported()); @@ -1743,7 +1748,8 @@ public class ActiveModeWarden { boolean scanEnabled = hasAnyClientModeManager(); boolean scanningForHiddenNetworksEnabled; - if (mContext.getResources().getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) { + if (mResourceCache + .getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) { scanningForHiddenNetworksEnabled = hasAnyClientModeManager(); } else { scanningForHiddenNetworksEnabled = hasAnyClientModeManagerInConnectivityRole(); @@ -1845,7 +1851,7 @@ public class ActiveModeWarden { WifiController() { super(TAG, mLooper); - final int threshold = mContext.getResources().getInteger( + final int threshold = mResourceCache.getInteger( R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); DefaultState defaultState = new DefaultState(threshold); mEnabledState = new EnabledState(threshold); @@ -1967,7 +1973,7 @@ public class ActiveModeWarden { } private int readWifiRecoveryDelay() { - int recoveryDelayMillis = mContext.getResources().getInteger( + int recoveryDelayMillis = mResourceCache.getInteger( R.integer.config_wifi_framework_recovery_timeout_delay); if (recoveryDelayMillis > MAX_RECOVERY_TIMEOUT_DELAY_MS) { recoveryDelayMillis = MAX_RECOVERY_TIMEOUT_DELAY_MS; @@ -2694,6 +2700,28 @@ public class ActiveModeWarden { // onStopped will move the state machine to "DisabledState". break; } + case CMD_RECOVERY_RESTART_WIFI_CONTINUE: { + log("received CMD_RECOVERY_RESTART_WIFI_CONTINUE when already in " + + "mEnabledState"); + // This could happen when SoftAp is turned on before recovery is complete. + // Simply make sure the primary CMM is on in this case. + if (shouldEnableSta() && !hasPrimaryOrScanOnlyModeManager()) { + startPrimaryOrScanOnlyClientModeManager( + // Assumes user toggled it on from settings before. + mFacade.getSettingsWorkSource(mContext)); + } + int numCallbacks = mRestartCallbacks.beginBroadcast(); + for (int i = 0; i < numCallbacks; i++) { + try { + mRestartCallbacks.getBroadcastItem(i).onSubsystemRestarted(); + } catch (RemoteException e) { + Log.e(TAG, "Failure calling onSubsystemRestarted" + e); + } + } + mRestartCallbacks.finishBroadcast(); + mWifiInjector.getSelfRecovery().onRecoveryCompleted(); + break; + } default: return NOT_HANDLED; } @@ -2729,86 +2757,85 @@ public class ActiveModeWarden { /** * Set the current supported Wifi feature set, called from primary client mode manager. - * @param supportedFeatureSet supported Wifi feature set + * @param wifiNativeFeatureSet feature set retrieved from WifiNative * @param isStaApConcurrencySupported true if Sta+Ap concurrency supported * @param isStaStaConcurrencySupported true if Sta+Sta concurrency supported */ - private void setSupportedFeatureSet(long supportedFeatureSet, + private void setSupportedFeatureSet(BitSet wifiNativeFeatureSet, boolean isStaApConcurrencySupported, boolean isStaStaConcurrencySupported) { - long concurrencyFeatureSet = 0L; + BitSet featureSet = (BitSet) wifiNativeFeatureSet.clone(); + + // Concurrency features if (isStaApConcurrencySupported) { - concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_AP_STA; + featureSet.set(WifiManager.WIFI_FEATURE_AP_STA); } if (isStaStaConcurrencySupported) { - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) { - concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY; + featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) { - concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB; + featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB); } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) { - concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED; + featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED); } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)) { - concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET; + featureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET); } } - long additionalFeatureSet = 0L; - long excludedFeatureSet = 0L; - // Mask the feature set against system properties. - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) { - // flags filled in by vendor HAL, remove if overlay disables it. - excludedFeatureSet |= - (WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT); - } - - if (!mContext.getResources().getBoolean( - R.bool.config_wifi_p2p_mac_randomization_supported)) { - // flags filled in by vendor HAL, remove if overlay disables it. - excludedFeatureSet |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC; - } - if (mContext.getResources().getBoolean( + // Additional features + if (mResourceCache.getBoolean( R.bool.config_wifi_connected_mac_randomization_supported)) { // no corresponding flags in vendor HAL, set if overlay enables it. - additionalFeatureSet |= WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; + featureSet.set(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC); } if (ApConfigUtil.isApMacRandomizationSupported(mContext)) { // no corresponding flags in vendor HAL, set if overlay enables it. - additionalFeatureSet |= WifiManager.WIFI_FEATURE_AP_RAND_MAC; + featureSet.set(WifiManager.WIFI_FEATURE_AP_RAND_MAC); } - if (ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)) { // The bridged mode requires the kernel network modules support. // It doesn't relate the vendor HAL, set if overlay enables it. - additionalFeatureSet |= WifiManager.WIFI_FEATURE_BRIDGED_AP; + featureSet.set(WifiManager.WIFI_FEATURE_BRIDGED_AP); } if (ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative)) { // The bridged mode requires the kernel network modules support. // It doesn't relate the vendor HAL, set if overlay enables it. - additionalFeatureSet |= WifiManager.WIFI_FEATURE_STA_BRIDGED_AP; + featureSet.set(WifiManager.WIFI_FEATURE_STA_BRIDGED_AP); } if (mWifiGlobals.isWepSupported()) { - additionalFeatureSet |= WifiManager.WIFI_FEATURE_WEP; + featureSet.set(WifiManager.WIFI_FEATURE_WEP); } if (!mWifiGlobals.isWpaPersonalDeprecated()) { // The WPA didn't be deprecated, set it. - additionalFeatureSet |= WifiManager.WIFI_FEATURE_WPA_PERSONAL; + featureSet.set(WifiManager.WIFI_FEATURE_WPA_PERSONAL); } if (mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()) { - additionalFeatureSet |= WifiManager.WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED; + featureSet.set(WifiManager.WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED); } - mSupportedFeatureSet.set( - (supportedFeatureSet | concurrencyFeatureSet | additionalFeatureSet) - & ~excludedFeatureSet); - if (mVerboseLoggingEnabled) { - Log.d(TAG, "setSupportedFeatureSet 0x" + Long.toHexString(mSupportedFeatureSet.get())); + + // Remove capabilities that are disabled by the system properties + if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) { + featureSet.clear(WifiManager.WIFI_FEATURE_D2D_RTT); + featureSet.clear(WifiManager.WIFI_FEATURE_D2AP_RTT); + } + if (!mResourceCache.getBoolean( + R.bool.config_wifi_p2p_mac_randomization_supported)) { + featureSet.clear(WifiManager.WIFI_FEATURE_P2P_RAND_MAC); + } + + synchronized (mServiceApiLock) { + mSupportedFeatureSet = featureSet; + if (mVerboseLoggingEnabled) { + Log.d(TAG, "setSupportedFeatureSet to " + mSupportedFeatureSet); + } } } @@ -2816,8 +2843,10 @@ public class ActiveModeWarden { * Get the current supported Wifi feature set. * @return supported Wifi feature set */ - public long getSupportedFeatureSet() { - return mSupportedFeatureSet.get(); + public @NonNull BitSet getSupportedFeatureSet() { + synchronized (mServiceApiLock) { + return mSupportedFeatureSet; + } } /** @@ -2920,4 +2949,21 @@ public class ActiveModeWarden { mSettingsStore.updateSatelliteModeTracker(); mWifiController.sendMessage(WifiController.CMD_SATELLITE_MODE_CHANGED); } + + /** + * Returns the number of 11be SoftApManagers which are being operated. + */ + public int getNumberOf11beSoftApManager() { + if (!SdkLevel.isAtLeastT()) { + return 0; + } + int numberOf11beSoftApManager = 0; + for (SoftApManager manager : mSoftApManagers) { + if (manager.isStarted() && manager.getSoftApModeConfiguration() + .getSoftApConfiguration().isIeee80211beEnabled()) { + numberOf11beSoftApManager++; + } + } + return numberOf11beSoftApManager; + } } diff --git a/service/java/com/android/server/wifi/ClientMode.java b/service/java/com/android/server/wifi/ClientMode.java index 7292de3338..7d3308469c 100644 --- a/service/java/com/android/server/wifi/ClientMode.java +++ b/service/java/com/android/server/wifi/ClientMode.java @@ -43,6 +43,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.BitSet; import java.util.List; import java.util.Set; @@ -136,7 +137,8 @@ public interface ClientMode { DhcpResultsParcelable syncGetDhcpResultsParcelable(); /** Get the supported feature set synchronously */ - long getSupportedFeatures(); + @NonNull + BitSet getSupportedFeatures(); boolean syncStartSubscriptionProvisioning(int callingUid, OsuProvider provider, IProvisioningCallback callback); diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 913ac9bf7b..b63f1c1af2 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -26,6 +26,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; import static android.net.wifi.WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; import static android.net.wifi.WifiManager.WIFI_FEATURE_TDLS; import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; +import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; @@ -34,6 +35,12 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LO import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED; import android.annotation.IntDef; @@ -175,6 +182,7 @@ import java.net.URL; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Map; @@ -697,7 +705,6 @@ public class ClientModeImpl extends StateMachine implements ClientMode { public static final int EAP_FAILURE_CODE_CERTIFICATE_EXPIRED = 32768; private boolean mCurrentConnectionReportedCertificateExpired = false; - /** Note that this constructor will also start() the StateMachine. */ public ClientModeImpl( @NonNull WifiContext context, @@ -1221,7 +1228,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_REMOVED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_REMOVED); // Log disconnection here, since the network config won't exist when the // disconnection event is received. String bssid = getConnectedBssidInternal(); @@ -1258,7 +1265,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { + " triggering disconnect"); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_WIFI7_TOGGLED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED); return; } @@ -1275,7 +1283,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!newConfig.trusted) { Log.w(getTag(), "Network marked untrusted, triggering disconnect"); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_UNTRUSTED); return; } } @@ -1283,7 +1292,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (isMetered) { Log.w(getTag(), "Network marked metered, triggering disconnect"); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_METERED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_METERED); return; } @@ -1299,7 +1308,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_TEMP_DISABLED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_TEMPORARY_DISABLED); } } @@ -1314,7 +1324,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (config.networkId == mTargetNetworkId || config.networkId == mLastNetworkId) { // Disconnect and let autojoin reselect a new network mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_PERM_DISABLED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_PERMANENT_DISABLED); } } } @@ -1334,7 +1345,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { && configuration.carrierMerged == merged) { Log.i(getTag(), "Carrier network offload disabled, triggering disconnect"); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_CARRIER_OFFLOAD_DISABLED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_CARRIER_OFFLOAD_DISABLED); } mWifiConnectivityManager.clearCachedCandidates(); } @@ -1640,7 +1652,14 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } private boolean isLinkLayerStatsSupported() { - return (getSupportedFeatures() & WIFI_FEATURE_LINK_LAYER_STATS) != 0; + return getSupportedFeatures().get(WIFI_FEATURE_LINK_LAYER_STATS); + } + + /** + * @return true if this device supports WPA3_SAE + */ + private boolean isWpa3SaeSupported() { + return getSupportedFeatures().get(WIFI_FEATURE_WPA3_SAE); } /** @@ -1668,6 +1687,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode { && cap.getMaxNumberAkms() >= 3) { mWifiGlobals.setWpa3SaeUpgradeOffloadEnabled(); } + if (SdkLevel.isAtLeastV() && mWifiNative.isSupplicantAidlServiceVersionAtLeast(3) + && isWpa3SaeSupported()) { + mWifiGlobals.enableWpa3SaeH2eSupport(); + } mWifiNative.setDeviceWiphyCapabilities(mInterfaceName, cap); } @@ -1961,7 +1984,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { /** * Get the supported feature set synchronously */ - public long getSupportedFeatures() { + public @NonNull BitSet getSupportedFeatures() { return mWifiNative.getSupportedFeatureSet(mInterfaceName); } @@ -2025,8 +2048,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * Check if a TDLS session can be established */ public boolean isTdlsOperationCurrentlyAvailable() { - return (getSupportedFeatures() & WIFI_FEATURE_TDLS) != 0 && isConnected() - && canEnableTdls(); + return getSupportedFeatures().get(WIFI_FEATURE_TDLS) && isConnected() && canEnableTdls(); } /** @@ -2430,6 +2452,12 @@ public class ClientModeImpl extends StateMachine implements ClientMode { case WifiMonitor.BSS_FREQUENCY_CHANGED_EVENT: sb.append(" frequency=" + msg.arg1); break; + case WifiMonitor.AUXILIARY_SUPPLICANT_EVENT: + SupplicantEventInfo eventInfo = (SupplicantEventInfo) msg.obj; + if (eventInfo != null) { + sb.append(" ").append(eventInfo.toString()); + } + break; default: sb.append(" "); sb.append(Integer.toString(msg.arg1)); @@ -2892,6 +2920,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setSuccessfulRxPacketsPerSecond(0); mWifiScoreReport.reset(); mLastLinkLayerStats = null; + if (isPrimary()) { + mWifiMetrics.resetWifiUnusableEvent(); + } updateCurrentConnectionInfo(); } @@ -3250,6 +3281,10 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.clearCurrentSecurityType(); mWifiInfo.resetMultiLinkInfo(); } + if (state == SupplicantState.SCANNING) { + // Set networkId only for matching Wi-Fi entry in UI. + mWifiInfo.setNetworkId(stateChangeResult.networkId); + } // SSID might have been updated, so call updateCapabilities updateCapabilities(); @@ -3737,19 +3772,18 @@ public class ClientModeImpl extends StateMachine implements ClientMode { ActiveModeManager.ClientRole clientRole = mClientModeManager.getRole(); if (clientRole == ROLE_CLIENT_PRIMARY) { return config != null && config.fromWifiNetworkSpecifier - ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY - : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY; + ? WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY + : WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY; } else if (clientRole == ROLE_CLIENT_LOCAL_ONLY) { - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY; + return WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY; } else if (clientRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { return mClientModeManager.isSecondaryInternet() - ? WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET - : WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED; + ? WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET + : WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED; } else if (clientRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { - return WifiStatsLog - .WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT; + return WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT; } - return WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS; + return WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS; } /** @@ -4043,9 +4077,11 @@ public class ClientModeImpl extends StateMachine implements ClientMode { WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE); /* DHCP times out after about 30 seconds, we do a - * disconnect thru supplicant, we will let autojoin retry connecting to the network + * disconnect through supplicant, we will let autojoin retry connecting to the network */ mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_IP_PROVISIONING_FAILURE; + mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, + StaEvent.DISCONNECT_IP_CONFIGURATION_LOST); mWifiNative.disconnect(mInterfaceName); updateCurrentConnectionInfo(); } @@ -4067,7 +4103,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NUD_FAILURE_ORGANIC; } // Disconnect via supplicant, and let autojoin retry connecting to the network. - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_IP_REACHABILITY_LOST); updateCurrentConnectionInfo(); } @@ -4131,6 +4167,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // processing the posted message sent from the legacy IpClientCallbacks instance, // see b/286338765. maybeShutdownIpclient(); + mTargetNetworkId = config.networkId; transitionTo(mWaitBeforeL3ProvisioningState); updateCurrentConnectionInfo(); @@ -4736,10 +4773,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { break; } if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { - mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_P2P_REQUESTED_DISCONNECT; - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); } else { mWifiNative.reconnect(mInterfaceName); } @@ -4840,6 +4876,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!isTrustOnFirstUseSupported()) { mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected); } + mFrameworkDisconnectReasonOverride = 0; connectToNetwork(config); break; } @@ -4992,7 +5029,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { loge("Disconnecting from Passpoint network due to an issue with the " + "Terms and Conditions URL"); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_PASSPOINT_TAC; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_PASSPOINT_TAC); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_PASSPOINT_TAC); } break; case WifiMonitor.HS20_REMEDIATION_EVENT: @@ -5299,7 +5337,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (vcnNetworkPolicy.isTeardownRequested()) { mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_VNC_REQUEST; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_VCN_REQUEST); } final NetworkCapabilities vcnCapability = vcnNetworkPolicy.getNetworkCapabilities(); if (!vcnCapability.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)) { @@ -5377,7 +5415,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * @param bssid BSSID of the AP. * @return true if BSSID matches to one of the affiliated link BSSIDs, false otherwise. */ - public boolean isAffiliatedLinkBssid(@NonNull MacAddress bssid) { + public boolean isAffiliatedLinkBssid(@Nullable MacAddress bssid) { + if (bssid == null) return false; List<MloLink> links = mWifiInfo.getAffiliatedMloLinks(); for (MloLink link: links) { if (bssid.equals(link.getApMacAddress())) { @@ -5747,7 +5786,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { logw("Connected to unknown networkId " + mLastNetworkId + ", disconnecting..."); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_UNKNOWN_NETWORK; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_UNKNOWN_NETWORK); break; } handleNetworkConnectionEventInfo(config, connectionInfo); @@ -6010,7 +6050,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // disconnect the network. if (disconnectRequired) { mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_UNTRUSTED); } break; } @@ -6366,9 +6407,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { WifiConfiguration.NetworkSelectionStatus .DISABLED_AUTHENTICATION_NO_CREDENTIALS); } - mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_GENERIC); - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NO_CREDENTIALS); } break; } @@ -6417,7 +6457,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { // In the TOFU flow, the user approval dialog is now displayed and the // network remains disconnected and disabled until it is approved. mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_UNTRUSTED; - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_NETWORK_UNTRUSTED); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_NETWORK_UNTRUSTED); mLeafCertSent = true; } break; @@ -6445,7 +6486,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (config == null) { logw("Connected to a network that's already been removed " + mLastNetworkId + ", disconnecting..."); - sendMessage(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_UNKNOWN_NETWORK); return; } @@ -6561,12 +6602,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (getConnectedWifiConfigurationInternal() == null || mNetworkAgent == null) { // The current config may have been removed while we were connecting, // trigger a disconnect to clear up state. - reportConnectionAttemptEnd( - WifiMetrics.ConnectionEvent.FAILURE_NETWORK_DISCONNECTION, - WifiMetricsProto.ConnectionEvent.HLF_NONE, - WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, 0); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_NETWORK_REMOVED; - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_UNKNOWN_NETWORK); } else { handleSuccessfulIpConfiguration(); transitionTo(mL3ConnectedState); @@ -6618,10 +6656,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } case WifiP2pServiceImpl.DISCONNECT_WIFI_REQUEST: { if (mWifiP2pConnection.shouldTemporarilyDisconnectWifi()) { - mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_P2P_REQUESTED_DISCONNECT; - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, + StaEvent.DISCONNECT_P2P_DISCONNECT_WIFI_REQUEST); } break; } @@ -6773,12 +6810,15 @@ public class ClientModeImpl extends StateMachine implements ClientMode { && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) { WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(mLastNetworkId); - if (config != null - && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED + if (config == null) { + break; + } + boolean isSimBasedNetwork = config.enterpriseConfig != null + && config.enterpriseConfig.isAuthenticationSimBased(); + boolean isLastSubReady = mWifiCarrierInfoManager.isSimReady(mLastSubId); + if ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) - || (config.enterpriseConfig != null - && config.enterpriseConfig.isAuthenticationSimBased() - && !mWifiCarrierInfoManager.isSimReady(mLastSubId)))) { + || (isSimBasedNetwork && !isLastSubReady)) { mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, StaEvent.DISCONNECT_RESET_SIM_NETWORKS); @@ -6786,7 +6826,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiNative.removeNetworkCachedData(mLastNetworkId); // remove network so that supplicant's PMKSA cache is cleared mWifiNative.removeAllNetworks(mInterfaceName); - if (isPrimary() && !mWifiCarrierInfoManager.isSimReady(mLastSubId)) { + if (isPrimary() && isSimBasedNetwork && !isLastSubReady) { mSimRequiredNotifier.showSimRequiredNotification( config, mLastSimBasedConnectionCarrierName); } @@ -6893,12 +6933,29 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } WifiLinkLayerStats stats = updateLinkLayerStatsRssiSpeedFrequencyCapabilities(txBytes, rxBytes); - mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats); // checkDataStallAndThroughputSufficiency() should be called before // mWifiScoreReport.calculateAndReportScore() which needs the latest throughput int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency( mInterfaceName, mLastConnectionCapabilities, mLastLinkLayerStats, stats, mWifiInfo, txBytes, rxBytes); + // This function will update stats that are used for WifiUsabilityStatsEntry and + // logScorerPredictionResult, so it should be called before + // mWifiMetrics.updateWifiUsabilityStatsEntries and + // mWifiMetrics.logScorerPredictionResult + mWifiMetrics.updateWiFiEvaluationAndScorerStats(mWifiScoreReport.getLingering(), + mWifiInfo, mLastConnectionCapabilities); + mWifiMetrics.updateWifiUsabilityStatsEntries(mInterfaceName, mWifiInfo, stats); + if (getClientRoleForMetrics(getConnectedWifiConfiguration()) + == WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY) { + mWifiMetrics.logScorerPredictionResult(mWifiInjector.hasActiveModem(), + mWifiCarrierInfoManager.hasActiveSubInfo(), + mWifiCarrierInfoManager.isMobileDataEnabled(), + mWifiGlobals.getPollRssiIntervalMillis(), + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation(), + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); + mWifiScoreReport.clearScorerPredictionStatusForEvaluation(); + } + if (mDataStallTriggerTimeMs == -1 && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) { mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis(); @@ -6997,6 +7054,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { case CMD_IPCLIENT_CREATED: { if (!isFromCurrentIpClientCallbacks(message)) break; mIpClient = (IpClientManager) message.obj; + setMulticastFilter(true); transitionTo(mL3ProvisioningState); break; } @@ -7224,9 +7282,8 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mRoamFailCount++; handleNetworkDisconnect(false, WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__ROAM_WATCHDOG_TIMER); - mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_ROAM_WATCHDOG_TIMER); - mWifiNative.disconnect(mInterfaceName); transitionTo(mDisconnectedState); } break; @@ -7377,8 +7434,6 @@ public class ClientModeImpl extends StateMachine implements ClientMode { switch (message.what) { case CMD_UNWANTED_NETWORK: { if (message.arg1 == NETWORK_STATUS_UNWANTED_DISCONNECT) { - mWifiMetrics.logStaEvent(mInterfaceName, StaEvent.TYPE_FRAMEWORK_DISCONNECT, - StaEvent.DISCONNECT_UNWANTED); if (mClientModeManager.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT && mClientModeManager.getPreviousRole() == ROLE_CLIENT_PRIMARY) { mWifiMetrics.incrementMakeBeforeBreakLingerCompletedCount( @@ -7403,7 +7458,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { DISABLED_UNWANTED_LOW_RSSI); } mFrameworkDisconnectReasonOverride = WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__DISCONNECT_UNWANTED_BY_CONNECTIVITY; - mWifiNative.disconnect(mInterfaceName); + sendMessageAtFrontOfQueue(CMD_DISCONNECT, StaEvent.DISCONNECT_UNWANTED); } else if (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN || message.arg1 == NETWORK_STATUS_UNWANTED_VALIDATION_FAILED) { Log.d(getTag(), (message.arg1 == NETWORK_STATUS_UNWANTED_DISABLE_AUTOJOIN @@ -8036,21 +8091,21 @@ public class ClientModeImpl extends StateMachine implements ClientMode { * @return true if this device supports FILS-SHA256 */ private boolean isFilsSha256Supported() { - return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA256) != 0; + return getSupportedFeatures().get(WIFI_FEATURE_FILS_SHA256); } /** * @return true if this device supports FILS-SHA384 */ private boolean isFilsSha384Supported() { - return (getSupportedFeatures() & WIFI_FEATURE_FILS_SHA384) != 0; + return getSupportedFeatures().get(WIFI_FEATURE_FILS_SHA384); } /** * @return true if this device supports Trust On First Use */ private boolean isTrustOnFirstUseSupported() { - return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0; + return getSupportedFeatures().get(WIFI_FEATURE_TRUST_ON_FIRST_USE); } /** diff --git a/service/java/com/android/server/wifi/ConcreteClientModeManager.java b/service/java/com/android/server/wifi/ConcreteClientModeManager.java index 3864262b56..a7c67031f1 100644 --- a/service/java/com/android/server/wifi/ConcreteClientModeManager.java +++ b/service/java/com/android/server/wifi/ConcreteClientModeManager.java @@ -75,6 +75,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Set; @@ -465,6 +466,8 @@ public class ConcreteClientModeManager implements ClientModeManager { return true; } } + } catch (UnsupportedOperationException ex) { + Log.d(TAG, "IMS Manager is not supported."); } catch (RuntimeException ex) { Log.e(TAG, "IMS Manager is not available.", ex); } @@ -1477,7 +1480,7 @@ public class ConcreteClientModeManager implements ClientModeManager { } @Override - public long getSupportedFeatures() { + public @NonNull BitSet getSupportedFeatures() { return getClientMode().getSupportedFeatures(); } diff --git a/service/java/com/android/server/wifi/DefaultClientModeManager.java b/service/java/com/android/server/wifi/DefaultClientModeManager.java index 450dd1e87e..b289640342 100644 --- a/service/java/com/android/server/wifi/DefaultClientModeManager.java +++ b/service/java/com/android/server/wifi/DefaultClientModeManager.java @@ -16,11 +16,13 @@ package com.android.server.wifi; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.WorkSource; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.BitSet; /** * This is used for creating a public {@link ClientModeManager} instance when wifi is off. @@ -81,8 +83,8 @@ public class DefaultClientModeManager implements ClientModeManager, ClientModeDe } @Override - public long getSupportedFeatures() { - return 0L; + public @NonNull BitSet getSupportedFeatures() { + return new BitSet(); } @Override diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java index ec5c4bfef9..3b777b6135 100644 --- a/service/java/com/android/server/wifi/DeviceConfigFacade.java +++ b/service/java/com/android/server/wifi/DeviceConfigFacade.java @@ -152,6 +152,7 @@ public class DeviceConfigFacade { // Maximum traffic stats threshold for link bandwidth estimator static final int DEFAULT_TRAFFIC_STATS_THRESHOLD_MAX_KB = 8000; static final int DEFAULT_BANDWIDTH_ESTIMATOR_TIME_CONSTANT_LARGE_SEC = 6; + static final String DEFAULT_DRY_RUN_SCORER_PKG_NAME = ""; // Cached values of fields updated via updateDeviceConfigFlags() private boolean mIsAbnormalConnectionBugreportEnabled; private int mAbnormalConnectionDurationMs; @@ -215,6 +216,8 @@ public class DeviceConfigFacade { private boolean mHighPerfLockDeprecated; private Optional<Boolean> mOobPseudonymEnabled = Optional.empty(); private Consumer<Boolean> mOobPseudonymFeatureFlagChangedListener = null; + private String mDryRunScorerPkgName; + private Consumer<String> mDryRunScorerPkgNameChangedListener = null; private boolean mApplicationQosPolicyApiEnabled; private boolean mAdjustPollRssiIntervalEnabled; private boolean mSoftwarePnoEnabled; @@ -412,6 +415,16 @@ public class DeviceConfigFacade { () -> mOobPseudonymFeatureFlagChangedListener.accept(oobPseudonymEnabled)); } mOobPseudonymEnabled = Optional.of(oobPseudonymEnabled); + + String dryRunScorerPkgName = DeviceConfig.getString(NAMESPACE, "dry_run_scorer_pkg_name", + DEFAULT_DRY_RUN_SCORER_PKG_NAME); + if (mDryRunScorerPkgNameChangedListener != null + && !dryRunScorerPkgName.equalsIgnoreCase(mDryRunScorerPkgName)) { + mWifiHandler.post( + () -> mDryRunScorerPkgNameChangedListener.accept(dryRunScorerPkgName)); + } + mDryRunScorerPkgName = dryRunScorerPkgName; + mApplicationQosPolicyApiEnabled = DeviceConfig.getBoolean(NAMESPACE, "application_qos_policy_api_enabled", true); mAdjustPollRssiIntervalEnabled = @@ -937,6 +950,18 @@ public class DeviceConfigFacade { mOobPseudonymFeatureFlagChangedListener = listener; } + /* + * Sets the listener to be notified when the DryRunScorerPkgName is changed. + * Only 1 listener is accepted. + */ + public void setDryRunScorerPkgNameChangedListener(Consumer<String> listener) { + mDryRunScorerPkgNameChangedListener = listener; + } + + public String getDryRunScorerPkgName() { + return mDryRunScorerPkgName; + } + /** * Get the set of bugreports that are explicitly disabled. * @return A Set of String to indicate disabled auto-bugreports trigger points. diff --git a/service/java/com/android/server/wifi/HalDeviceManager.java b/service/java/com/android/server/wifi/HalDeviceManager.java index 99f929c8f3..0974347660 100644 --- a/service/java/com/android/server/wifi/HalDeviceManager.java +++ b/service/java/com/android/server/wifi/HalDeviceManager.java @@ -19,6 +19,7 @@ package com.android.server.wifi; import static com.android.server.wifi.HalDeviceManagerUtil.jsonToStaticChipInfo; import static com.android.server.wifi.HalDeviceManagerUtil.staticChipInfoToJson; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; import android.annotation.IntDef; import android.annotation.NonNull; @@ -64,10 +65,10 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -82,8 +83,9 @@ public class HalDeviceManager { private final FeatureFlags mFeatureFlags; private boolean mDbg = false; - public static final long CHIP_CAPABILITY_ANY = 0L; - private static final long CHIP_CAPABILITY_UNINITIALIZED = -1L; + public static final BitSet CHIP_CAPABILITY_ANY = new BitSet(); + // TODO: Determine if CHIP_CAPABILITY_UNINITIALIZED can be replaced with an empty BitSet + private static final BitSet CHIP_CAPABILITY_UNINITIALIZED = longToBitset(-1L); private static final int DBS_24G_5G_MASK = WifiScanner.WIFI_BAND_24_GHZ | WifiScanner.WIFI_BAND_5_GHZ; @@ -321,8 +323,9 @@ public class HalDeviceManager { * @param concreteClientModeManager ConcreteClientModeManager requesting the interface. * @return A newly created interface - or null if the interface could not be created. */ - public WifiStaIface createStaIface( - long requiredChipCapabilities, + @VisibleForTesting + protected WifiStaIface createStaIface( + @NonNull BitSet requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs, @NonNull ConcreteClientModeManager concreteClientModeManager) { @@ -366,7 +369,7 @@ public class HalDeviceManager { * Create AP interface if possible (see createStaIface doc). */ public WifiApIface createApIface( - long requiredChipCapabilities, + @NonNull BitSet requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs, boolean isBridged, @NonNull SoftApManager softApManager, @NonNull List<OuiKeyedData> vendorData) { @@ -386,8 +389,9 @@ public class HalDeviceManager { /** * Create P2P interface if possible (see createStaIface doc). */ - public String createP2pIface( - long requiredChipCapabilities, + @VisibleForTesting + protected String createP2pIface( + @NonNull BitSet requiredChipCapabilities, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler, @NonNull WorkSource requestorWs) { WifiP2pIface iface = (WifiP2pIface) createIface(HDM_CREATE_IFACE_P2P, @@ -817,8 +821,9 @@ public class HalDeviceManager { * interface using rules based on the requestor app's context. * @return true if the device supports the provided combo, false otherwise. */ - public boolean isItPossibleToCreateIface(@HdmIfaceTypeForCreation int createIfaceType, - long requiredChipCapabilities, WorkSource requestorWs) { + @VisibleForTesting + protected boolean isItPossibleToCreateIface(@HdmIfaceTypeForCreation int createIfaceType, + BitSet requiredChipCapabilities, WorkSource requestorWs) { if (VDBG) { Log.d(TAG, "isItPossibleToCreateIface: createIfaceType=" + createIfaceType + ", requiredChipCapabilities=" + requiredChipCapabilities); @@ -862,7 +867,7 @@ public class HalDeviceManager { */ private List<WifiIfaceInfo> getIfacesToDestroyForRequest( @HdmIfaceTypeForCreation int createIfaceType, boolean queryForNewInterface, - long requiredChipCapabilities, WorkSource requestorWs) { + BitSet requiredChipCapabilities, WorkSource requestorWs) { if (VDBG) { Log.d(TAG, "getIfacesToDestroyForRequest: ifaceType=" + createIfaceType + ", requiredChipCapabilities=" + requiredChipCapabilities @@ -951,6 +956,14 @@ public class HalDeviceManager { public List<Pair<Integer, WorkSource>> reportImpactToCreateIface( @HdmIfaceTypeForCreation int createIfaceType, boolean queryForNewInterface, WorkSource requestorWs) { + if (!isWifiStarted()) { + if (canDeviceSupportCreateTypeCombo(new SparseArray<>() {{ + put(createIfaceType, 1); + }})) { + return Collections.emptyList(); + } + return null; + } List<WifiIfaceInfo> ifaces = getIfacesToDestroyForRequest(createIfaceType, queryForNewInterface, CHIP_CAPABILITY_ANY, requestorWs); if (ifaces == null) { @@ -1057,7 +1070,7 @@ public class HalDeviceManager { // Arrays of WifiIfaceInfo indexed by @HdmIfaceTypeForCreation, in order of creation as // returned by WifiChip.getXxxIfaceNames. public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[CREATE_TYPES_BY_PRIORITY.length][]; - public long chipCapabilities; + public BitSet chipCapabilities = new BitSet(); public List<WifiChip.WifiRadioCombination> radioCombinations = null; // A data structure for the faster band combination lookup. public Set<List<Integer>> bandCombinations = null; @@ -1199,7 +1212,7 @@ public class HalDeviceManager { return null; } - long chipCapabilities = getChipCapabilities(chip); + BitSet chipCapabilities = getChipCapabilities(chip); List<String> ifaceNames = chip.getStaIfaceNames(); if (ifaceNames == null) { @@ -1381,7 +1394,6 @@ public class HalDeviceManager { WifiChipInfo chipInfo = chipInfos[i]; staticChipInfos[i] = new StaticChipInfo( chipInfo.chipId, - chipInfo.chipCapabilities, chipInfo.availableModes); } return staticChipInfos; @@ -1607,7 +1619,7 @@ public class HalDeviceManager { } private WifiHal.WifiInterface createIface(@HdmIfaceTypeForCreation int createIfaceType, - long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, + BitSet requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData) { if (mDbg) { Log.d(TAG, "createIface: createIfaceType=" + createIfaceType @@ -1619,6 +1631,10 @@ public class HalDeviceManager { + "with NonNull destroyedListener but Null handler"); return null; } + if (requiredChipCapabilities == null) { + Log.wtf(TAG, "createIface received null required chip capabilities"); + return null; + } synchronized (mLock) { WifiChipInfo[] chipInfos = getAllChipInfo(false); @@ -1644,19 +1660,28 @@ public class HalDeviceManager { } } - private static boolean isChipCapabilitiesSupported(long currentChipCapabilities, - long requiredChipCapabilities) { - if (requiredChipCapabilities == CHIP_CAPABILITY_ANY) return true; - - if (CHIP_CAPABILITY_UNINITIALIZED == currentChipCapabilities) return true; + @VisibleForTesting + protected static boolean areChipCapabilitiesSupported(BitSet currentChipCapabilities, + BitSet requiredChipCapabilities) { + if (requiredChipCapabilities == null + || requiredChipCapabilities.equals(CHIP_CAPABILITY_ANY)) { + // No capabilities are required for this operation + return true; + } + if (currentChipCapabilities.equals(CHIP_CAPABILITY_UNINITIALIZED)) { + return true; + } - return (currentChipCapabilities & requiredChipCapabilities) - == requiredChipCapabilities; + // Check if the chip supports the required capabilities using + // (requiredChipCapabilities & currentChipCapabilities) == requiredChipCapabilities + BitSet tempRequiredCapabilities = (BitSet) requiredChipCapabilities.clone(); + tempRequiredCapabilities.and(currentChipCapabilities); + return tempRequiredCapabilities.equals(requiredChipCapabilities); } private IfaceCreationData getBestIfaceCreationProposal( WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType, - long requiredChipCapabilities, WorkSource requestorWs) { + BitSet requiredChipCapabilities, WorkSource requestorWs) { int targetHalIfaceType = HAL_IFACE_MAP.get(createIfaceType); if (VDBG) { Log.d(TAG, "getBestIfaceCreationProposal: chipInfos=" + Arrays.deepToString(chipInfos) @@ -1668,7 +1693,7 @@ public class HalDeviceManager { synchronized (mLock) { IfaceCreationData bestIfaceCreationProposal = null; for (WifiChipInfo chipInfo : chipInfos) { - if (!isChipCapabilitiesSupported( + if (!areChipCapabilitiesSupported( chipInfo.chipCapabilities, requiredChipCapabilities)) { continue; } @@ -1740,7 +1765,7 @@ public class HalDeviceManager { private WifiHal.WifiInterface createIfaceIfPossible( WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType, - long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, + BitSet requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs, @Nullable List<OuiKeyedData> vendorData) { int targetHalIfaceType = HAL_IFACE_MAP.get(createIfaceType); if (VDBG) { @@ -1851,6 +1876,22 @@ public class HalDeviceManager { } } + private boolean isRequestorAllowedToUseP2pNanConcurrency(WorkSource requestorWs) { + String[] allowlistArray = mContext.getResources().getStringArray( + R.array.config_wifiP2pAwareConcurrencyAllowlist); + if (allowlistArray == null || allowlistArray.length == 0) { + // No allowlist defined, so allow. + return true; + } + List<String> allowlist = Arrays.asList(allowlistArray); + for (int i = 0; i < requestorWs.size(); i++) { + if (allowlist.contains(requestorWs.getPackageName(i))) { + return true; + } + } + return false; + } + /** * Checks whether the input chip-create-type-combo can support the requested create type: * if not then returns null, if yes then returns information containing the list of interfaces @@ -1883,6 +1924,21 @@ public class HalDeviceManager { return null; } + // Remove P2P/NAN concurrency if the requestor isn't on the allowlist. + if ((requestedCreateType == HDM_CREATE_IFACE_P2P + || requestedCreateType == HDM_CREATE_IFACE_NAN) + && chipCreateTypeCombo[HDM_CREATE_IFACE_P2P] > 0 + && chipCreateTypeCombo[HDM_CREATE_IFACE_NAN] > 0) { + if (!isRequestorAllowedToUseP2pNanConcurrency(requestorWs)) { + chipCreateTypeCombo = chipCreateTypeCombo.clone(); + if (requestedCreateType == HDM_CREATE_IFACE_P2P) { + chipCreateTypeCombo[HDM_CREATE_IFACE_NAN] = 0; + } else { + chipCreateTypeCombo[HDM_CREATE_IFACE_P2P] = 0; + } + } + } + IfaceCreationData ifaceCreationData = new IfaceCreationData(); ifaceCreationData.chipInfo = chipInfo; ifaceCreationData.chipModeId = chipModeId; @@ -2492,6 +2548,7 @@ public class HalDeviceManager { return false; } + boolean success = false; synchronized (mLock) { WifiChip chip = getChip(iface); if (chip == null) { @@ -2504,7 +2561,6 @@ public class HalDeviceManager { return false; } - boolean success = false; switch (type) { case WifiChip.IFACE_TYPE_STA: mClientModeManagers.remove(name); @@ -2523,20 +2579,20 @@ public class HalDeviceManager { Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); return false; } + } - // dispatch listeners no matter what status - dispatchDestroyedListeners(name, type); - if (validateRttController) { - // Try to update the RttController - updateRttControllerWhenInterfaceChanges(); - } + // dispatch listeners no matter what status + dispatchDestroyedListeners(name, type); + if (validateRttController) { + // Try to update the RttController + updateRttControllerWhenInterfaceChanges(); + } - if (success) { - return true; - } else { - Log.e(TAG, "IWifiChip.removeXxxIface failed, name=" + name + ", type=" + type); - return false; - } + if (success) { + return true; + } else { + Log.e(TAG, "IWifiChip.removeXxxIface failed, name=" + name + ", type=" + type); + return false; } } @@ -2546,20 +2602,19 @@ public class HalDeviceManager { // onlyOnOtherThreads = false: call all listeners private void dispatchDestroyedListeners(String name, int type) { if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name); + InterfaceCacheEntry entry; + List<InterfaceDestroyedListenerProxy> triggerList; synchronized (mLock) { - InterfaceCacheEntry entry = mInterfaceInfoCache.remove(Pair.create(name, type)); + entry = mInterfaceInfoCache.remove(Pair.create(name, type)); if (entry == null) { Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name); return; } - - Iterator<InterfaceDestroyedListenerProxy> iterator = - entry.destroyedListeners.iterator(); - while (iterator.hasNext()) { - InterfaceDestroyedListenerProxy listener = iterator.next(); - iterator.remove(); - listener.action(); - } + triggerList = new ArrayList<>(entry.destroyedListeners); + entry.destroyedListeners.clear(); + } + for (InterfaceDestroyedListenerProxy listener : triggerList) { + listener.action(); } } @@ -2570,9 +2625,7 @@ public class HalDeviceManager { List<InterfaceDestroyedListenerProxy> triggerList = new ArrayList<>(); synchronized (mLock) { for (InterfaceCacheEntry cacheEntry: mInterfaceInfoCache.values()) { - for (InterfaceDestroyedListenerProxy listener : cacheEntry.destroyedListeners) { - triggerList.add(listener); - } + triggerList.addAll(cacheEntry.destroyedListeners); cacheEntry.destroyedListeners.clear(); // for insurance } mInterfaceInfoCache.clear(); @@ -2821,10 +2874,10 @@ public class HalDeviceManager { * @param wifiChip WifiChip to get the features for. * @return Bitset of WifiManager.WIFI_FEATURE_* values. */ - public long getChipCapabilities(@NonNull WifiChip wifiChip) { - if (wifiChip == null) return 0; + private BitSet getChipCapabilities(@NonNull WifiChip wifiChip) { + if (wifiChip == null) return new BitSet(); - WifiChip.Response<Long> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist(); + WifiChip.Response<BitSet> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist(); if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS) { return capsResp.getValue(); } else if (capsResp.getStatusCode() != WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION) { @@ -2832,7 +2885,7 @@ public class HalDeviceManager { // does not support getting capabilities before creating an interface. return CHIP_CAPABILITY_UNINITIALIZED; } else { // remote exception - return 0; + return new BitSet(); } } diff --git a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java index 5897307522..09aa486ef0 100644 --- a/service/java/com/android/server/wifi/HalDeviceManagerUtil.java +++ b/service/java/com/android/server/wifi/HalDeviceManagerUtil.java @@ -33,15 +33,12 @@ import java.util.List; public class HalDeviceManagerUtil { static class StaticChipInfo { private int mChipId; - private long mChipCapabilities; private @NonNull ArrayList<WifiChip.ChipMode> mAvailableModes = new ArrayList<>(); StaticChipInfo( int chipId, - long chipCapabilities, @NonNull ArrayList<WifiChip.ChipMode> availableModes) { mChipId = chipId; - mChipCapabilities = chipCapabilities; if (availableModes != null) { mAvailableModes = availableModes; } @@ -51,24 +48,18 @@ public class HalDeviceManagerUtil { return mChipId; } - long getChipCapabilities() { - return mChipCapabilities; - } - ArrayList<WifiChip.ChipMode> getAvailableModes() { return mAvailableModes; } } private static final String KEY_CHIP_ID = "chipId"; - private static final String KEY_CHIP_CAPABILITIES = "chipCapabilities"; private static final String KEY_AVAILABLE_MODES = "availableModes"; static JSONObject staticChipInfoToJson(@NonNull StaticChipInfo staticChipInfo) throws JSONException { JSONObject jsonObject = new JSONObject(); jsonObject.put(KEY_CHIP_ID, staticChipInfo.getChipId()); - jsonObject.put(KEY_CHIP_CAPABILITIES, staticChipInfo.getChipCapabilities()); JSONArray availableModesJson = new JSONArray(); for (WifiChip.ChipMode mode : staticChipInfo.getAvailableModes()) { availableModesJson.put(chipModeToJson(mode)); @@ -80,12 +71,11 @@ public class HalDeviceManagerUtil { static StaticChipInfo jsonToStaticChipInfo(JSONObject jsonObject) throws JSONException { ArrayList<WifiChip.ChipMode> availableModes = new ArrayList<>(); int chipId = jsonObject.getInt(KEY_CHIP_ID); - long chipCapabilities = jsonObject.getLong(KEY_CHIP_CAPABILITIES); JSONArray modesJson = jsonObject.getJSONArray(KEY_AVAILABLE_MODES); for (int i = 0; i < modesJson.length(); i++) { availableModes.add(jsonToChipMode(modesJson.getJSONObject(i))); } - return new StaticChipInfo(chipId, chipCapabilities, availableModes); + return new StaticChipInfo(chipId, availableModes); } private static final String KEY_ID = "id"; diff --git a/service/java/com/android/server/wifi/HostapdHal.java b/service/java/com/android/server/wifi/HostapdHal.java index dbb7c705ff..7d7b2bfda2 100644 --- a/service/java/com/android/server/wifi/HostapdHal.java +++ b/service/java/com/android/server/wifi/HostapdHal.java @@ -16,9 +16,9 @@ package com.android.server.wifi; import android.annotation.NonNull; -import android.content.Context; import android.net.MacAddress; import android.net.wifi.SoftApConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.os.Handler; import android.util.Log; @@ -42,13 +42,13 @@ public class HostapdHal { private final Object mLock = new Object(); private boolean mVerboseLoggingEnabled = false; private boolean mVerboseHalLoggingEnabled = false; - private final Context mContext; + private final WifiContext mContext; private final Handler mEventHandler; // Hostapd HAL interface object - might be implemented by HIDL or AIDL private IHostapdHal mIHostapd; - public HostapdHal(Context context, Handler handler) { + public HostapdHal(WifiContext context, Handler handler) { mContext = context; mEventHandler = handler; } diff --git a/service/java/com/android/server/wifi/HostapdHalAidlImp.java b/service/java/com/android/server/wifi/HostapdHalAidlImp.java index ffca0c3526..77d2b50849 100644 --- a/service/java/com/android/server/wifi/HostapdHalAidlImp.java +++ b/service/java/com/android/server/wifi/HostapdHalAidlImp.java @@ -16,7 +16,6 @@ package com.android.server.wifi; import android.annotation.NonNull; -import android.content.Context; import android.hardware.wifi.hostapd.ApInfo; import android.hardware.wifi.hostapd.BandMask; import android.hardware.wifi.hostapd.ChannelBandwidth; @@ -33,13 +32,16 @@ import android.hardware.wifi.hostapd.Ieee80211ReasonCode; import android.hardware.wifi.hostapd.IfaceParams; import android.hardware.wifi.hostapd.NetworkParams; import android.net.MacAddress; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.OuiKeyedData; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.BandType; import android.net.wifi.SoftApInfo; import android.net.wifi.WifiAnnotations; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; +import android.net.wifi.util.WifiResourceCache; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; @@ -84,7 +86,7 @@ public class HostapdHalAidlImp implements IHostapdHal { private final Object mLock = new Object(); private boolean mVerboseLoggingEnabled = false; private boolean mVerboseHalLoggingEnabled = false; - private final Context mContext; + private final WifiContext mContext; private final Handler mEventHandler; // Hostapd HAL interface objects @@ -96,6 +98,7 @@ public class HostapdHalAidlImp implements IHostapdHal { private boolean mServiceDeclared = false; private int mServiceVersion; private CountDownLatch mWaitForDeathLatch; + private final WifiResourceCache mResourceCache; /** * Default death recipient. Called any time the service dies. @@ -127,9 +130,10 @@ public class HostapdHalAidlImp implements IHostapdHal { } } - public HostapdHalAidlImp(@NonNull Context context, @NonNull Handler handler) { + public HostapdHalAidlImp(@NonNull WifiContext context, @NonNull Handler handler) { mContext = context; mEventHandler = handler; + mResourceCache = mContext.getResourceCache(); Log.d(TAG, "init HostapdHalAidlImp"); } @@ -380,14 +384,23 @@ public class HostapdHalAidlImp implements IHostapdHal { public void onFailure(String ifaceName, String instanceName) { Log.w(TAG, "Failure on iface " + ifaceName + ", instance: " + instanceName); Runnable onFailureListener = mSoftApFailureListeners.get(ifaceName); - SoftApHalCallback callback = mSoftApHalCallbacks.get(ifaceName); - if (onFailureListener != null) { - mActiveInstances.remove(instanceName); - if (mActiveInstances.size() == 0) { + if (onFailureListener != null && ifaceName != null) { + if (ifaceName.equals(instanceName)) { + // Single AP onFailureListener.run(); - } else if (callback != null) { - callback.onInstanceFailure(instanceName); + } else { + // Bridged AP + if (mActiveInstances.contains(instanceName)) { + SoftApHalCallback callback = mSoftApHalCallbacks.get(ifaceName); + if (callback != null) { + callback.onInstanceFailure(instanceName); + } + } else { + Log.w(TAG, "Ignore error for inactive instances"); + + } } + mActiveInstances.remove(instanceName); } } @@ -421,8 +434,12 @@ public class HostapdHalAidlImp implements IHostapdHal { + " isConnected: " + info.isConnected); SoftApHalCallback callback = mSoftApHalCallbacks.get(info.ifaceName); if (callback != null) { + int disconnectReasonCode = isServiceVersionAtLeast(3) && !info.isConnected + ? mapHalToFrameworkDeauthenticationReasonCode(info.disconnectReasonCode) + : DeauthenticationReasonCode.REASON_UNKNOWN; callback.onConnectedClientsChanged(info.apIfaceInstance, - MacAddress.fromBytes(info.clientAddress), info.isConnected); + MacAddress.fromBytes(info.clientAddress), info.isConnected, + disconnectReasonCode); } } catch (IllegalArgumentException iae) { Log.e(TAG, " Invalid clientAddress, " + iae); @@ -688,15 +705,15 @@ public class HostapdHalAidlImp implements IHostapdHal { String oemConfig; switch (band) { case SoftApConfiguration.BAND_2GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap2gChannelList); break; case SoftApConfiguration.BAND_5GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap5gChannelList); break; case SoftApConfiguration.BAND_6GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap6gChannelList); break; default: @@ -844,6 +861,175 @@ public class HostapdHalAidlImp implements IHostapdHal { } } + /** + * Convert from a HAL DeauthenticationReasonCode to its framework equivalent. + * + * @param deauthenticationReasonCode The deauthentication reason code defined in HAL. + * @return The corresponding {@link DeauthenticationReasonCode}. + */ + @VisibleForTesting + @WifiAnnotations.SoftApDisconnectReason int mapHalToFrameworkDeauthenticationReasonCode( + int deauthenticationReasonCode) { + return switch (deauthenticationReasonCode) { + case android.hardware.wifi.common.DeauthenticationReasonCode.HOSTAPD_NO_REASON -> + DeauthenticationReasonCode.REASON_UNKNOWN; + case android.hardware.wifi.common.DeauthenticationReasonCode.UNSPECIFIED -> + DeauthenticationReasonCode.REASON_UNSPECIFIED; + case android.hardware.wifi.common.DeauthenticationReasonCode.PREV_AUTH_NOT_VALID -> + DeauthenticationReasonCode.REASON_PREV_AUTH_NOT_VALID; + case android.hardware.wifi.common.DeauthenticationReasonCode.DEAUTH_LEAVING -> + DeauthenticationReasonCode.REASON_DEAUTH_LEAVING; + case android.hardware.wifi.common + .DeauthenticationReasonCode.DISASSOC_DUE_TO_INACTIVITY -> + DeauthenticationReasonCode.REASON_DISASSOC_DUE_TO_INACTIVITY; + case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_AP_BUSY -> + DeauthenticationReasonCode.REASON_DISASSOC_AP_BUSY; + case android.hardware.wifi.common + .DeauthenticationReasonCode.CLASS2_FRAME_FROM_NONAUTH_STA -> + DeauthenticationReasonCode.REASON_CLASS2_FRAME_FROM_NONAUTH_STA; + case android.hardware.wifi.common + .DeauthenticationReasonCode.CLASS3_FRAME_FROM_NONASSOC_STA -> + DeauthenticationReasonCode.REASON_CLASS3_FRAME_FROM_NONASSOC_STA; + case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_STA_HAS_LEFT -> + DeauthenticationReasonCode.REASON_DISASSOC_STA_HAS_LEFT; + case android.hardware.wifi.common + .DeauthenticationReasonCode.STA_REQ_ASSOC_WITHOUT_AUTH -> + DeauthenticationReasonCode.REASON_STA_REQ_ASSOC_WITHOUT_AUTH; + case android.hardware.wifi.common + .DeauthenticationReasonCode.PWR_CAPABILITY_NOT_VALID -> + DeauthenticationReasonCode.REASON_PWR_CAPABILITY_NOT_VALID; + case android.hardware.wifi.common + .DeauthenticationReasonCode.SUPPORTED_CHANNEL_NOT_VALID -> + DeauthenticationReasonCode.REASON_SUPPORTED_CHANNEL_NOT_VALID; + case android.hardware.wifi.common.DeauthenticationReasonCode.BSS_TRANSITION_DISASSOC -> + DeauthenticationReasonCode.REASON_BSS_TRANSITION_DISASSOC; + case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_IE -> + DeauthenticationReasonCode.REASON_INVALID_IE; + case android.hardware.wifi.common.DeauthenticationReasonCode.MICHAEL_MIC_FAILURE -> + DeauthenticationReasonCode.REASON_MICHAEL_MIC_FAILURE; + case android.hardware.wifi.common + .DeauthenticationReasonCode.FOURWAY_HANDSHAKE_TIMEOUT -> + DeauthenticationReasonCode.REASON_FOURWAY_HANDSHAKE_TIMEOUT; + case android.hardware.wifi.common + .DeauthenticationReasonCode.GROUP_KEY_UPDATE_TIMEOUT -> + DeauthenticationReasonCode.REASON_GROUP_KEY_UPDATE_TIMEOUT; + case android.hardware.wifi.common.DeauthenticationReasonCode.IE_IN_4WAY_DIFFERS -> + DeauthenticationReasonCode.REASON_IE_IN_4WAY_DIFFERS; + case android.hardware.wifi.common.DeauthenticationReasonCode.GROUP_CIPHER_NOT_VALID -> + DeauthenticationReasonCode.REASON_GROUP_CIPHER_NOT_VALID; + case android.hardware.wifi.common + .DeauthenticationReasonCode.PAIRWISE_CIPHER_NOT_VALID -> + DeauthenticationReasonCode.REASON_PAIRWISE_CIPHER_NOT_VALID; + case android.hardware.wifi.common.DeauthenticationReasonCode.AKMP_NOT_VALID -> + DeauthenticationReasonCode.REASON_AKMP_NOT_VALID; + case android.hardware.wifi.common + .DeauthenticationReasonCode.UNSUPPORTED_RSN_IE_VERSION -> + DeauthenticationReasonCode.REASON_UNSUPPORTED_RSN_IE_VERSION; + case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_RSN_IE_CAPAB -> + DeauthenticationReasonCode.REASON_INVALID_RSN_IE_CAPAB; + case android.hardware.wifi.common.DeauthenticationReasonCode.IEEE_802_1X_AUTH_FAILED -> + DeauthenticationReasonCode.REASON_IEEE_802_1X_AUTH_FAILED; + case android.hardware.wifi.common.DeauthenticationReasonCode.CIPHER_SUITE_REJECTED -> + DeauthenticationReasonCode.REASON_CIPHER_SUITE_REJECTED; + case android.hardware.wifi.common + .DeauthenticationReasonCode.TDLS_TEARDOWN_UNREACHABLE -> + DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNREACHABLE; + case android.hardware.wifi.common + .DeauthenticationReasonCode.TDLS_TEARDOWN_UNSPECIFIED -> + DeauthenticationReasonCode.REASON_TDLS_TEARDOWN_UNSPECIFIED; + case android.hardware.wifi.common.DeauthenticationReasonCode.SSP_REQUESTED_DISASSOC -> + DeauthenticationReasonCode.REASON_SSP_REQUESTED_DISASSOC; + case android.hardware.wifi.common + .DeauthenticationReasonCode.NO_SSP_ROAMING_AGREEMENT -> + DeauthenticationReasonCode.REASON_NO_SSP_ROAMING_AGREEMENT; + case android.hardware.wifi.common.DeauthenticationReasonCode.BAD_CIPHER_OR_AKM -> + DeauthenticationReasonCode.REASON_BAD_CIPHER_OR_AKM; + case android.hardware.wifi.common + .DeauthenticationReasonCode.NOT_AUTHORIZED_THIS_LOCATION -> + DeauthenticationReasonCode.REASON_NOT_AUTHORIZED_THIS_LOCATION; + case android.hardware.wifi.common + .DeauthenticationReasonCode.SERVICE_CHANGE_PRECLUDES_TS -> + DeauthenticationReasonCode.REASON_SERVICE_CHANGE_PRECLUDES_TS; + case android.hardware.wifi.common.DeauthenticationReasonCode.UNSPECIFIED_QOS_REASON -> + DeauthenticationReasonCode.REASON_UNSPECIFIED_QOS_REASON; + case android.hardware.wifi.common.DeauthenticationReasonCode.NOT_ENOUGH_BANDWIDTH -> + DeauthenticationReasonCode.REASON_NOT_ENOUGH_BANDWIDTH; + case android.hardware.wifi.common.DeauthenticationReasonCode.DISASSOC_LOW_ACK -> + DeauthenticationReasonCode.REASON_DISASSOC_LOW_ACK; + case android.hardware.wifi.common.DeauthenticationReasonCode.EXCEEDED_TXOP -> + DeauthenticationReasonCode.REASON_EXCEEDED_TXOP; + case android.hardware.wifi.common.DeauthenticationReasonCode.STA_LEAVING -> + DeauthenticationReasonCode.REASON_STA_LEAVING; + case android.hardware.wifi.common.DeauthenticationReasonCode.END_TS_BA_DLS -> + DeauthenticationReasonCode.REASON_END_TS_BA_DLS; + case android.hardware.wifi.common.DeauthenticationReasonCode.UNKNOWN_TS_BA -> + DeauthenticationReasonCode.REASON_UNKNOWN_TS_BA; + case android.hardware.wifi.common.DeauthenticationReasonCode.TIMEOUT -> + DeauthenticationReasonCode.REASON_TIMEOUT; + case android.hardware.wifi.common.DeauthenticationReasonCode.PEERKEY_MISMATCH -> + DeauthenticationReasonCode.REASON_PEERKEY_MISMATCH; + case android.hardware.wifi.common + .DeauthenticationReasonCode.AUTHORIZED_ACCESS_LIMIT_REACHED -> + DeauthenticationReasonCode.REASON_AUTHORIZED_ACCESS_LIMIT_REACHED; + case android.hardware.wifi.common + .DeauthenticationReasonCode.EXTERNAL_SERVICE_REQUIREMENTS -> + DeauthenticationReasonCode.REASON_EXTERNAL_SERVICE_REQUIREMENTS; + case android.hardware.wifi.common + .DeauthenticationReasonCode.INVALID_FT_ACTION_FRAME_COUNT -> + DeauthenticationReasonCode.REASON_INVALID_FT_ACTION_FRAME_COUNT; + case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_PMKID -> + DeauthenticationReasonCode.REASON_INVALID_PMKID; + case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_MDE -> + DeauthenticationReasonCode.REASON_INVALID_MDE; + case android.hardware.wifi.common.DeauthenticationReasonCode.INVALID_FTE -> + DeauthenticationReasonCode.REASON_INVALID_FTE; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_PEERING_CANCELLED -> + DeauthenticationReasonCode.REASON_MESH_PEERING_CANCELLED; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_MAX_PEERS -> + DeauthenticationReasonCode.REASON_MESH_MAX_PEERS; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_CONFIG_POLICY_VIOLATION -> + DeauthenticationReasonCode.REASON_MESH_CONFIG_POLICY_VIOLATION; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_CLOSE_RCVD -> + DeauthenticationReasonCode.REASON_MESH_CLOSE_RCVD; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_MAX_RETRIES -> + DeauthenticationReasonCode.REASON_MESH_MAX_RETRIES; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_CONFIRM_TIMEOUT -> + DeauthenticationReasonCode.REASON_MESH_CONFIRM_TIMEOUT; + case android.hardware.wifi.common.DeauthenticationReasonCode.MESH_INVALID_GTK -> + DeauthenticationReasonCode.REASON_MESH_INVALID_GTK; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_INCONSISTENT_PARAMS -> + DeauthenticationReasonCode.REASON_MESH_INCONSISTENT_PARAMS; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_INVALID_SECURITY_CAP -> + DeauthenticationReasonCode.REASON_MESH_INVALID_SECURITY_CAP; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_PATH_ERROR_NO_PROXY_INFO -> + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_PROXY_INFO; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_PATH_ERROR_NO_FORWARDING_INFO -> + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_PATH_ERROR_DEST_UNREACHABLE -> + DeauthenticationReasonCode.REASON_MESH_PATH_ERROR_DEST_UNREACHABLE; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS -> + DeauthenticationReasonCode.REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_CHANNEL_SWITCH_REGULATORY_REQ -> + DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ; + case android.hardware.wifi.common + .DeauthenticationReasonCode.MESH_CHANNEL_SWITCH_UNSPECIFIED -> + DeauthenticationReasonCode.REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED; + default -> { + Log.e(TAG, "Invalid DeauthenticationReasonCode: " + + deauthenticationReasonCode); + yield DeauthenticationReasonCode.REASON_UNKNOWN; + } + }; + } + private NetworkParams prepareNetworkParams(boolean isMetered, SoftApConfiguration config) { NetworkParams nwParams = new NetworkParams(); @@ -901,20 +1087,20 @@ public class HostapdHalAidlImp implements IHostapdHal { private HwModeParams prepareHwModeParams(SoftApConfiguration config) { HwModeParams hwModeParams = new HwModeParams(); hwModeParams.enable80211N = true; - hwModeParams.enable80211AC = mContext.getResources().getBoolean( + hwModeParams.enable80211AC = mResourceCache.getBoolean( R.bool.config_wifi_softap_ieee80211ac_supported); hwModeParams.enable80211AX = ApConfigUtil.isIeee80211axSupported(mContext); //Update 80211ax support with the configuration. hwModeParams.enable80211AX &= config.isIeee80211axEnabledInternal(); hwModeParams.enable6GhzBand = ApConfigUtil.isBandSupported( SoftApConfiguration.BAND_6GHZ, mContext); - hwModeParams.enableHeSingleUserBeamformer = mContext.getResources().getBoolean( + hwModeParams.enableHeSingleUserBeamformer = mResourceCache.getBoolean( R.bool.config_wifiSoftapHeSuBeamformerSupported); - hwModeParams.enableHeSingleUserBeamformee = mContext.getResources().getBoolean( + hwModeParams.enableHeSingleUserBeamformee = mResourceCache.getBoolean( R.bool.config_wifiSoftapHeSuBeamformeeSupported); - hwModeParams.enableHeMultiUserBeamformer = mContext.getResources().getBoolean( + hwModeParams.enableHeMultiUserBeamformer = mResourceCache.getBoolean( R.bool.config_wifiSoftapHeMuBeamformerSupported); - hwModeParams.enableHeTargetWakeTime = mContext.getResources().getBoolean( + hwModeParams.enableHeTargetWakeTime = mResourceCache.getBoolean( R.bool.config_wifiSoftapHeTwtSupported); if (SdkLevel.isAtLeastT()) { @@ -954,7 +1140,7 @@ public class HostapdHalAidlImp implements IHostapdHal { channelParamsList[i].bandMask = getHalBandMask(band); channelParamsList[i].acsChannelFreqRangesMhz = new FrequencyRange[0]; if (channelParamsList[i].enableAcs) { - channelParamsList[i].acsShouldExcludeDfs = !mContext.getResources() + channelParamsList[i].acsShouldExcludeDfs = !mResourceCache .getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs); if (ApConfigUtil.isSendFreqRangesNeeded(band, mContext, config)) { prepareAcsChannelFreqRangesMhz(channelParamsList[i], band, config); diff --git a/service/java/com/android/server/wifi/HostapdHalHidlImp.java b/service/java/com/android/server/wifi/HostapdHalHidlImp.java index 1dc63f03dd..209774630e 100644 --- a/service/java/com/android/server/wifi/HostapdHalHidlImp.java +++ b/service/java/com/android/server/wifi/HostapdHalHidlImp.java @@ -16,7 +16,6 @@ package com.android.server.wifi; import android.annotation.NonNull; -import android.content.Context; import android.hardware.wifi.hostapd.V1_0.HostapdStatus; import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode; import android.hardware.wifi.hostapd.V1_0.IHostapd; @@ -27,11 +26,14 @@ import android.hardware.wifi.hostapd.V1_3.Generation; import android.hidl.manager.V1_0.IServiceManager; import android.hidl.manager.V1_0.IServiceNotification; import android.net.MacAddress; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.ScanResult; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.BandType; import android.net.wifi.SoftApInfo; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; +import android.net.wifi.util.WifiResourceCache; import android.os.Handler; import android.os.IHwBinder.DeathRecipient; import android.os.RemoteException; @@ -74,7 +76,7 @@ public class HostapdHalHidlImp implements IHostapdHal { private final Object mLock = new Object(); private boolean mVerboseLoggingEnabled = false; private boolean mVerboseHalLoggingEnabled = false; - private final Context mContext; + private final WifiContext mContext; private final Handler mEventHandler; // Hostapd HAL interface objects @@ -87,6 +89,7 @@ public class HostapdHalHidlImp implements IHostapdHal { private HostapdDeathRecipient mHostapdDeathRecipient; // Death recipient cookie registered for current hostapd instance. private long mDeathRecipientCookie = 0; + private final WifiResourceCache mResourceCache; private final IServiceNotification mServiceNotificationCallback = new IServiceNotification.Stub() { @@ -131,11 +134,12 @@ public class HostapdHalHidlImp implements IHostapdHal { } } - public HostapdHalHidlImp(@NonNull Context context, @NonNull Handler handler) { + public HostapdHalHidlImp(@NonNull WifiContext context, @NonNull Handler handler) { mContext = context; mEventHandler = handler; mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient(); mHostapdDeathRecipient = new HostapdDeathRecipient(); + mResourceCache = mContext.getResourceCache(); Log.d(TAG, "init HostapdHalHidlImp"); } @@ -790,16 +794,16 @@ public class HostapdHalHidlImp implements IHostapdHal { ifaceParams12.hwModeParams.enable6GhzBand = ApConfigUtil.isBandSupported(SoftApConfiguration.BAND_6GHZ, mContext); ifaceParams12.hwModeParams.enableHeSingleUserBeamformer = - mContext.getResources().getBoolean( + mResourceCache.getBoolean( R.bool.config_wifiSoftapHeSuBeamformerSupported); ifaceParams12.hwModeParams.enableHeSingleUserBeamformee = - mContext.getResources().getBoolean( + mResourceCache.getBoolean( R.bool.config_wifiSoftapHeSuBeamformeeSupported); ifaceParams12.hwModeParams.enableHeMultiUserBeamformer = - mContext.getResources().getBoolean( + mResourceCache.getBoolean( R.bool.config_wifiSoftapHeMuBeamformerSupported); ifaceParams12.hwModeParams.enableHeTargetWakeTime = - mContext.getResources().getBoolean(R.bool.config_wifiSoftapHeTwtSupported); + mResourceCache.getBoolean(R.bool.config_wifiSoftapHeTwtSupported); } private android.hardware.wifi.hostapd.V1_0.IHostapd.IfaceParams @@ -807,12 +811,12 @@ public class HostapdHalHidlImp implements IHostapdHal { IHostapd.IfaceParams ifaceParamsV1_0 = new IHostapd.IfaceParams(); ifaceParamsV1_0.ifaceName = ifaceName; ifaceParamsV1_0.hwModeParams.enable80211N = true; - ifaceParamsV1_0.hwModeParams.enable80211AC = mContext.getResources().getBoolean( + ifaceParamsV1_0.hwModeParams.enable80211AC = mResourceCache.getBoolean( R.bool.config_wifi_softap_ieee80211ac_supported); boolean enableAcs = ApConfigUtil.isAcsSupported(mContext) && config.getChannel() == 0; if (enableAcs) { ifaceParamsV1_0.channelParams.enableAcs = true; - ifaceParamsV1_0.channelParams.acsShouldExcludeDfs = !mContext.getResources() + ifaceParamsV1_0.channelParams.acsShouldExcludeDfs = !mResourceCache .getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs); } ifaceParamsV1_0.channelParams.channel = config.getChannel(); @@ -832,12 +836,12 @@ public class HostapdHalHidlImp implements IHostapdHal { if (ifaceParamsV10.channelParams.enableAcs) { if ((config.getBand() & SoftApConfiguration.BAND_2GHZ) != 0) { ifaceParamsV1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( + toAcsChannelRanges(mResourceCache.getString( R.string.config_wifiSoftap2gChannelList))); } if ((config.getBand() & SoftApConfiguration.BAND_5GHZ) != 0) { ifaceParamsV1_1.channelParams.acsChannelRanges.addAll( - toAcsChannelRanges(mContext.getResources().getString( + toAcsChannelRanges(mResourceCache.getString( R.string.config_wifiSoftap5gChannelList))); } } @@ -1070,15 +1074,15 @@ public class HostapdHalHidlImp implements IHostapdHal { String oemConfig; switch (band) { case SoftApConfiguration.BAND_2GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap2gChannelList); break; case SoftApConfiguration.BAND_5GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap5gChannelList); break; case SoftApConfiguration.BAND_6GHZ: - oemConfig = mContext.getResources().getString( + oemConfig = mResourceCache.getString( R.string.config_wifiSoftap6gChannelList); break; default: @@ -1296,7 +1300,8 @@ public class HostapdHalHidlImp implements IHostapdHal { SoftApHalCallback callback = mSoftApHalCallbacks.get(ifaceName); if (callback != null) { callback.onConnectedClientsChanged(apIfaceInstance, - MacAddress.fromBytes(clientAddress), isConnected); + MacAddress.fromBytes(clientAddress), isConnected, + DeauthenticationReasonCode.REASON_UNKNOWN); } } catch (IllegalArgumentException iae) { Log.e(TAG, " Invalid clientAddress, " + iae); diff --git a/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java index 6796b2e904..c860322719 100644 --- a/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java +++ b/service/java/com/android/server/wifi/ISupplicantStaIfaceHal.java @@ -25,6 +25,7 @@ import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Map; @@ -563,23 +564,23 @@ interface ISupplicantStaIfaceHal { boolean setConcurrencyPriority(boolean isStaHigherPriority); /** - * Returns a bitmask of advanced capabilities: WPA3 SAE/SUITE B and OWE + * Returns a BitSet of advanced capabilities: WPA3 SAE/SUITE B and OWE * Bitmask used is: * - WIFI_FEATURE_WPA3_SAE * - WIFI_FEATURE_WPA3_SUITE_B * - WIFI_FEATURE_OWE * - * On error, or if these features are not supported, 0 is returned. + * On error, or if these features are not supported, an empty BitSet is returned. */ - long getAdvancedCapabilities(@NonNull String ifaceName); + @NonNull BitSet getAdvancedCapabilities(@NonNull String ifaceName); /** * Get the driver supported features through supplicant. * * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_*. + * @return BitSet defined by WifiManager.WIFI_FEATURE_*. */ - long getWpaDriverFeatureSet(@NonNull String ifaceName); + @NonNull BitSet getWpaDriverFeatureSet(@NonNull String ifaceName); /** * Returns connection capabilities of the current network @@ -852,4 +853,11 @@ interface ISupplicantStaIfaceHal { * @param ifaceName Name of the interface. */ default void disableMscs(String ifaceName) {} + + /** + * Returns true if this device supports RSN Overriding, false otherwise. + */ + default boolean isRsnOverridingSupported(@NonNull String ifaceName) { + return false; + } } diff --git a/service/java/com/android/server/wifi/MboOceController.java b/service/java/com/android/server/wifi/MboOceController.java index 2b5e9102f2..35b1965959 100644 --- a/service/java/com/android/server/wifi/MboOceController.java +++ b/service/java/com/android/server/wifi/MboOceController.java @@ -25,6 +25,8 @@ import android.util.Log; import com.android.server.wifi.SupplicantStaIfaceHal.MboAssocDisallowedReasonCode; +import java.util.BitSet; + /** * MboOceController is responsible for controlling MBO and OCE operations. */ @@ -60,9 +62,9 @@ public class MboOceController { if (clientModeManager == null) { return; } - long supportedFeatures = clientModeManager.getSupportedFeatures(); - mIsMboSupported = (supportedFeatures & WIFI_FEATURE_MBO) != 0; - mIsOceSupported = (supportedFeatures & WIFI_FEATURE_OCE) != 0; + BitSet supportedFeatures = clientModeManager.getSupportedFeatures(); + mIsMboSupported = supportedFeatures.get(WIFI_FEATURE_MBO); + mIsOceSupported = supportedFeatures.get(WIFI_FEATURE_OCE); mEnabled = true; if (mVerboseLoggingEnabled) { Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported diff --git a/service/java/com/android/server/wifi/PmkCacheManager.java b/service/java/com/android/server/wifi/PmkCacheManager.java index adcd54948d..18a7c51b14 100644 --- a/service/java/com/android/server/wifi/PmkCacheManager.java +++ b/service/java/com/android/server/wifi/PmkCacheManager.java @@ -217,6 +217,9 @@ public class PmkCacheManager { for (int i = 0; i < mPmkCacheEntries.size(); i++) { int networkId = mPmkCacheEntries.keyAt(i); List<PmkCacheStoreData> list = mPmkCacheEntries.get(networkId); + if (null == list) { + continue; + } list.removeIf(pmkData -> !pmkData.isValid(elapseTimeInSecond)); if (list.size() == 0) { emptyStoreDataList.add(networkId); diff --git a/service/java/com/android/server/wifi/RssiMonitor.java b/service/java/com/android/server/wifi/RssiMonitor.java index 9e2867cbeb..4f976b006e 100644 --- a/service/java/com/android/server/wifi/RssiMonitor.java +++ b/service/java/com/android/server/wifi/RssiMonitor.java @@ -42,7 +42,6 @@ public class RssiMonitor { private final DeviceConfigFacade mDeviceConfigFacade; private boolean mEnableClientRssiMonitor = false; - private boolean mIsPollRssiIntervalOverridden = false; private int[] mAppThresholds = {}; private byte[] mRssiRanges = {}; @@ -138,7 +137,7 @@ public class RssiMonitor { mEnableClientRssiMonitor = false; mAppThresholds = new int[] {}; mRssiRanges = new byte[] {}; - if (!mIsPollRssiIntervalOverridden) { + if (!mWifiGlobals.isPollRssiIntervalOverridden()) { int shortInterval = mWifiGlobals.getPollRssiShortIntervalMillis(); mWifiGlobals.setPollRssiIntervalMillis(shortInterval); } @@ -162,7 +161,7 @@ public class RssiMonitor { public void updatePollRssiInterval(@DeviceMobilityState int state) { if (!mWifiGlobals.isAdjustPollRssiIntervalEnabled() || !mDeviceConfigFacade.isAdjustPollRssiIntervalEnabled() - || mIsPollRssiIntervalOverridden) { + || mWifiGlobals.isPollRssiIntervalOverridden()) { return; } int curRssi = mWifiInfo.getRssi(); @@ -192,7 +191,7 @@ public class RssiMonitor { * Change the RSSI polling interval to the short interval and disable client mode RSSI monitor */ public void setShortPollRssiInterval() { - if (mIsPollRssiIntervalOverridden) { + if (mWifiGlobals.isPollRssiIntervalOverridden()) { return; } int shortInterval = mWifiGlobals.getPollRssiShortIntervalMillis(); @@ -287,7 +286,7 @@ public class RssiMonitor { * For automatic handling of the interval, use value 0 */ public void overridePollRssiInterval(int newIntervalMs) { - if (mIsPollRssiIntervalOverridden && newIntervalMs == 0) { + if (mWifiGlobals.isPollRssiIntervalOverridden() && newIntervalMs == 0) { setAutoPollRssiInterval(); return; } @@ -297,13 +296,13 @@ public class RssiMonitor { } private void setAutoPollRssiInterval() { - mIsPollRssiIntervalOverridden = false; + mWifiGlobals.setPollRssiIntervalOverridden(false); int regularInterval = mWifiGlobals.getPollRssiShortIntervalMillis(); mWifiGlobals.setPollRssiIntervalMillis(regularInterval); } private void setFixedPollRssiInterval(int newIntervalMs) { - mIsPollRssiIntervalOverridden = true; + mWifiGlobals.setPollRssiIntervalOverridden(true); mWifiGlobals.setPollRssiIntervalMillis(newIntervalMs); if (mEnableClientRssiMonitor) { disableClientRssiMonitorAndUpdateThresholds(mWifiInfo.getRssi()); diff --git a/service/java/com/android/server/wifi/RunnerHandler.java b/service/java/com/android/server/wifi/RunnerHandler.java index 78b7b12a4f..0329031014 100644 --- a/service/java/com/android/server/wifi/RunnerHandler.java +++ b/service/java/com/android/server/wifi/RunnerHandler.java @@ -52,6 +52,7 @@ public class RunnerHandler extends Handler { // TODO: b/246623192 Add Wifi metric for Runner state overruns. private final LocalLog mLocalLog; + private boolean mVerboseLoggingEnabled = false; /** * The Runner handler Constructor @@ -73,6 +74,11 @@ public class RunnerHandler extends Handler { mIgnoredMethods.add("handleMessage"); } + /** Enable/disable verbose logging. */ + public void enableVerboseLogging(boolean verboseEnabled) { + mVerboseLoggingEnabled = verboseEnabled; + } + private String getSignature(StackTraceElement[] elements, Runnable callback) { StringBuilder sb = new StringBuilder(); for (StackTraceElement e : elements) { @@ -114,7 +120,8 @@ public class RunnerHandler extends Handler { public void dispatchMessage(@NonNull Message msg) { final Bundle bundle = msg.getData(); final String signature = bundle.getString(KEY_SIGNATURE); - if (signature != null) { + boolean traceEvent = mVerboseLoggingEnabled; + if (signature != null && traceEvent) { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signature); } // The message sent to front of the queue has when=0, get from the bundle in that case. @@ -122,10 +129,10 @@ public class RunnerHandler extends Handler { final long start = SystemClock.uptimeMillis(); final long scheduleLatency = start - when; super.dispatchMessage(msg); - if (signature != null) { + final long runTime = SystemClock.uptimeMillis() - start; + if (signature != null && traceEvent) { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } - final long runTime = SystemClock.uptimeMillis() - start; final String signatureToLog = signature != null ? signature : "unknown"; if (runTime > mRunningTimeThresholdInMilliseconds) { mLocalLog.log(signatureToLog + " was running for " + runTime); diff --git a/service/java/com/android/server/wifi/RunnerState.java b/service/java/com/android/server/wifi/RunnerState.java index e6a8573826..04ba369ddf 100644 --- a/service/java/com/android/server/wifi/RunnerState.java +++ b/service/java/com/android/server/wifi/RunnerState.java @@ -48,6 +48,7 @@ public abstract class RunnerState extends State { private final int mRunningTimeThresholdInMilliseconds; // TODO: b/246623192 Add Wifi metric for Runner state overruns. private final LocalLog mLocalLog; + private final WifiInjector mWifiInjector; /** * The Runner state Constructor @@ -56,37 +57,55 @@ public abstract class RunnerState extends State { public RunnerState(int threshold, @NonNull LocalLog localLog) { mRunningTimeThresholdInMilliseconds = threshold; mLocalLog = localLog; + mWifiInjector = WifiInjector.getInstance(); + } + + private boolean isVerboseLoggingEnabled() { + return mWifiInjector.isVerboseLoggingEnabled(); } @Override public boolean processMessage(Message message) { - long startTime = System.currentTimeMillis(); - String signatureToLog = getMessageLogRec(message); if (signatureToLog == null) { signatureToLog = getMessageLogRec(message.what); } - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + boolean traceEvent = isVerboseLoggingEnabled(); + if (traceEvent) { + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + } + + long startTime = System.currentTimeMillis(); + // TODO(b/295398783): Support deferMessage and sendMessageAtFrontOfQueue where when is 0; + long scheduleLatency = message.getWhen() != 0 ? startTime - message.getWhen() : 0; boolean ret = processMessageImpl(message); - Trace.traceEnd(Trace.TRACE_TAG_NETWORK); long runTime = System.currentTimeMillis() - startTime; + if (traceEvent) { + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + } if (runTime > mRunningTimeThresholdInMilliseconds) { mLocalLog.log(signatureToLog + " was running for " + runTime + " ms"); } - if (runTime > METRICS_THRESHOLD_MILLIS) { - WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, 0, signatureToLog); + if (runTime > METRICS_THRESHOLD_MILLIS || scheduleLatency > METRICS_THRESHOLD_MILLIS) { + WifiStatsLog.write(WIFI_THREAD_TASK_EXECUTED, (int) runTime, (int) scheduleLatency, + signatureToLog); } return ret; } @Override public void enter() { - long startTime = System.currentTimeMillis(); String signatureToLog = getMessageLogRec(STATE_ENTER_CMD); - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + boolean traceEvent = isVerboseLoggingEnabled(); + if (traceEvent) { + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + } + long startTime = System.currentTimeMillis(); enterImpl(); - Trace.traceEnd(Trace.TRACE_TAG_NETWORK); long runTime = System.currentTimeMillis() - startTime; + if (traceEvent) { + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + } if (runTime > mRunningTimeThresholdInMilliseconds) { mLocalLog.log(signatureToLog + " was running for " + runTime + " ms"); } @@ -97,12 +116,18 @@ public abstract class RunnerState extends State { @Override public void exit() { - long startTime = System.currentTimeMillis(); String signatureToLog = getMessageLogRec(STATE_EXIT_CMD); - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + boolean traceEvent = isVerboseLoggingEnabled(); + if (traceEvent) { + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, signatureToLog); + } + long startTime = System.currentTimeMillis(); exitImpl(); - Trace.traceEnd(Trace.TRACE_TAG_NETWORK); long runTime = System.currentTimeMillis() - startTime; + if (traceEvent) { + Trace.traceEnd(Trace.TRACE_TAG_NETWORK); + } + if (runTime > mRunningTimeThresholdInMilliseconds) { mLocalLog.log(signatureToLog + " was running for " + runTime + " ms"); } diff --git a/service/java/com/android/server/wifi/ScanOnlyModeImpl.java b/service/java/com/android/server/wifi/ScanOnlyModeImpl.java index 6449b6a18d..1946652a21 100644 --- a/service/java/com/android/server/wifi/ScanOnlyModeImpl.java +++ b/service/java/com/android/server/wifi/ScanOnlyModeImpl.java @@ -18,6 +18,8 @@ package com.android.server.wifi; import android.annotation.NonNull; +import java.util.BitSet; + /** * Used to respond to calls to ClientMode interface when ClientModeImpl is not up * i.e. in scan only mode. @@ -40,7 +42,7 @@ public class ScanOnlyModeImpl implements ClientModeDefaults { } @Override - public long getSupportedFeatures() { + public @NonNull BitSet getSupportedFeatures() { return mWifiNative.getSupportedFeatureSet(mIfaceName); } diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java index e8651652a5..38cf93767a 100644 --- a/service/java/com/android/server/wifi/ScanRequestProxy.java +++ b/service/java/com/android/server/wifi/ScanRequestProxy.java @@ -464,8 +464,8 @@ public class ScanRequestProxy { * Safely retrieve package importance. */ private int getPackageImportance(int callingUid, String packageName) { - mAppOps.checkPackage(callingUid, packageName); try { + mAppOps.checkPackage(callingUid, packageName); return mActivityManager.getPackageImportance(packageName); } catch (SecurityException e) { Log.e(TAG, "Failed to check the app state", e); diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java index a0ceb41f96..fdc1f276d1 100644 --- a/service/java/com/android/server/wifi/SoftApManager.java +++ b/service/java/com/android/server/wifi/SoftApManager.java @@ -40,6 +40,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; import android.net.wifi.nl80211.DeviceWiphyCapabilities; +import android.net.wifi.util.WifiResourceCache; import android.os.BatteryManager; import android.os.Handler; import android.os.Looper; @@ -73,6 +74,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -181,6 +183,7 @@ public class SoftApManager implements ActiveModeManager { private final SoftApNotifier mSoftApNotifier; private final InterfaceConflictManager mInterfaceConflictManager; private final WifiInjector mWifiInjector; + private final WifiResourceCache mResourceCache; @VisibleForTesting static final long SOFT_AP_PENDING_DISCONNECTION_CHECK_DELAY_MS = 1000; @@ -247,7 +250,7 @@ public class SoftApManager implements ActiveModeManager { private final SarManager mSarManager; - private String mStartTimestamp; + private long mStartTimestampMs; private long mDefaultShutdownTimeoutMillis; @@ -336,10 +339,10 @@ public class SoftApManager implements ActiveModeManager { @Override public void onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress, - boolean isConnected) { + boolean isConnected, @WifiAnnotations.SoftApDisconnectReason int disconnectReason) { if (clientAddress != null) { WifiClient client = new WifiClient(clientAddress, apIfaceInstance != null - ? apIfaceInstance : mApInterfaceName); + ? apIfaceInstance : mApInterfaceName, disconnectReason); mStateMachine.sendMessage(SoftApStateMachine.CMD_ASSOCIATED_STATIONS_CHANGED, isConnected ? 1 : 0, 0, client); } else { @@ -448,6 +451,7 @@ public class SoftApManager implements ActiveModeManager { mWifiInjector = wifiInjector; mCoexManager = coexManager; mInterfaceConflictManager = interfaceConflictManager; + mResourceCache = mContext.getResourceCache(); if (SdkLevel.isAtLeastS()) { mCoexListener = new CoexListener() { @Override @@ -494,12 +498,12 @@ public class SoftApManager implements ActiveModeManager { mWifiDiagnostics = wifiDiagnostics; mStateMachine = new SoftApStateMachine(looper); configureInternalConfiguration(); - mDefaultShutdownTimeoutMillis = mContext.getResources().getInteger( + mDefaultShutdownTimeoutMillis = mResourceCache.getInteger( R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - mDefaultShutdownIdleInstanceInBridgedModeTimeoutMillis = mContext.getResources().getInteger( - R.integer + mDefaultShutdownIdleInstanceInBridgedModeTimeoutMillis = mResourceCache + .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); - mIsDisableShutDownBridgedModeIdleInstanceTimerWhenPlugged = mContext.getResources() + mIsDisableShutDownBridgedModeIdleInstanceTimerWhenPlugged = mResourceCache .getBoolean(R.bool .config_wifiFrameworkSoftApDisableBridgedModeShutdownIdleInstanceWhenCharging); mCmiMonitor = cmiMonitor; @@ -659,6 +663,13 @@ public class SoftApManager implements ActiveModeManager { } /** + * Return true when current softap state is enabled. + */ + public boolean isStarted() { + return mCurrentApState == WifiManager.WIFI_AP_STATE_ENABLED; + } + + /** * Dump info about this softap manager. */ @Override @@ -680,7 +691,7 @@ public class SoftApManager implements ActiveModeManager { pw.println("mBridgedModeOpportunisticsShutdownTimeoutEnabled: " + mBridgedModeOpportunisticsShutdownTimeoutEnabled); pw.println("mCurrentSoftApInfoMap " + mCurrentSoftApInfoMap); - pw.println("mStartTimestamp: " + mStartTimestamp); + pw.println("mStartTimestamp: " + FORMATTER.format(new Date(mStartTimestampMs))); pw.println("mSafeChannelFrequencyList: " + mSafeChannelFrequencyList.stream() .map(Object::toString) .collect(Collectors.joining(","))); @@ -854,7 +865,7 @@ public class SoftApManager implements ActiveModeManager { new SoftApConfiguration.Builder(mCurrentSoftApConfiguration); startResult = ApConfigUtil.updateApChannelConfig( - mWifiNative, mCoexManager, mContext.getResources(), mCountryCode, + mWifiNative, mCoexManager, mResourceCache, mCountryCode, localConfigBuilder, mCurrentSoftApConfiguration, mCurrentSoftApCapability); if (startResult != START_RESULT_SUCCESS) { Log.e(getTag(), "Failed to update AP band and channel"); @@ -885,7 +896,7 @@ public class SoftApManager implements ActiveModeManager { } mWifiDiagnostics.startLogging(mApInterfaceName); - mStartTimestamp = FORMATTER.format(new Date(System.currentTimeMillis())); + mStartTimestampMs = mWifiInjector.getClock().getWallClockMillis(); Log.d(getTag(), "Soft AP is started "); return START_RESULT_SUCCESS; @@ -1064,7 +1075,7 @@ public class SoftApManager implements ActiveModeManager { SoftApStateMachine(Looper looper) { super(TAG, looper); - final int threshold = mContext.getResources().getInteger( + final int threshold = mResourceCache.getInteger( R.integer.config_wifiConfigurationWifiRunnerThresholdInMs); mIdleState = new IdleState(threshold); mWaitingForDriverCountryCodeChangedState = @@ -1181,8 +1192,9 @@ public class SoftApManager implements ActiveModeManager { handleStartSoftApFailure(START_RESULT_FAILURE_GENERAL); break; } - if (TextUtils.isEmpty(mCountryCode) && mContext.getResources().getBoolean( - R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)) { + if (TextUtils.isEmpty(mCountryCode) && mResourceCache + .getBoolean( + R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)) { Log.i(getTag(), "No country code set in the framework." + " Should Wait for driver country code update to start AP"); shouldwaitForDriverCountryCodeIfNoCountryToSet = true; @@ -1196,43 +1208,8 @@ public class SoftApManager implements ActiveModeManager { + ", base country in SoftApCapability = " + mCurrentSoftApCapability.getCountryCode()); } + if (isBridgedMode()) { - boolean isFallbackToSingleAp = false; - final List<ClientModeManager> cmms = - mActiveModeWarden.getClientModeManagers(); - // Checking STA status only when device supports STA + AP concurrency - // since STA would be dropped when device doesn't support it. - if (cmms.size() != 0 && mWifiNative.isStaApConcurrencySupported()) { - if (ApConfigUtil.isStaWithBridgedModeSupported(mContext, - mWifiNative)) { - for (ClientModeManager cmm - : mActiveModeWarden.getClientModeManagers()) { - WifiInfo wifiConnectedInfo = cmm.getConnectionInfo(); - int wifiFrequency = wifiConnectedInfo.getFrequency(); - if (wifiFrequency > 0 - && !mSafeChannelFrequencyList.contains( - wifiFrequency)) { - Log.d(getTag(), "Wifi connected to unavailable freq: " - + wifiFrequency); - isFallbackToSingleAp = true; - break; - } - } - } else { - // The client mode exist but DUT doesn't support - // STA + bridged AP, we should fallback to single AP mode. - Log.d(getTag(), " STA iface exist but device doesn't support" - + " STA + Bridged AP"); - isFallbackToSingleAp = true; - } - } - if (isCountryCodeChanged && mCountryCode.equalsIgnoreCase( - mContext.getResources().getString( - R.string.config_wifiDriverWorldModeCountryCode))) { - Log.i(getTag(), "Country code changed to world mode" - + " - fallback to single AP"); - isFallbackToSingleAp = true; - } if (!isCountryCodeChanged) { SoftApConfiguration tempConfig = ApConfigUtil.removeUnavailableBandsFromConfig( @@ -1246,26 +1223,9 @@ public class SoftApManager implements ActiveModeManager { break; } mCurrentSoftApConfiguration = tempConfig; - if (mCurrentSoftApConfiguration.getBands().length == 1) { - isFallbackToSingleAp = true; - Log.i( - getTag(), - "Removed unavailable bands" - + " - fallback to single AP"); - } } - // Fall back to Single AP if it's not possible to create a Bridged AP. - if (!mWifiNative.isItPossibleToCreateBridgedApIface(mRequestorWs)) { - isFallbackToSingleAp = true; - } - // Fall back to single AP if creating a single AP does not require - // destroying an existing iface, but creating a bridged AP does. - if (mWifiNative.shouldDowngradeToSingleApForConcurrency(mRequestorWs)) { - Log.d(getTag(), "Creating bridged AP will destroy an existing" - + " iface, but single AP will not."); - isFallbackToSingleAp = true; - } - if (isFallbackToSingleAp) { + if (!isBridgedApAvailable() + || mCurrentSoftApConfiguration.getBands().length == 1) { int newSingleApBand = 0; for (int configuredBand : mCurrentSoftApConfiguration.getBands()) { newSingleApBand |= configuredBand; @@ -1276,16 +1236,27 @@ public class SoftApManager implements ActiveModeManager { + newSingleApBand); mCurrentSoftApConfiguration = new SoftApConfiguration.Builder(mCurrentSoftApConfiguration) - .setBand(newSingleApBand) - .build(); + .setBand(newSingleApBand) + .build(); } + } else if (!isCountryCodeChanged + && mRole == ROLE_SOFTAP_TETHERED && isBridgedApAvailable()) { + // Try upgrading config to 2 + 5 GHz Dual Band if the available config + // bands only include 2 or 5 Ghz. This is to handle cases where the + // config was previously set to single band in a CC that didn't support + // DBS, but the current one does. + mCurrentSoftApConfiguration = + ApConfigUtil.upgradeTo2g5gBridgedIfAvailableBandsAreSubset( + mCurrentSoftApConfiguration, + mCurrentSoftApCapability, + mContext); } // Remove 6GHz from requested bands if security type is restricted // Note: 6GHz only band is already handled by initial validation SoftApConfiguration tempConfig = ApConfigUtil.remove6gBandForUnsupportedSecurity( - mContext.getResources(), + mResourceCache, mCurrentSoftApConfiguration, isBridgedMode()); if (tempConfig == null) { handleStartSoftApFailure(START_RESULT_FAILURE_UNSUPPORTED_CONFIG); @@ -1334,8 +1305,12 @@ public class SoftApManager implements ActiveModeManager { DeviceWiphyCapabilities capabilities = mWifiNative.getDeviceWiphyCapabilities( mApInterfaceName, isBridgeRequired()); + int numberOf11beSoftApManager = + mActiveModeWarden.getNumberOf11beSoftApManager(); if (!ApConfigUtil.is11beAllowedForThisConfiguration(capabilities, - mContext, mCurrentSoftApConfiguration, isBridgedMode())) { + mContext, mCurrentSoftApConfiguration, isBridgedMode(), + numberOf11beSoftApManager, + false /* TODO: pass the real isChipSupportMultiLinkOnMLD */)) { Log.d(getTag(), "11BE is not allowed," + " removing from configuration"); mCurrentSoftApConfiguration = new SoftApConfiguration.Builder( @@ -1401,6 +1376,64 @@ public class SoftApManager implements ActiveModeManager { } } + private boolean isBridgedApAvailable() { + // Skip if bridged mode isn't supported. + if (!ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative)) { + return false; + } + + // Checking STA status only when device supports STA + AP concurrency + // since STA would be dropped when device doesn't support it. + final List<ClientModeManager> cmms = + mActiveModeWarden.getClientModeManagers(); + if (cmms.size() != 0 && mWifiNative.isStaApConcurrencySupported()) { + if (ApConfigUtil.isStaWithBridgedModeSupported(mContext, + mWifiNative)) { + for (ClientModeManager cmm + : mActiveModeWarden.getClientModeManagers()) { + WifiInfo wifiConnectedInfo = cmm.getConnectionInfo(); + int wifiFrequency = wifiConnectedInfo.getFrequency(); + if (wifiFrequency > 0 + && !mSafeChannelFrequencyList.contains( + wifiFrequency)) { + Log.d(getTag(), "Wifi connected to unavailable freq: " + + wifiFrequency); + return false; + } + } + } else { + // The client mode exist but DUT doesn't support + // STA + bridged AP, we should fallback to single AP mode. + Log.d(getTag(), " STA iface exist but device doesn't support STA + Bridged AP"); + return false; + } + } + + // Fallback if the target country code is world mode. + if (mCountryCode != null && mCountryCode.equalsIgnoreCase( + mResourceCache.getString( + R.string.config_wifiDriverWorldModeCountryCode))) { + Log.i(getTag(), "Country code changed to world mode - fallback to single AP"); + return false; + } + + // Fall back to Single AP if it's not possible to create a Bridged AP. + if (!mWifiNative.isItPossibleToCreateBridgedApIface(mRequestorWs)) { + Log.i(getTag(), "Not possible to create bridged AP iface - fallback to single AP"); + return false; + } + + // Fall back to single AP if creating a single AP does not require + // destroying an exististng iface, but creating a bridged AP does. + if (mWifiNative.shouldDowngradeToSingleApForConcurrency(mRequestorWs)) { + Log.d(getTag(), "Creating bridged AP will destroy an existing" + + " iface, but single AP will not."); + return false; + } + + return true; + } + private class WaitingForDriverCountryCodeChangedState extends RunnerState { private static final int TIMEOUT_MS = 5_000; @@ -1439,6 +1472,14 @@ public class SoftApManager implements ActiveModeManager { ApConfigUtil.updateSoftApCapabilityWithAvailableChannelList( mCurrentSoftApCapability, mContext, mWifiNative, null); updateSafeChannelFrequencyList(); + int[] oldBands = mCurrentSoftApConfiguration.getBands(); + if (mRole == ROLE_SOFTAP_TETHERED && isBridgedApAvailable()) { + mCurrentSoftApConfiguration = + ApConfigUtil.upgradeTo2g5gBridgedIfAvailableBandsAreSubset( + mCurrentSoftApConfiguration, + mCurrentSoftApCapability, + mContext); + } if (isBridgedMode()) { SoftApConfiguration tempConfig = ApConfigUtil.removeUnavailableBandsFromConfig( @@ -1450,9 +1491,10 @@ public class SoftApManager implements ActiveModeManager { return HANDLED; } mCurrentSoftApConfiguration = tempConfig; - if (mCurrentSoftApConfiguration.getBands().length == 1) { - Log.i(getTag(), "Moving to single AP after updating the CC and band." - + " Teardown bridged interface and setup single AP interface"); + if (mCurrentSoftApConfiguration.getBands().length != oldBands.length) { + Log.i(getTag(), "Restarting AP interface to accommodate band change" + + " from " + Arrays.toString(oldBands) + " to " + + Arrays.toString(mCurrentSoftApConfiguration.getBands())); mWifiNative.teardownInterface(mApInterfaceName); mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode( mWifiNativeInterfaceCallback, mRequestorWs, @@ -1996,6 +2038,7 @@ public class SoftApManager implements ActiveModeManager { updateApState(WifiManager.WIFI_AP_STATE_DISABLING, WifiManager.WIFI_AP_STATE_ENABLING, 0); } + writeSoftApStoppedEvent(STOP_EVENT_STOPPED); quitNow(); break; case CMD_START: @@ -2060,8 +2103,10 @@ public class SoftApManager implements ActiveModeManager { if (instance != null) { Log.i(getTag(), "receive instanceFailure on " + instance); removeIfaceInstanceFromBridgedApIface(instance); - // there is an available instance, keep AP on. - if (mCurrentSoftApInfoMap.size() == 1) { + instances = + mWifiNative.getBridgedApInstances(mApInterfaceName); + // Check if there's any instance still active. + if (instances != null && instances.size() > 0) { break; } } else if (mCurrentSoftApInfoMap.size() == 1 && instances != null @@ -2300,7 +2345,8 @@ public class SoftApManager implements ActiveModeManager { mWifiNative.isStaApConcurrencySupported(), ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative), getCurrentStaFreqMhz(), - securityType); + securityType, + mRequestorWs); } private void writeSoftApStoppedEvent(@StopEvent int stopEvent) { @@ -2316,6 +2362,8 @@ public class SoftApManager implements ActiveModeManager { if (mCurrentSoftApConfiguration != null) { securityType = mCurrentSoftApConfiguration.getSecurityType(); } + int durationSeconds = + (int) ((mWifiInjector.getClock().getWallClockMillis() - mStartTimestampMs) / 1000); // TODO(b/245824786): Fill out the rest of the fields mWifiMetrics.writeSoftApStoppedEvent( stopEvent, @@ -2326,7 +2374,7 @@ public class SoftApManager implements ActiveModeManager { ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative), getCurrentStaFreqMhz(), mDefaultShutdownTimeoutMillis > 0, - -1, + durationSeconds, securityType, standard, -1, diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java index 5f377894cb..3cf8cbdf36 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java @@ -318,28 +318,21 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu } @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { + public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int halReasonCode) { synchronized (mLock) { mStaIfaceHal.logCallback("onDisconnected"); if (mStaIfaceHal.isVerboseLoggingEnabled()) { Log.e(TAG, "onDisconnected state=" + mStateBeforeDisconnect + " locallyGenerated=" + locallyGenerated - + " reasonCode=" + reasonCode); + + " reasonCode=" + halReasonCode); } + int reasonCode = halToFrameworkReasonCode(halReasonCode); WifiConfiguration curConfiguration = mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName); if (curConfiguration != null) { - // In case of PSK networks the disconnection event in the middle of key exchange - // happens due to PSK mismatch. But filter out the de-authentication/disassociation - // frame from AP with known reason codes which are not related to PSK mismatch from - // reporting wrong password error. if (mStateBeforeDisconnect == StaIfaceCallbackState.FOURWAY_HANDSHAKE - && (WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration) - || WifiConfigurationUtil.isConfigForWapiPskNetwork( - curConfiguration)) - && (!locallyGenerated - || (reasonCode != StaIfaceReasonCode.IE_IN_4WAY_DIFFERS - && reasonCode != StaIfaceReasonCode.DISASSOC_AP_BUSY))) { + && NativeUtil.isEapol4WayHandshakeFailureDueToWrongPassword( + curConfiguration, locallyGenerated, reasonCode)) { mWifiMonitor.broadcastAuthenticationFailureEvent( mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1, mCurrentSsid, MacAddress.fromBytes(bssid)); @@ -351,7 +344,7 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu } } mWifiMonitor.broadcastNetworkDisconnectionEvent( - mIfaceName, locallyGenerated, halToFrameworkReasonCode(reasonCode), + mIfaceName, locallyGenerated, reasonCode, mCurrentSsid, NativeUtil.macAddressFromByteArray(bssid)); } } @@ -381,15 +374,13 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu // was not successfully verified is indicated with a status code of 15. This // typically happens when the entered password is wrong. So treat status code // of 15 as incorrect password. - // Some implementations also send status code of 1 for incorrect password. But - // this is a generic status code and can't be treated as incorrect password all - // the time. So treat status code of 1 as incorrect password only if the STA - // was not connected to this network before. In this case, we will - // send an authentication failure event up. + // Some implementations also send status code of 1 for incorrect password. For + // both status codes, broadcast authentication failure message with reason code + // set to wrong password. ClientModeImpl will notify user for wrong password + // error if the network had never been connected before. if (statusCode == SupplicantStaIfaceHal.StaIfaceStatusCode.CHALLENGE_FAIL - || (statusCode - == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE - && !curConfiguration.getNetworkSelectionStatus().hasEverConnected())) { + || statusCode + == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE) { mStaIfaceHal.logCallback("SAE incorrect password"); isWrongPwd = true; } else { @@ -1239,6 +1230,9 @@ class SupplicantStaIfaceCallbackAidlImpl extends ISupplicantStaIfaceCallback.Stu @Override public void onNetworkNotFound(byte[] ssid) { mStaIfaceHal.logCallback("onNetworkNotFoundNotification"); + if (mStaIfaceHal.shouldIgnoreNetworkNotFound(mIfaceName)) { + return; + } if (mStaIfaceHal.connectToFallbackSsid(mIfaceName)) { return; } diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java index da8a38b9e3..7727a96732 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlImpl.java @@ -276,28 +276,21 @@ abstract class SupplicantStaIfaceCallbackHidlImpl extends ISupplicantStaIfaceCal } @Override - public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int reasonCode) { + public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated, int halReasonCode) { synchronized (mLock) { mStaIfaceHal.logCallback("onDisconnected"); if (mStaIfaceHal.isVerboseLoggingEnabled()) { Log.e(TAG, "onDisconnected state=" + mStateBeforeDisconnect + " locallyGenerated=" + locallyGenerated - + " reasonCode=" + reasonCode); + + " reasonCode=" + halReasonCode); } + int reasonCode = halToFrameworkReasonCode(halReasonCode); WifiConfiguration curConfiguration = mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName); if (curConfiguration != null) { - // In case of PSK networks the disconnection event in the middle of key exchange - // happens due to PSK mismatch. But filter out the de-authentication/disassociation - // frame from AP with known reason codes which are not related to PSK mismatch from - // reporting wrong password error. if (mStateBeforeDisconnect == State.FOURWAY_HANDSHAKE - && (WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration) - || WifiConfigurationUtil.isConfigForWapiPskNetwork( - curConfiguration)) - && (!locallyGenerated - || (reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS - && reasonCode != ReasonCode.DISASSOC_AP_BUSY))) { + && NativeUtil.isEapol4WayHandshakeFailureDueToWrongPassword( + curConfiguration, locallyGenerated, reasonCode)) { mWifiMonitor.broadcastAuthenticationFailureEvent( mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1, mCurrentSsid, MacAddress.fromBytes(bssid)); @@ -309,7 +302,7 @@ abstract class SupplicantStaIfaceCallbackHidlImpl extends ISupplicantStaIfaceCal } } mWifiMonitor.broadcastNetworkDisconnectionEvent( - mIfaceName, locallyGenerated, halToFrameworkReasonCode(reasonCode), + mIfaceName, locallyGenerated, reasonCode, mCurrentSsid, NativeUtil.macAddressFromByteArray(bssid)); } } @@ -340,15 +333,13 @@ abstract class SupplicantStaIfaceCallbackHidlImpl extends ISupplicantStaIfaceCal // was not successfully verified is indicated with a status code of 15. This // typically happens when the entered password is wrong. So treat status code // of 15 as incorrect password. - // Some implementations also send status code of 1 for incorrect password. But - // this is a generic status code and can't be treated as incorrect password all - // the time. So treat status code of 1 as incorrect password only if the STA - // was not connected to this network before. In this case, we will - // send an authentication failure event up. + // Some implementations also send status code of 1 for incorrect password. For + // both status codes, broadcast authentication failure message with reason code + // set to wrong password. ClientModeImpl will notify user for wrong password + // error if the network had never been connected before. if (statusCode == SupplicantStaIfaceHal.StaIfaceStatusCode.CHALLENGE_FAIL - || (statusCode - == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE - && !curConfiguration.getNetworkSelectionStatus().hasEverConnected())) { + || statusCode + == SupplicantStaIfaceHal.StaIfaceStatusCode.UNSPECIFIED_FAILURE) { mStaIfaceHal.logCallback("SAE incorrect password"); isWrongPwd = true; } else { diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_4Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_4Impl.java index 1cdf26eda1..5ceee6416a 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_4Impl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackHidlV1_4Impl.java @@ -275,6 +275,9 @@ abstract class SupplicantStaIfaceCallbackHidlV1_4Impl extends @Override public void onNetworkNotFound(ArrayList<Byte> ssid) { mStaIfaceHal.logCallback("onNetworkNotFoundNotification"); + if (mStaIfaceHal.shouldIgnoreNetworkNotFound(mIfaceName)) { + return; + } if (mStaIfaceHal.connectToFallbackSsid(mIfaceName)) { return; } diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java index eb6f4609df..72b47f1ce2 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java @@ -34,6 +34,7 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Map; @@ -119,7 +120,7 @@ public class SupplicantStaIfaceHal { public static final byte INSUFFICIENT_RSSI = 5; } - protected static class StaIfaceReasonCode { + public static class StaIfaceReasonCode { public static final int UNSPECIFIED = 1; public static final int PREV_AUTH_NOT_VALID = 2; public static final int DEAUTH_LEAVING = 3; @@ -1926,43 +1927,48 @@ public class SupplicantStaIfaceHal { /** - * Returns a bitmask of advanced capabilities: WPA3 SAE/SUITE B and OWE - * Bitmask used is: - * - WIFI_FEATURE_WPA3_SAE - * - WIFI_FEATURE_WPA3_SUITE_B - * - WIFI_FEATURE_OWE - * - * On error, or if these features are not supported, 0 is returned. + * See comments for {@link ISupplicantStaIfaceHal#getAdvancedCapabilities(String)} */ - public long getAdvancedCapabilities(@NonNull String ifaceName) { + public @NonNull BitSet getAdvancedCapabilities(@NonNull String ifaceName) { synchronized (mLock) { String methodStr = "getAdvancedCapabilities"; if (mStaIfaceHal == null) { handleNullHal(methodStr); - return 0; + return new BitSet(); } return mStaIfaceHal.getAdvancedCapabilities(ifaceName); } } /** - * Get the driver supported features through supplicant. - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_*. + * See comments for {@link ISupplicantStaIfaceHal#getWpaDriverFeatureSet(String)} */ - public long getWpaDriverFeatureSet(@NonNull String ifaceName) { + public @NonNull BitSet getWpaDriverFeatureSet(@NonNull String ifaceName) { synchronized (mLock) { String methodStr = "getWpaDriverFeatureSet"; if (mStaIfaceHal == null) { handleNullHal(methodStr); - return 0; + return new BitSet(); } return mStaIfaceHal.getWpaDriverFeatureSet(ifaceName); } } /** + * Returns true if this device supports RSN Overriding, false otherwise. + */ + public boolean isRsnOverridingSupported(@NonNull String ifaceName) { + synchronized (mLock) { + String methodStr = "isRsnOverridingSupported"; + if (mStaIfaceHal == null) { + handleNullHal(methodStr); + return false; + } + return mStaIfaceHal.isRsnOverridingSupported(ifaceName); + } + } + + /** * Returns connection capabilities of the current network * * @param ifaceName Name of the interface. diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java index 1bcf4b742d..83a9338f0c 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java @@ -33,6 +33,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI; import static android.net.wifi.WifiManager.WIFI_FEATURE_WFD_R2; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; +import static android.os.Build.VERSION.SDK_INT; import android.annotation.NonNull; import android.content.Context; @@ -87,7 +88,9 @@ import android.net.wifi.SecurityParams; import android.net.wifi.WifiAnnotations; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiKeystore; +import android.net.wifi.WifiMigration; import android.net.wifi.WifiSsid; +import android.net.wifi.flags.Flags; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; @@ -99,6 +102,7 @@ import android.util.Log; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.mockwifi.MockWifiServiceUtil; import com.android.server.wifi.util.HalAidlUtil; @@ -106,9 +110,8 @@ import com.android.server.wifi.util.NativeUtil; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Deque; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -116,6 +119,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.IntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -132,6 +136,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private static final String HAL_INSTANCE_NAME = ISupplicant.DESCRIPTOR + "/default"; @VisibleForTesting public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L; + private static final long INVALID_CONNECT_TO_NETWORK_TIMESTAMP = -1L; + @VisibleForTesting + public static final long IGNORE_NETWORK_NOT_FOUND_DURATION_MS = 1000L; /** * Regex pattern for extracting the wps device type bytes. @@ -154,8 +161,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private Map<String, SupplicantStaNetworkHalAidlImpl> mCurrentNetworkRemoteHandles = new HashMap<>(); private Map<String, WifiConfiguration> mCurrentNetworkLocalConfigs = new HashMap<>(); - private Map<String, Deque<WifiSsid>> mCurrentNetworkFallbackSsids = new HashMap<>(); - private Map<String, WifiSsid> mCurrentNetworkFirstSsid = new HashMap<>(); + private Map<String, Long> mCurrentNetworkConnectTimestamp = new HashMap<>(); + private Map<String, List<WifiSsid>> mCurrentNetworkFallbackSsids = new HashMap<>(); + private Map<String, Integer> mCurrentNetworkFallbackSsidIndex = new HashMap<>(); private Map<String, List<Pair<SupplicantStaNetworkHalAidlImpl, WifiConfiguration>>> mLinkedNetworkLocalAndRemoteConfigs = new HashMap<>(); @VisibleForTesting @@ -176,6 +184,11 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private SupplicantStaIfaceHal.QosScsResponseCallback mQosScsResponseCallback; private MscsParams mLastMscsParams; + @VisibleForTesting + protected boolean mHasMigratedLegacyKeystoreAliases = false; + @VisibleForTesting + protected KeystoreMigrationStatusConsumer mKeystoreMigrationStatusConsumer; + private class SupplicantDeathRecipient implements DeathRecipient { @Override public void binderDied() { @@ -203,6 +216,26 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } } + @VisibleForTesting + protected class KeystoreMigrationStatusConsumer implements IntConsumer { + @Override + public void accept(int statusCode) { + synchronized (mLock) { + if (statusCode == WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_NOT_NEEDED + || statusCode + == WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE) { + mHasMigratedLegacyKeystoreAliases = true; + } else { + mHasMigratedLegacyKeystoreAliases = false; + } + Log.i(TAG, "Keystore migration returned with success=" + + mHasMigratedLegacyKeystoreAliases + ", statusCode=" + statusCode); + // Consumer is no longer needed, since the callback has been received + mKeystoreMigrationStatusConsumer = null; + } + } + } + public SupplicantStaIfaceHalAidlImpl(Context context, WifiMonitor monitor, Handler handler, Clock clock, WifiMetrics wifiMetrics, WifiGlobals wifiGlobals, @NonNull SsidTranslator ssidTranslator, WifiInjector wifiInjector) { @@ -435,6 +468,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { mCurrentNetworkRemoteHandles.clear(); mLinkedNetworkLocalAndRemoteConfigs.clear(); mNonStandardCertCallback = null; + mCurrentNetworkConnectTimestamp.clear(); + mCurrentNetworkFallbackSsidIndex.clear(); + mCurrentNetworkFallbackSsids.clear(); } } @@ -642,24 +678,48 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } /** + * Returns whether to ignore the NETWORK_NOT_FOUND event in case it is based on stale cached + * scans. + * + * @param ifaceName Name of the interface. + * @return true if we should ignore NETWORK_NOT_FOUND, false otherwise + */ + public boolean shouldIgnoreNetworkNotFound(@NonNull String ifaceName) { + synchronized (mLock) { + return (mClock.getElapsedSinceBootMillis() + - mCurrentNetworkConnectTimestamp.getOrDefault( + ifaceName, INVALID_CONNECT_TO_NETWORK_TIMESTAMP) + < IGNORE_NETWORK_NOT_FOUND_DURATION_MS); + } + } + + /** * Connects to the next fallback SSID (if any) of the current network upon a network not found * notification. If all the fallback SSIDs have been tried, return to the first SSID and go * through the fallbacks again. * - * Returns false if there's no fallback SSID to connect to, or if we've wrapped back to the - * first SSID. + * @return true if we're connecting to a fallback SSID, false if there are no fallback SSIDs, or + * we've looped back to the first SSID. */ public boolean connectToFallbackSsid(@NonNull String ifaceName) { synchronized (mLock) { - Deque<WifiSsid> fallbackSsids = mCurrentNetworkFallbackSsids.get(ifaceName); + List<WifiSsid> fallbackSsids = mCurrentNetworkFallbackSsids.get(ifaceName); if (fallbackSsids == null || fallbackSsids.isEmpty()) { return false; } - WifiSsid nextSsid = fallbackSsids.removeFirst(); - fallbackSsids.addLast(nextSsid); - Log.d(TAG, "connectToFallbackSsid " + nextSsid); + // Select the next fallback ssid. + // Note that the very first SSID we connect to is index 0, so the next SSID (i.e the + // first fallback SSID) will start with index 1. Once the entire list has been tried, + // wrap back to the first SSID at index 0. + int nextIndex = mCurrentNetworkFallbackSsidIndex.getOrDefault(ifaceName, 0) + 1; + if (nextIndex >= fallbackSsids.size()) { + nextIndex = 0; + } + mCurrentNetworkFallbackSsidIndex.put(ifaceName, nextIndex); + WifiSsid nextSsid = fallbackSsids.get(nextIndex); + Log.d(TAG, "connectToFallbackSsid " + nextSsid + " at index " + nextIndex); connectToNetwork(ifaceName, getCurrentNetworkLocalConfig(ifaceName), nextSsid); - return !Objects.equals(nextSsid, mCurrentNetworkFirstSsid.get(ifaceName)); + return nextIndex != 0; } } @@ -715,7 +775,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { supplicantConfig.SSID = actualSsid.toString(); } else { mCurrentNetworkFallbackSsids.remove(ifaceName); - mCurrentNetworkFirstSsid.remove(ifaceName); + mCurrentNetworkFallbackSsidIndex.remove(ifaceName); if (config.SSID != null) { // No actual SSID supplied, so select from the network selection BSSID // or the latest candidate BSSID. @@ -725,15 +785,15 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { Log.d(TAG, "Selecting supplicant SSID " + supplicantSsid); supplicantConfig.SSID = supplicantSsid.toString(); - Deque<WifiSsid> fallbackSsids = new ArrayDeque<>(mSsidTranslator - .getAllPossibleOriginalSsids(configSsid)); + List<WifiSsid> fallbackSsids = mSsidTranslator + .getAllPossibleOriginalSsids(configSsid); fallbackSsids.remove(supplicantSsid); if (!fallbackSsids.isEmpty()) { // Store the unused SSIDs to fallback on in // connectToFallbackSsid(String) if the chosen SSID isn't found. - fallbackSsids.addLast(supplicantSsid); + fallbackSsids.add(0, supplicantSsid); mCurrentNetworkFallbackSsids.put(ifaceName, fallbackSsids); - mCurrentNetworkFirstSsid.put(ifaceName, supplicantSsid); + mCurrentNetworkFallbackSsidIndex.put(ifaceName, 0); } } // Set the actual translation of the original SSID in case the untranslated @@ -779,6 +839,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { Log.e(TAG, "Failed to select network configuration: " + config.getProfileKey()); return false; } + mCurrentNetworkConnectTimestamp.put(ifaceName, mClock.getElapsedSinceBootMillis()); return true; } } @@ -893,6 +954,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { if (networkHandle == null) { return false; } + Log.d(TAG, "Remove fallback ssids to avoid endless loop"); + mCurrentNetworkFallbackSsids.remove(ifaceName); + mCurrentNetworkFallbackSsidIndex.remove(ifaceName); return networkHandle.disable(); } } @@ -2543,29 +2607,23 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } /** - * Returns a bitmask of advanced capabilities: WPA3 SAE/SUITE B and OWE - * Bitmask used is: - * - WIFI_FEATURE_WPA3_SAE - * - WIFI_FEATURE_WPA3_SUITE_B - * - WIFI_FEATURE_OWE - * - * @return true if successful, false otherwise. + * See comments for {@link ISupplicantStaIfaceHal#getAdvancedCapabilities(String)} */ - public long getAdvancedCapabilities(@NonNull String ifaceName) { + public @NonNull BitSet getAdvancedCapabilities(@NonNull String ifaceName) { synchronized (mLock) { final String methodStr = "getAdvancedCapabilities"; - long advancedCapabilities = 0; + BitSet advancedCapabilities = new BitSet(); int keyMgmtCapabilities = getKeyMgmtCapabilities(ifaceName); - advancedCapabilities |= WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS - | WIFI_FEATURE_DECORATED_IDENTITY; + advancedCapabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); + advancedCapabilities.set(WIFI_FEATURE_DECORATED_IDENTITY); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": Passpoint T&C supported"); Log.v(TAG, methodStr + ": RFC 7542 decorated identity supported"); } if ((keyMgmtCapabilities & KeyMgmtMask.SAE) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SAE; + advancedCapabilities.set(WIFI_FEATURE_WPA3_SAE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE supported"); @@ -2573,7 +2631,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.SUITE_B_192) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SUITE_B; + advancedCapabilities.set(WIFI_FEATURE_WPA3_SUITE_B); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SUITE_B supported"); @@ -2581,7 +2639,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.OWE) != 0) { - advancedCapabilities |= WIFI_FEATURE_OWE; + advancedCapabilities.set(WIFI_FEATURE_OWE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OWE supported"); @@ -2589,8 +2647,8 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.DPP) != 0) { - advancedCapabilities |= WIFI_FEATURE_DPP - | WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; + advancedCapabilities.set(WIFI_FEATURE_DPP); + advancedCapabilities.set(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP supported"); @@ -2599,7 +2657,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.WAPI_PSK) != 0) { - advancedCapabilities |= WIFI_FEATURE_WAPI; + advancedCapabilities.set(WIFI_FEATURE_WAPI); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WAPI supported"); @@ -2607,7 +2665,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA256) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA256; + advancedCapabilities.set(WIFI_FEATURE_FILS_SHA256); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA256 supported"); @@ -2615,7 +2673,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA384) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA384; + advancedCapabilities.set(WIFI_FEATURE_FILS_SHA384); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA384 supported"); @@ -2652,21 +2710,21 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } } - private long aidlWpaDrvFeatureSetToFrameworkV2(int drvCapabilitiesMask) { - if (!isServiceVersionAtLeast(2)) return 0; + private BitSet aidlWpaDrvFeatureSetToFrameworkV2(int drvCapabilitiesMask) { + if (!isServiceVersionAtLeast(2)) return new BitSet(); final String methodStr = "getWpaDriverFeatureSetV2"; - long featureSet = 0; + BitSet featureSet = new BitSet(); if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SET_TLS_MINIMUM_VERSION) != 0) { - featureSet |= WIFI_FEATURE_SET_TLS_MINIMUM_VERSION; + featureSet.set(WIFI_FEATURE_SET_TLS_MINIMUM_VERSION); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": EAP-TLS minimum version supported"); } } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.TLS_V1_3) != 0) { - featureSet |= WIFI_FEATURE_TLS_V1_3; + featureSet.set(WIFI_FEATURE_TLS_V1_3); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": EAP-TLS v1.3 supported"); } @@ -2675,24 +2733,21 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } /** - * Get the driver supported features through supplicant. - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_*. + * See comments for {@link ISupplicantStaIfaceHal#getWpaDriverFeatureSet(String)} */ - public long getWpaDriverFeatureSet(@NonNull String ifaceName) { + public @NonNull BitSet getWpaDriverFeatureSet(@NonNull String ifaceName) { synchronized (mLock) { final String methodStr = "getWpaDriverFeatureSet"; int drvCapabilitiesMask = getWpaDriverCapabilities(ifaceName); - long featureSet = 0; + BitSet featureSet = new BitSet(); if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.MBO) != 0) { - featureSet |= WIFI_FEATURE_MBO; + featureSet.set(WIFI_FEATURE_MBO); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": MBO supported"); } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.OCE) != 0) { - featureSet |= WIFI_FEATURE_OCE; + featureSet.set(WIFI_FEATURE_OCE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OCE supported"); } @@ -2700,14 +2755,14 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SAE_PK) != 0) { - featureSet |= WIFI_FEATURE_SAE_PK; + featureSet.set(WIFI_FEATURE_SAE_PK); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE-PK supported"); } } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.WFD_R2) != 0) { - featureSet |= WIFI_FEATURE_WFD_R2; + featureSet.set(WIFI_FEATURE_WFD_R2); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WFD-R2 supported"); } @@ -2715,19 +2770,40 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.TRUST_ON_FIRST_USE) != 0) { - featureSet |= WIFI_FEATURE_TRUST_ON_FIRST_USE; + featureSet.set(WIFI_FEATURE_TRUST_ON_FIRST_USE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": Trust-On-First-Use supported"); } } - featureSet |= aidlWpaDrvFeatureSetToFrameworkV2(drvCapabilitiesMask); + featureSet.or(aidlWpaDrvFeatureSetToFrameworkV2(drvCapabilitiesMask)); return featureSet; } } /** + * Returns true if this device supports RSN Overriding, false otherwise. Need service version + * at least 4 or higher. + */ + public boolean isRsnOverridingSupported(@NonNull String ifaceName) { + synchronized (mLock) { + final String methodStr = "isRsnOverridingSupported"; + if (!isServiceVersionAtLeast(4)) { + return false; + } + int drvCapabilitiesMask = getWpaDriverCapabilities(ifaceName); + boolean rsnOverridingSupported = + (drvCapabilitiesMask & WpaDriverCapabilitiesMask.RSN_OVERRIDING) != 0; + if (mVerboseLoggingEnabled) { + Log.v(TAG, methodStr + ": RSN Overriding supported: " + + rsnOverridingSupported); + } + return rsnOverridingSupported; + } + } + + /** * Get the bitmask of supplicant/driver supported features in * AIDL WpaDriverCapabilitiesMask format. */ @@ -4038,6 +4114,17 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { return; } + // TODO: Use SdkLevel API when it exists, rather than the SDK_INT + if (!mHasMigratedLegacyKeystoreAliases && SDK_INT >= 36 + && Flags.legacyKeystoreToWifiBlobstoreMigrationReadOnly()) { + if (mKeystoreMigrationStatusConsumer == null) { + // Create global callback temporarily for access in the unit tests + mKeystoreMigrationStatusConsumer = new KeystoreMigrationStatusConsumer(); + } + WifiMigration.migrateLegacyKeystoreToWifiBlobstore( + new HandlerExecutor(mEventHandler), mKeystoreMigrationStatusConsumer); + } + try { INonStandardCertCallback tempCallback = new NonStandardCertCallback(); mISupplicant.registerNonStandardCertCallback(tempCallback); diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java index fbd031259d..6b9838ddcb 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java @@ -73,9 +73,8 @@ import com.android.server.wifi.util.NativeUtil; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.ArrayDeque; import java.util.ArrayList; -import java.util.Deque; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -101,6 +100,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { public static final String HAL_INSTANCE_NAME = "default"; @VisibleForTesting public static final long WAIT_FOR_DEATH_TIMEOUT_MS = 50L; + private static final long INVALID_CONNECT_TO_NETWORK_TIMESTAMP = -1L; + @VisibleForTesting + public static final long IGNORE_NETWORK_NOT_FOUND_DURATION_MS = 1000L; /** * Regex pattern for extracting the wps device type bytes. * Matches a strings like the following: "<categ>-<OUI>-<subcateg>"; @@ -121,8 +123,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { private Map<String, SupplicantStaNetworkHalHidlImpl> mCurrentNetworkRemoteHandles = new HashMap<>(); private Map<String, WifiConfiguration> mCurrentNetworkLocalConfigs = new HashMap<>(); - private Map<String, Deque<WifiSsid>> mCurrentNetworkFallbackSsids = new HashMap<>(); - private Map<String, WifiSsid> mCurrentNetworkFirstSsid = new HashMap<>(); + private Map<String, Long> mCurrentNetworkConnectTimestamp = new HashMap<>(); + private Map<String, List<WifiSsid>> mCurrentNetworkFallbackSsids = new HashMap<>(); + private Map<String, Integer> mCurrentNetworkFallbackSsidIndex = new HashMap<>(); private Map<String, List<Pair<SupplicantStaNetworkHalHidlImpl, WifiConfiguration>>> mLinkedNetworkLocalAndRemoteConfigs = new HashMap<>(); @VisibleForTesting @@ -644,6 +647,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { mCurrentNetworkLocalConfigs.clear(); mCurrentNetworkRemoteHandles.clear(); mLinkedNetworkLocalAndRemoteConfigs.clear(); + mCurrentNetworkConnectTimestamp.clear(); + mCurrentNetworkFallbackSsidIndex.clear(); + mCurrentNetworkFallbackSsids.clear(); } } @@ -976,24 +982,48 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } /** + * Returns whether to ignore the NETWORK_NOT_FOUND event in case it is based on stale cached + * scans. + * + * @param ifaceName Name of the interface. + * @return true if we should ignore NETWORK_NOT_FOUND, false otherwise + */ + public boolean shouldIgnoreNetworkNotFound(@NonNull String ifaceName) { + synchronized (mLock) { + return mClock.getElapsedSinceBootMillis() + - mCurrentNetworkConnectTimestamp.getOrDefault( + ifaceName, INVALID_CONNECT_TO_NETWORK_TIMESTAMP) + < IGNORE_NETWORK_NOT_FOUND_DURATION_MS; + } + } + + /** * Connects to the next fallback SSID (if any) of the current network upon a network not found * notification. If all the fallback SSIDs have been tried, return to the first SSID and go * through the fallbacks again. * - * Returns false if there's no fallback SSID to connect to, or if we've wrapped back to the - * first SSID. + * @return true if we're connecting to a fallback SSID, false if there are no fallback SSIDs, or + * we've looped back to the first SSID. */ public boolean connectToFallbackSsid(@NonNull String ifaceName) { synchronized (mLock) { - Deque<WifiSsid> fallbackSsids = mCurrentNetworkFallbackSsids.get(ifaceName); + List<WifiSsid> fallbackSsids = mCurrentNetworkFallbackSsids.get(ifaceName); if (fallbackSsids == null || fallbackSsids.isEmpty()) { return false; } - WifiSsid nextSsid = fallbackSsids.removeFirst(); - fallbackSsids.addLast(nextSsid); - Log.d(TAG, "connectToFallbackSsid " + nextSsid); + // Select the next fallback ssid. + // Note that the very first SSID we connect to is index 0, so the next SSID (i.e the + // first fallback SSID) will start with index 1. Once the entire list has been tried, + // wrap back to the first SSID at index 0. + int nextIndex = mCurrentNetworkFallbackSsidIndex.getOrDefault(ifaceName, 0) + 1; + if (nextIndex >= fallbackSsids.size()) { + nextIndex = 0; + } + mCurrentNetworkFallbackSsidIndex.put(ifaceName, nextIndex); + WifiSsid nextSsid = fallbackSsids.get(nextIndex); + Log.d(TAG, "connectToFallbackSsid " + nextSsid + " at index " + nextIndex); connectToNetwork(ifaceName, getCurrentNetworkLocalConfig(ifaceName), nextSsid); - return !Objects.equals(nextSsid, mCurrentNetworkFirstSsid.get(ifaceName)); + return nextIndex != 0; } } @@ -1049,7 +1079,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { supplicantConfig.SSID = actualSsid.toString(); } else { mCurrentNetworkFallbackSsids.remove(ifaceName); - mCurrentNetworkFirstSsid.remove(ifaceName); + mCurrentNetworkFallbackSsidIndex.remove(ifaceName); if (config.SSID != null) { // No actual SSID supplied, so select from the network selection BSSID // or the latest candidate BSSID. @@ -1059,15 +1089,15 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { Log.d(TAG, "Selecting supplicant SSID " + supplicantSsid); supplicantConfig.SSID = supplicantSsid.toString(); - Deque<WifiSsid> fallbackSsids = new ArrayDeque<>(mSsidTranslator - .getAllPossibleOriginalSsids(configSsid)); + List<WifiSsid> fallbackSsids = mSsidTranslator + .getAllPossibleOriginalSsids(configSsid); fallbackSsids.remove(supplicantSsid); if (!fallbackSsids.isEmpty()) { // Store the unused SSIDs to fallback on in // connectToFallbackSsid(String) if the chosen SSID isn't found. - fallbackSsids.addLast(supplicantSsid); + fallbackSsids.add(0, supplicantSsid); mCurrentNetworkFallbackSsids.put(ifaceName, fallbackSsids); - mCurrentNetworkFirstSsid.put(ifaceName, supplicantSsid); + mCurrentNetworkFallbackSsidIndex.put(ifaceName, 0); } } // Set the actual translation of the original SSID in case the untranslated @@ -1111,6 +1141,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { loge("Failed to select network configuration: " + config.getProfileKey()); return false; } + mCurrentNetworkConnectTimestamp.put(ifaceName, mClock.getElapsedSinceBootMillis()); return true; } } @@ -1222,6 +1253,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { SupplicantStaNetworkHalHidlImpl networkHandle = checkSupplicantStaNetworkAndLogFailure(ifaceName, "disableCurrentNetwork"); if (networkHandle == null) return false; + Log.d(TAG, "Remove fallback ssids to avoid endless loop"); + mCurrentNetworkFallbackSsids.remove(ifaceName); + mCurrentNetworkFallbackSsidIndex.remove(ifaceName); return networkHandle.disable(); } } @@ -2925,24 +2959,20 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } /** - * Returns a bitmask of advanced capabilities: WPA3 SAE/SUITE B and OWE - * Bitmask used is: - * - WIFI_FEATURE_WPA3_SAE - * - WIFI_FEATURE_WPA3_SUITE_B - * - WIFI_FEATURE_OWE + * See comments for {@link ISupplicantStaIfaceHal#getAdvancedCapabilities(String)} * * This is a v1.2+ HAL feature. - * On error, or if these features are not supported, 0 is returned. + * On error, or if these features are not supported, an empty BitSet is returned. */ - public long getAdvancedCapabilities(@NonNull String ifaceName) { + public @NonNull BitSet getAdvancedCapabilities(@NonNull String ifaceName) { final String methodStr = "getAdvancedCapabilities"; - long advancedCapabilities = 0; + BitSet advancedCapabilities = new BitSet(); int keyMgmtCapabilities = getKeyMgmtCapabilities(ifaceName); if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.SAE) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SAE; + advancedCapabilities.set(WIFI_FEATURE_WPA3_SAE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE supported"); @@ -2951,7 +2981,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.SUITE_B_192) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SUITE_B; + advancedCapabilities.set(WIFI_FEATURE_WPA3_SUITE_B); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SUITE_B supported"); @@ -2960,7 +2990,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.OWE) != 0) { - advancedCapabilities |= WIFI_FEATURE_OWE; + advancedCapabilities.set(WIFI_FEATURE_OWE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OWE supported"); @@ -2969,13 +2999,13 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.DPP) != 0) { - advancedCapabilities |= WIFI_FEATURE_DPP; + advancedCapabilities.set(WIFI_FEATURE_DPP); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP supported"); } if (isV1_4()) { - advancedCapabilities |= WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; + advancedCapabilities.set(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP ENROLLEE RESPONDER supported"); } @@ -2983,8 +3013,8 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } if (isV1_4()) { - advancedCapabilities |= WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS - | WIFI_FEATURE_DECORATED_IDENTITY; + advancedCapabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); + advancedCapabilities.set(WIFI_FEATURE_DECORATED_IDENTITY); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": Passpoint T&C supported"); Log.v(TAG, methodStr + ": RFC 7542 decorated identity supported"); @@ -2993,7 +3023,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork .KeyMgmtMask.WAPI_PSK) != 0) { - advancedCapabilities |= WIFI_FEATURE_WAPI; + advancedCapabilities.set(WIFI_FEATURE_WAPI); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WAPI supported"); @@ -3002,7 +3032,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork .KeyMgmtMask.FILS_SHA256) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA256; + advancedCapabilities.set(WIFI_FEATURE_FILS_SHA256); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA256 supported"); @@ -3010,7 +3040,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_3.ISupplicantStaNetwork .KeyMgmtMask.FILS_SHA384) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA384; + advancedCapabilities.set(WIFI_FEATURE_FILS_SHA384); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA384 supported"); @@ -3164,15 +3194,12 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } /** - * Get the driver supported features through supplicant. - * - * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_*. + * See comments for {@link ISupplicantStaIfaceHal#getWpaDriverFeatureSet(String)} */ - public long getWpaDriverFeatureSet(@NonNull String ifaceName) { + public @NonNull BitSet getWpaDriverFeatureSet(@NonNull String ifaceName) { final String methodStr = "getWpaDriverFeatureSet"; Mutable<Integer> drvCapabilitiesMask = new Mutable<>(0); - long featureSet = 0; + BitSet featureSet = new BitSet(); if (isV1_4()) { drvCapabilitiesMask = getWpaDriverCapabilities_1_4(ifaceName); @@ -3180,17 +3207,17 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { drvCapabilitiesMask = getWpaDriverCapabilities_1_3(ifaceName); } else { Log.i(TAG, "Method " + methodStr + " is not supported in existing HAL"); - return 0; + return new BitSet(); } if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.MBO) != 0) { - featureSet |= WIFI_FEATURE_MBO; + featureSet.set(WIFI_FEATURE_MBO); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": MBO supported"); } if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.OCE) != 0) { - featureSet |= WIFI_FEATURE_OCE; + featureSet.set(WIFI_FEATURE_OCE); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OCE supported"); } @@ -3199,7 +3226,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((drvCapabilitiesMask.value & android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.SAE_PK) != 0) { - featureSet |= WIFI_FEATURE_SAE_PK; + featureSet.set(WIFI_FEATURE_SAE_PK); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE-PK supported"); } @@ -3207,7 +3234,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((drvCapabilitiesMask.value & android.hardware.wifi.supplicant.V1_4.WpaDriverCapabilitiesMask.WFD_R2) != 0) { - featureSet |= WIFI_FEATURE_WFD_R2; + featureSet.set(WIFI_FEATURE_WFD_R2); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WFD-R2 supported"); } diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java index 3c1a8b4993..4797584cdc 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import static android.net.wifi.WifiManager.WIFI_FEATURE_TLS_V1_3; +import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; + import android.annotation.NonNull; import android.content.Context; import android.hardware.wifi.supplicant.AuthAlgMask; @@ -38,7 +41,6 @@ import android.net.wifi.OuiKeyedData; import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; -import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -151,13 +153,13 @@ public class SupplicantStaNetworkHalAidlImpl { private String mEapDomainSuffixMatch; private @WifiEnterpriseConfig.Ocsp int mOcsp; private String mWapiCertSuite; - private long mAdvanceKeyMgmtFeatures; - private long mWpaDriverFeatures; + private BitSet mAdvanceKeyMgmtFeatures; + private BitSet mWpaDriverFeatures; SupplicantStaNetworkHalAidlImpl(int serviceVersion, ISupplicantStaNetwork staNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeature, long wpaDriverFeatures) { + BitSet advanceKeyMgmtFeature, BitSet wpaDriverFeatures) { mServiceVersion = serviceVersion; mISupplicantStaNetwork = staNetwork; mContext = context; @@ -884,7 +886,7 @@ public class SupplicantStaNetworkHalAidlImpl { private int getOptimalMinimumTlsVersion(WifiEnterpriseConfig enterpriseConfig) { int maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_2; - if ((mWpaDriverFeatures & WifiManager.WIFI_FEATURE_TLS_V1_3) != 0) { + if (mWpaDriverFeatures.get(WIFI_FEATURE_TLS_V1_3)) { maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_3; } @@ -1044,8 +1046,7 @@ public class SupplicantStaNetworkHalAidlImpl { mask |= GroupCipherMask.GTK_NOT_USED; break; case WifiConfiguration.GroupCipher.GCMP_256: - if (0 == (mAdvanceKeyMgmtFeatures - & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { + if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupported GCMP_256 cipher."); break; } @@ -1106,8 +1107,7 @@ public class SupplicantStaNetworkHalAidlImpl { mask |= PairwiseCipherMask.CCMP; break; case WifiConfiguration.PairwiseCipher.GCMP_256: - if (0 == (mAdvanceKeyMgmtFeatures - & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { + if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupporting GCMP_256 cipher."); break; } diff --git a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java index 7e2d2e3567..4a96230367 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java @@ -15,6 +15,8 @@ */ package com.android.server.wifi; +import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; + import android.content.Context; import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback; @@ -24,7 +26,6 @@ import android.net.wifi.SecurityParams; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Ocsp; -import android.net.wifi.WifiManager; import android.net.wifi.WifiSsid; import android.os.RemoteException; import android.text.TextUtils; @@ -134,11 +135,11 @@ public class SupplicantStaNetworkHalHidlImpl { private String mEapDomainSuffixMatch; private @Ocsp int mOcsp; private String mWapiCertSuite; - private long mAdvanceKeyMgmtFeatures; + private BitSet mAdvanceKeyMgmtFeatures; SupplicantStaNetworkHalHidlImpl(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeature) { + BitSet advanceKeyMgmtFeature) { mISupplicantStaNetwork = iSupplicantStaNetwork; mContext = context; mIfaceName = ifaceName; @@ -991,7 +992,7 @@ public class SupplicantStaNetworkHalHidlImpl { Log.d(TAG, "Ignore GCMP_256 cipher for the HAL older than 1.2."); break; } - if (0 == (mAdvanceKeyMgmtFeatures & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { + if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupporting GCMP_256 cipher."); break; } @@ -1068,7 +1069,7 @@ public class SupplicantStaNetworkHalHidlImpl { Log.d(TAG, "Ignore GCMP_256 cipher for the HAL older than 1.2."); break; } - if (0 == (mAdvanceKeyMgmtFeatures & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { + if (!mAdvanceKeyMgmtFeatures.get(WIFI_FEATURE_WPA3_SUITE_B)) { Log.d(TAG, "Ignore unsupporting GCMP_256 cipher."); break; } diff --git a/service/java/com/android/server/wifi/WifiApConfigStore.java b/service/java/com/android/server/wifi/WifiApConfigStore.java index f4d062279b..d5167ac57a 100644 --- a/service/java/com/android/server/wifi/WifiApConfigStore.java +++ b/service/java/com/android/server/wifi/WifiApConfigStore.java @@ -32,7 +32,9 @@ import android.net.MacAddress; import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.BandType; +import android.net.wifi.WifiContext; import android.net.wifi.WifiSsid; +import android.net.wifi.util.WifiResourceCache; import android.os.Handler; import android.os.Process; import android.text.TextUtils; @@ -79,7 +81,7 @@ public class WifiApConfigStore { private SoftApConfiguration mPersistentWifiApConfig = null; private String mLastConfiguredPassphrase = null; - private final Context mContext; + private final WifiContext mContext; private final Handler mHandler; private final WifiMetrics mWifiMetrics; private final BackupManagerProxy mBackupManagerProxy; @@ -95,6 +97,7 @@ public class WifiApConfigStore { private int mForcedApChannel; private int mForcedApMaximumChannelBandWidth; private final boolean mIsAutoAppendLowerBandEnabled; + private final WifiResourceCache mResourceCache; /** * Module to interact with the wifi config store. @@ -125,7 +128,7 @@ public class WifiApConfigStore { } } - WifiApConfigStore(Context context, + WifiApConfigStore(WifiContext context, WifiInjector wifiInjector, Handler handler, BackupManagerProxy backupManagerProxy, @@ -147,7 +150,8 @@ public class WifiApConfigStore { IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_HOTSPOT_CONFIG_USER_TAPPED_CONTENT); mMacAddressUtil = wifiInjector.getMacAddressUtil(); - mIsAutoAppendLowerBandEnabled = mContext.getResources().getBoolean( + mResourceCache = context.getResourceCache(); + mIsAutoAppendLowerBandEnabled = mResourceCache.getBoolean( R.bool.config_wifiSoftapAutoAppendLowerBandsToBandConfigurationEnabled); mHalDeviceManager = wifiInjector.getHalDeviceManager(); mWifiSettingsConfigStore = wifiInjector.getSettingsConfigStore(); @@ -240,7 +244,7 @@ public class WifiApConfigStore { @NonNull SoftApConfiguration config) { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); if (SdkLevel.isAtLeastS() && ApConfigUtil.isBridgedModeSupported(mContext, mWifiNative) - && config.getBands().length == 1 && mContext.getResources().getBoolean( + && config.getBands().length == 1 && mResourceCache.getBoolean( R.bool.config_wifiSoftapAutoUpgradeToBridgedConfigWhenSupported)) { int[] dual_bands = new int[] { SoftApConfiguration.BAND_2GHZ, @@ -274,7 +278,7 @@ public class WifiApConfigStore { @NonNull SoftApConfiguration config) { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config); if ((!ApConfigUtil.isClientForceDisconnectSupported(mContext) - || mContext.getResources().getBoolean( + || mResourceCache.getBoolean( R.bool.config_wifiSoftapResetUserControlConfig)) && (config.isClientControlByUserEnabled() || config.getBlockedClientList().size() != 0)) { @@ -284,7 +288,7 @@ public class WifiApConfigStore { } if ((!ApConfigUtil.isClientForceDisconnectSupported(mContext) - || mContext.getResources().getBoolean( + || mResourceCache.getBoolean( R.bool.config_wifiSoftapResetMaxClientSettingConfig)) && config.getMaxNumberOfClients() != 0) { configBuilder.setMaxNumberOfClients(0); @@ -304,7 +308,7 @@ public class WifiApConfigStore { Log.i(TAG, "Device doesn't support WPA3-SAE, reset config to WPA2"); } - if (mContext.getResources().getBoolean(R.bool.config_wifiSoftapResetChannelConfig) + if (mResourceCache.getBoolean(R.bool.config_wifiSoftapResetChannelConfig) && config.getChannel() != 0) { // The device might not support customize channel or forced channel might not // work in some countries. Need to reset it. @@ -339,13 +343,13 @@ public class WifiApConfigStore { } } - if (mContext.getResources().getBoolean(R.bool.config_wifiSoftapResetHiddenConfig) + if (mResourceCache.getBoolean(R.bool.config_wifiSoftapResetHiddenConfig) && config.isHiddenSsid()) { configBuilder.setHiddenSsid(false); Log.i(TAG, "Reset SAP Hidden Network configuration"); } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiSoftapResetAutoShutdownTimerConfig) && config.getShutdownTimeoutMillis() > 0) { if (CompatChanges.isChangeEnabled( @@ -426,7 +430,7 @@ public class WifiApConfigStore { private SoftApConfiguration getDefaultApConfiguration() { SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(); configBuilder.setBand(generateDefaultBand(mContext)); - configBuilder.setSsid(mContext.getResources().getString( + configBuilder.setSsid(mResourceCache.getString( R.string.wifi_tether_configure_ssid_default) + "_" + getRandomIntForDefaultSsid()); try { if (ApConfigUtil.isWpa3SaeSupported(mContext)) { @@ -470,8 +474,8 @@ public class WifiApConfigStore { return random.nextInt((RAND_SSID_INT_MAX - RAND_SSID_INT_MIN) + 1) + RAND_SSID_INT_MIN; } - private static String generateLohsSsid(Context context) { - return context.getResources().getString( + private static String generateLohsSsid(WifiContext context) { + return context.getResourceCache().getString( R.string.wifi_localhotspot_configure_ssid_default) + "_" + getRandomIntForDefaultSsid(); } @@ -484,7 +488,7 @@ public class WifiApConfigStore { * Generate a temporary WPA2 based configuration for use by the local only hotspot. * This config is not persisted and will not be stored by the WifiApConfigStore. */ - public SoftApConfiguration generateLocalOnlyHotspotConfig(@NonNull Context context, + public SoftApConfiguration generateLocalOnlyHotspotConfig(@NonNull WifiContext context, @Nullable SoftApConfiguration customConfig, @NonNull SoftApCapability capability) { SoftApConfiguration.Builder configBuilder; if (customConfig != null) { @@ -529,11 +533,11 @@ public class WifiApConfigStore { // Automotive mode can force the LOHS to specific bands if (hasAutomotiveFeature(context)) { int desiredBand = SoftApConfiguration.BAND_2GHZ; - if (context.getResources().getBoolean(R.bool.config_wifiLocalOnlyHotspot6ghz) + if (context.getResourceCache().getBoolean(R.bool.config_wifiLocalOnlyHotspot6ghz) && ApConfigUtil.isBandSupported(SoftApConfiguration.BAND_6GHZ, mContext)) { desiredBand |= SoftApConfiguration.BAND_6GHZ; } - if (context.getResources().getBoolean(R.bool.config_wifi_local_only_hotspot_5ghz) + if (context.getResourceCache().getBoolean(R.bool.config_wifi_local_only_hotspot_5ghz) && ApConfigUtil.isBandSupported(SoftApConfiguration.BAND_5GHZ, mContext)) { desiredBand |= SoftApConfiguration.BAND_5GHZ; } @@ -619,7 +623,7 @@ public class WifiApConfigStore { * otherwise. */ static boolean validateApWifiConfiguration(@NonNull SoftApConfiguration apConfig, - boolean isPrivileged, Context context, WifiNative wifiNative) { + boolean isPrivileged, WifiContext context, WifiNative wifiNative) { // first check the SSID WifiSsid ssid = apConfig.getWifiSsid(); if (ssid == null || ssid.getBytes().length == 0) { @@ -659,7 +663,7 @@ public class WifiApConfigStore { return false; } - if (context.getResources().getBoolean( + if (context.getResourceCache().getBoolean( R.bool.config_wifiSoftapPassphraseAsciiEncodableCheck)) { final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder(); if (!asciiEncoder.canEncode(preSharedKey)) { @@ -686,7 +690,7 @@ public class WifiApConfigStore { // Only return failure if requested band is limited to 6GHz only if (band == SoftApConfiguration.BAND_6GHZ && !ApConfigUtil.canHALConvertRestrictedSecurityTypeFor6GHz( - context.getResources(), authType)) { + context.getResourceCache(), authType)) { Log.d(TAG, "security type: " + authType + " is not allowed for softap in 6GHz band"); return false; @@ -728,7 +732,7 @@ public class WifiApConfigStore { * @param context The caller context used to get value from resource file. * @return A band which will be used for a default band in default configuration. */ - public static @BandType int generateDefaultBand(Context context) { + public static @BandType int generateDefaultBand(WifiContext context) { for (int band : SoftApConfiguration.BAND_TYPES) { if (ApConfigUtil.isBandSupported(band, context)) { return band; @@ -738,7 +742,7 @@ public class WifiApConfigStore { return SoftApConfiguration.BAND_2GHZ; } - private static boolean isBandsSupported(@NonNull int[] apBands, Context context) { + private static boolean isBandsSupported(@NonNull int[] apBands, WifiContext context) { for (int band : apBands) { if (!ApConfigUtil.isBandSupported(band, context)) { return false; diff --git a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java index 1936abb7ae..1e623a6987 100644 --- a/service/java/com/android/server/wifi/WifiCarrierInfoManager.java +++ b/service/java/com/android/server/wifi/WifiCarrierInfoManager.java @@ -2178,6 +2178,31 @@ public class WifiCarrierInfoManager { return enabled; } + /** + * Return true if there is one or more SIMs' mobile data is enabled. + */ + public boolean isMobileDataEnabled() { + if (mActiveSubInfos == null) { + return false; + } + for (SubscriptionInfo info : mActiveSubInfos) { + if (isMobileDataEnabled(info.getSubscriptionId())) { + return true; + } + } + return false; + } + + /** + * Return true if there is one or more active SubInfo. + */ + public boolean hasActiveSubInfo() { + if (mActiveSubInfos == null || mActiveSubInfos.isEmpty()) { + return false; + } + return true; + } + private void saveToStore() { // Set the flag to let WifiConfigStore that we have new data to write. mHasNewUserDataToSerialize = true; diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 9b0af36429..b08fbc27cd 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -17,12 +17,16 @@ package com.android.server.wifi; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_NO_PERMISSION_MODIFY_CONFIG; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_SUCCESS; import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; +import static com.android.server.wifi.WifiConfigurationUtil.validatePassword; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -81,6 +85,7 @@ import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -124,6 +129,7 @@ public class WifiConfigManager { private final AlarmManager mAlarmManager; private final FeatureFlags mFeatureFlags; private boolean mBufferedWritePending; + private int mCellularConnectivityStatus = WifiDataStall.CELLULAR_DATA_UNKNOWN; /** Alarm tag to use for starting alarms for buffering file writes. */ @VisibleForTesting public static final String BUFFERED_WRITE_ALARM_TAG = "WriteBufferAlarm"; /** Time interval for buffering file writes for non-forced writes */ @@ -480,8 +486,16 @@ public class WifiConfigManager { */ public void onCellularConnectivityChanged(@WifiDataStall.CellularDataStatusCode int status) { localLog("onCellularConnectivityChanged:" + status); - if (status == WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE) { + mCellularConnectivityStatus = status; + } + + /** + * Allow wifi connection if cellular data is unavailable. + */ + public void considerStopRestrictingAutoJoinToSubscriptionId() { + if (mCellularConnectivityStatus == WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE) { stopRestrictingAutoJoinToSubscriptionId(); + mCellularConnectivityStatus = WifiDataStall.CELLULAR_DATA_UNKNOWN; } } @@ -1116,6 +1130,12 @@ public class WifiConfigManager { if (internalConfig.isSecurityType(newType)) { internalConfig.setSecurityParamsIsAddedByAutoUpgrade(newType, externalConfig.getDefaultSecurityParams().isAddedByAutoUpgrade()); + // Set to SAE-only in case we're updating a PSK/SAE config with an SAE-only + // passphrase. + if (oldType == SECURITY_TYPE_PSK && newType == SECURITY_TYPE_SAE + && !validatePassword(externalConfig.preSharedKey, false, false, false)) { + internalConfig.setSecurityParams(externalConfig.getSecurityParamsList()); + } } else if (externalConfig.isSecurityType(oldType)) { internalConfig.setSecurityParams(newType); internalConfig.addSecurityParams(oldType); @@ -1430,7 +1450,7 @@ public class WifiConfigManager { } WifiConfiguration newInternalConfig = null; - long supportedFeatures = mWifiInjector.getActiveModeWarden() + BitSet supportedFeatures = mWifiInjector.getActiveModeWarden() .getPrimaryClientModeManager().getSupportedFeatures(); // First check if we already have a network with the provided network id or configKey. @@ -1580,7 +1600,7 @@ public class WifiConfigManager { // Validate an Enterprise network with Trust On First Use. if (config.isEnterprise() && config.enterpriseConfig.isTrustOnFirstUseEnabled()) { - if ((supportedFeatures & WIFI_FEATURE_TRUST_ON_FIRST_USE) == 0) { + if (!supportedFeatures.get(WIFI_FEATURE_TRUST_ON_FIRST_USE)) { Log.e(TAG, "Trust On First Use could not be set " + "when Trust On First Use is not supported."); return new Pair<>( @@ -3545,7 +3565,7 @@ public class WifiConfigManager { List<WifiConfiguration> configurations, Map<String, String> macAddressMapping) { - long supportedFeatures = mWifiInjector.getActiveModeWarden() + BitSet supportedFeatures = mWifiInjector.getActiveModeWarden() .getPrimaryClientModeManager().getSupportedFeatures(); for (WifiConfiguration configuration : configurations) { @@ -3584,7 +3604,7 @@ public class WifiConfigManager { * @param configurations list of configurations retrieved from store. */ private void loadInternalDataFromUserStore(List<WifiConfiguration> configurations) { - long supportedFeatures = mWifiInjector.getActiveModeWarden() + BitSet supportedFeatures = mWifiInjector.getActiveModeWarden() .getPrimaryClientModeManager().getSupportedFeatures(); for (WifiConfiguration configuration : configurations) { diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java index 4421fcd08e..b44d2af092 100644 --- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java +++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java @@ -16,7 +16,11 @@ package com.android.server.wifi; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_NUM; import static android.net.wifi.WifiManager.ALL_ZEROS_MAC_ADDRESS; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES; import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; @@ -31,6 +35,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSpecifier; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; +import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.PatternMatcher; import android.text.TextUtils; import android.util.Log; @@ -46,8 +51,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; /** * WifiConfiguration utility for any {@link android.net.wifi.WifiConfiguration} related operations. @@ -70,6 +77,7 @@ public class WifiConfigurationUtil { private static final int PSK_SAE_HEX_LEN = 64; private static final int WEP104_KEY_BYTES_LEN = 13; private static final int WEP40_KEY_BYTES_LEN = 5; + private static final int MAX_STRING_LENGTH = 512; @VisibleForTesting public static final String PASSWORD_MASK = "*"; @@ -507,7 +515,10 @@ public class WifiConfigurationUtil { return true; } - private static boolean validatePassword(String password, boolean isAdd, boolean isSae, + /** + * Checks that a password is formatted correctly. + */ + public static boolean validatePassword(String password, boolean isAdd, boolean isSae, boolean isWapi) { if (isAdd) { if (password == null) { @@ -745,12 +756,13 @@ public class WifiConfigurationUtil { * update could contain only the fields that are being changed. * @return true if the parameters are valid, false otherwise. */ - public static boolean validate(WifiConfiguration config, long supportedFeatureSet, + public static boolean validate(WifiConfiguration config, BitSet supportedFeatureSet, boolean isAdd) { if (!validateSsid(config.SSID, isAdd)) { return false; } - if (!validateBssid(config.BSSID)) { + if (!validateBssid(config.BSSID) || !validateBssid(config.dhcpServer) + || !validateBssid(config.defaultGwMacAddress)) { return false; } if (!validateBitSets(config)) { @@ -759,9 +771,22 @@ public class WifiConfigurationUtil { if (!validateKeyMgmt(config.allowedKeyManagement)) { return false; } - if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_WEP) - && config.wepKeys != null - && !validateWepKeys(config.wepKeys, config.wepTxKeyIndex, isAdd)) { + if (!validateSecurityParameters(config.getSecurityParamsList())) { + return false; + } + if (!validatePasspoint(config)) { + return false; + } + if (!validateNetworkSelectionStatus(config.getNetworkSelectionStatus())) { + return false; + } + + if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_WEP)) { + if (config.wepKeys != null + && !validateWepKeys(config.wepKeys, config.wepTxKeyIndex, isAdd)) { + return false; + } + } else if (!validateWepKeys(config.wepKeys, config.wepTxKeyIndex, false)) { return false; } if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) @@ -777,7 +802,7 @@ public class WifiConfigurationUtil { return false; } if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP) - && (supportedFeatureSet & WifiManager.WIFI_FEATURE_DPP_AKM) == 0) { + && !supportedFeatureSet.get(WifiManager.WIFI_FEATURE_DPP_AKM)) { Log.e(TAG, "DPP AKM is not supported"); return false; } @@ -793,10 +818,92 @@ public class WifiConfigurationUtil { if (!validateIpConfiguration(config.getIpConfiguration())) { return false; } + + if (config.getDppConnector().length > MAX_URL_BYTES + || config.getDppCSignKey().length > MAX_URL_BYTES + || config.getDppPrivateEcKey().length > MAX_URL_BYTES + || config.getDppNetAccessKey().length > MAX_URL_BYTES) { + return false; + } // TBD: Validate some enterprise params as well in the future here. return true; } + private static boolean validateStringField(String field, int maxLength) { + return field == null || field.length() <= maxLength; + } + + private static boolean validatePasspoint(WifiConfiguration config) { + if (!validateStringField(config.FQDN, PasspointConfiguration.MAX_STRING_LENGTH)) { + return false; + } + if (!validateStringField(config.providerFriendlyName, + PasspointConfiguration.MAX_STRING_LENGTH)) { + return false; + } + if (!validateRoamingConsortiumIds(config.roamingConsortiumIds)) { + return false; + } + if (!validateUpdateIdentifier(config.updateIdentifier)) { + return false; + } + return true; + } + + private static boolean validateUpdateIdentifier(String updateIdentifier) { + if (TextUtils.isEmpty(updateIdentifier)) { + return true; + } + try { + Integer.valueOf(updateIdentifier); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + private static boolean validateNetworkSelectionStatus( + WifiConfiguration.NetworkSelectionStatus status) { + if (status == null) { + return false; + } + return validateStringField(status.getConnectChoice(), MAX_STRING_LENGTH) + && validateBssid(status.getNetworkSelectionBSSID()); + } + + private static boolean validateRoamingConsortiumIds(long[] roamingConsortiumIds) { + if (roamingConsortiumIds != null) { + if (roamingConsortiumIds.length > MAX_NUMBER_OF_OI) { + Log.d(TAG, "too many Roaming Consortium Organization Identifiers in the " + + "profile"); + return false; + } + for (long oi : roamingConsortiumIds) { + if (oi < 0 || oi > MAX_OI_VALUE) { + Log.d(TAG, "Organization Identifiers is out of range"); + return false; + } + } + } + return true; + } + + private static boolean validateSecurityParameters(List<SecurityParams> paramsList) { + Set<Integer> uniqueSecurityTypes = new HashSet<>(SECURITY_TYPE_NUM + 1); + for (SecurityParams params : paramsList) { + int securityType = params.getSecurityType(); + if (securityType < 0 || securityType > SECURITY_TYPE_NUM) { + return false; + } + if (uniqueSecurityTypes.contains(securityType)) { + return false; + } + uniqueSecurityTypes.add(securityType); + } + return true; + + } + private static boolean validateBssidPattern( Pair<MacAddress, MacAddress> bssidPatternMatcher) { if (bssidPatternMatcher == null) return true; @@ -1078,14 +1185,14 @@ public class WifiConfigurationUtil { } private static boolean isSecurityParamsSupported(SecurityParams params) { - final long wifiFeatures = WifiInjector.getInstance() + final BitSet wifiFeatures = WifiInjector.getInstance() .getActiveModeWarden().getPrimaryClientModeManager() .getSupportedFeatures(); switch (params.getSecurityType()) { case WifiConfiguration.SECURITY_TYPE_SAE: - return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_WPA3_SAE); + return wifiFeatures.get(WifiManager.WIFI_FEATURE_WPA3_SAE); case WifiConfiguration.SECURITY_TYPE_OWE: - return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_OWE); + return wifiFeatures.get(WifiManager.WIFI_FEATURE_OWE); } return true; } diff --git a/service/java/com/android/server/wifi/WifiConnectivityHelper.java b/service/java/com/android/server/wifi/WifiConnectivityHelper.java index e1c43ecd86..65d5306591 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java +++ b/service/java/com/android/server/wifi/WifiConnectivityHelper.java @@ -25,6 +25,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.BitSet; /** * This class provides helper functions for Wifi connectivity related modules to @@ -63,10 +64,10 @@ public class WifiConnectivityHelper { ClientModeManager primaryManager = mWifiInjector.getActiveModeWarden().getPrimaryClientModeManager(); - long fwFeatureSet = primaryManager.getSupportedFeatures(); - Log.d(TAG, "Firmware supported feature set: " + Long.toHexString(fwFeatureSet)); + BitSet fwFeatureSet = primaryManager.getSupportedFeatures(); + Log.d(TAG, "Firmware supported feature set: " + fwFeatureSet); - if ((fwFeatureSet & WIFI_FEATURE_CONTROL_ROAMING) == 0) { + if (!fwFeatureSet.get(WIFI_FEATURE_CONTROL_ROAMING)) { Log.d(TAG, "Firmware roaming is not supported"); return true; } diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index 59d8934edf..da0ae94dbf 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityManager.java +++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java @@ -25,6 +25,7 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LO import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE; import static com.android.server.wifi.WifiMetrics.ConnectionEvent.FAILURE_AUTHENTICATION_FAILURE; +import static com.android.server.wifi.WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE; import static com.android.server.wifi.proto.nano.WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE; import android.annotation.NonNull; @@ -52,6 +53,7 @@ import android.os.IBinder; import android.os.PowerManager; import android.os.Process; import android.os.WorkSource; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; @@ -73,6 +75,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; @@ -198,6 +201,7 @@ public class WifiConnectivityManager { private int mInitialScanState = INITIAL_SCAN_STATE_COMPLETE; private boolean mAutoJoinEnabledExternal = true; // enabled by default private boolean mAutoJoinEnabledExternalSetByDeviceAdmin = false; + private int mAutojoinDisallowedSecurityTypes = 0; // restrict none by default private boolean mUntrustedConnectionAllowed = false; private Set<Integer> mRestrictedConnectionAllowedUids = new ArraySet<>(); private boolean mOemPaidConnectionAllowed = false; @@ -218,9 +222,11 @@ public class WifiConnectivityManager { private Object mDelayedPnoScanToken = new Object(); private boolean mDelayedPnoScanPending = false; private boolean mPeriodicScanTimerSet = false; + private boolean mDelayedCarrierPartialScanScheduled = false; private Object mPeriodicScanTimerToken = new Object(); private Object mDelayedStartPeriodicScanToken = new Object(); - private boolean mDelayedPartialScanTimerSet = false; + private Object mDelayedCarrierPartialScanToken = new Object(); + private boolean mHighMvmtDelayedPartialScanTimerSet = false; private boolean mWatchdogScanTimerSet = false; private boolean mIsLocationModeEnabled; @@ -265,6 +271,12 @@ public class WifiConnectivityManager { private @DeviceMobilityState int mDeviceMobilityState = WifiManager.DEVICE_MOBILITY_STATE_UNKNOWN; + // Cached WifiCandidate timestamps for delayed carrier network selection + private Map<WifiCandidates.Key, Long> mDelayedCarrierCandidateTimestamps = new HashMap<>(); + private Set<Integer> mDelayedCarrierCandidateFrequencies = new HashSet<>(); + private Set<Integer> mDelayedSelectionCarrierIds = new HashSet<>(); + private long mDelayedCarrierSelectionTimeMs; + // A helper to log debugging information in the local log buffer, which can // be retrieved in bugreport. private void localLog(String log) { @@ -312,7 +324,7 @@ public class WifiConnectivityManager { } }; - private final AlarmManager.OnAlarmListener mDelayedPartialScanTimerListener = + private final AlarmManager.OnAlarmListener mHighMvmtDelayedPartialScanListener = new AlarmManager.OnAlarmListener() { public void onAlarm() { if (mCachedWifiCandidates == null @@ -320,26 +332,46 @@ public class WifiConnectivityManager { || mCachedWifiCandidates.frequencies.size() == 0) { return; } - ScanSettings settings = new ScanSettings(); - settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; - settings.band = getScanBand(false); - settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT - | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; - settings.numBssidsPerScan = 0; - int index = 0; - settings.channels = - new WifiScanner.ChannelSpec[mCachedWifiCandidates.frequencies.size()]; - for (Integer freq : mCachedWifiCandidates.frequencies) { - settings.channels[index++] = new WifiScanner.ChannelSpec(freq); - } - SingleScanListener singleScanListener = new SingleScanListener(false); - mScanner.startScan(settings, - new WifiScannerInternal.ScanListener(singleScanListener, - mWifiThreadRunner)); - mWifiMetrics.incrementConnectivityOneshotScanCount(); + startPartialScan(mCachedWifiCandidates.frequencies); + mHighMvmtDelayedPartialScanTimerSet = false; } }; + private void startDelayedCarrierPartialScan() { + if (!mDelayedCarrierPartialScanScheduled) { + Log.i(TAG, "Ignoring delayed carrier partial scan"); + return; + } + mDelayedCarrierPartialScanScheduled = false; + + if (mDelayedCarrierCandidateFrequencies == null + || mDelayedCarrierCandidateFrequencies.isEmpty()) { + Log.i(TAG, "No frequencies found for the delayed carrier partial scan"); + return; + } + Log.i(TAG, "Starting delayed carrier partial scan"); + startPartialScan(mDelayedCarrierCandidateFrequencies); + } + + private void startPartialScan(Set<Integer> frequencies) { + ScanSettings settings = new ScanSettings(); + settings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; + settings.band = getScanBand(false); + settings.reportEvents = WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT + | WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; + settings.numBssidsPerScan = 0; + int index = 0; + settings.channels = new WifiScanner.ChannelSpec[frequencies.size()]; + for (Integer freq : frequencies) { + settings.channels[index++] = new WifiScanner.ChannelSpec(freq); + } + SingleScanListener singleScanListener = new SingleScanListener(false); + mScanner.startScan(settings, + new WifiScannerInternal.ScanListener(singleScanListener, + mWifiThreadRunner)); + mWifiMetrics.incrementConnectivityOneshotScanCount(); + } + /** * Interface for callback from handling scan results. */ @@ -627,6 +659,9 @@ public class WifiConnectivityManager { } boolean skipSufficiencyCheck = shouldSkipSufficiencyCheck(hasExistingSecondaryCmm); + // If cellular is unavailable, re-enable Wi-Fi networks disabled by pinning to cell. + mConfigManager.considerStopRestrictingAutoJoinToSubscriptionId(); + // Check if any blocklisted BSSIDs can be freed. List<ScanDetail> enabledDetails = mWifiBlocklistMonitor.tryEnablingBlockedBssids(scanDetails); @@ -648,7 +683,11 @@ public class WifiConnectivityManager { List<WifiCandidates.Candidate> candidates = mNetworkSelector.getCandidatesFromScan( scanDetails, bssidBlocklist, cmmStates, mUntrustedConnectionAllowed, mOemPaidConnectionAllowed, mOemPrivateConnectionAllowed, - mRestrictedConnectionAllowedUids, skipSufficiencyCheck); + mRestrictedConnectionAllowedUids, skipSufficiencyCheck, + mAutojoinDisallowedSecurityTypes); + // Filter candidates before caching to avoid reconnecting on failure + candidates = filterDelayedCarrierSelectionCandidates(candidates, listenerName, + isFullScan); mLatestCandidates = candidates; mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis(); @@ -875,12 +914,102 @@ public class WifiConnectivityManager { candidates); localLog("Found " + candidates.size() + " candidates at high mobility state. " + "Re-doing scan to confirm network quality."); - scheduleDelayedPartialScan(minimumTimeBetweenScansMs); + scheduleHighMvmtDelayedPartialScan(minimumTimeBetweenScansMs); } mWifiMetrics.incrementNumHighMovementConnectionSkipped(); return null; } + /** + * Filter carrier candidates affected by the delayed carrier selection optimization. + */ + private List<WifiCandidates.Candidate> filterDelayedCarrierSelectionCandidates( + List<WifiCandidates.Candidate> candidates, String listenerName, boolean isFullScan) { + if (mDelayedSelectionCarrierIds == null || mDelayedSelectionCarrierIds.isEmpty()) { + // No carrier IDs apply to this filter + return candidates; + } + + boolean isNotPartialScan = isFullScan || listenerName.equals(PNO_SCAN_LISTENER); + if (candidates == null || candidates.isEmpty()) { + // No connectable networks nearby or network selection is unnecessary + if (isNotPartialScan) { + mDelayedCarrierCandidateTimestamps.clear(); + } + return null; + } + + List<WifiCandidates.Candidate> delayedCarrierCandidates = new ArrayList<>(); + List<WifiCandidates.Candidate> nonAffectedCandidates = new ArrayList<>(); + for (WifiCandidates.Candidate candidate : candidates) { + WifiConfiguration configuration = + mConfigManager.getConfiguredNetwork(candidate.getNetworkConfigId()); + if (configuration != null + && mDelayedSelectionCarrierIds.contains(configuration.carrierId)) { + delayedCarrierCandidates.add(candidate); + } else { + nonAffectedCandidates.add(candidate); + } + } + + if (isNotPartialScan) { + updateDelayedCarrierCandidateCache(delayedCarrierCandidates); + } + if (delayedCarrierCandidates.isEmpty()) { + return candidates; + } + + // Include delayed carrier candidates that were first seen + // at least mDelayedCarrierSelectionTimeMs ago + long currentTimeMs = mClock.getElapsedSinceBootMillis(); + List<WifiCandidates.Candidate> filteredCandidates = new ArrayList<>(); + for (WifiCandidates.Candidate candidate : delayedCarrierCandidates) { + long firstSeenTimeMs = mDelayedCarrierCandidateTimestamps + .getOrDefault(candidate.getKey(), currentTimeMs); + if ((currentTimeMs - firstSeenTimeMs) > mDelayedCarrierSelectionTimeMs) { + filteredCandidates.add(candidate); + } + } + Log.i(TAG, filteredCandidates.size() + " of " + delayedCarrierCandidates.size() + + " delayed carrier candidates are eligible for network selection"); + filteredCandidates.addAll(nonAffectedCandidates); + scheduleDelayedCarrierPartialScanIfNeeded(isNotPartialScan); + return filteredCandidates; + } + + /** + * Update the first seen timestamp for all delayed carrier scan candidates, + * as well as the frequencies where the candidates were last seen. + */ + private void updateDelayedCarrierCandidateCache( + List<WifiCandidates.Candidate> delayedCarrierCandidates) { + Map<WifiCandidates.Key, Long> updatedTimestamps = new HashMap<>(); + Set<Integer> updatedFrequencies = new HashSet<>(); + long currentTimeMs = mClock.getElapsedSinceBootMillis(); + for (WifiCandidates.Candidate candidate : delayedCarrierCandidates) { + WifiCandidates.Key candidateKey = candidate.getKey(); + // Use the existing first-seen time if this candidate has been seen before + long firstSeenTimestamp = mDelayedCarrierCandidateTimestamps.getOrDefault( + candidateKey, currentTimeMs); + updatedTimestamps.put(candidateKey, firstSeenTimestamp); + updatedFrequencies.add(candidate.getFrequency()); + } + mDelayedCarrierCandidateTimestamps = updatedTimestamps; + mDelayedCarrierCandidateFrequencies = updatedFrequencies; + } + + private void scheduleDelayedCarrierPartialScanIfNeeded(boolean isNotPartialScan) { + if (!isNotPartialScan || mDelayedCarrierPartialScanScheduled + || mWifiState == WIFI_STATE_CONNECTED) { + return; + } + Log.i(TAG, "Scheduling delayed carrier partial scan to run in " + + mDelayedCarrierSelectionTimeMs + " ms"); + mEventHandler.postDelayed(() -> startDelayedCarrierPartialScan(), + mDelayedCarrierPartialScanToken, mDelayedCarrierSelectionTimeMs); + mDelayedCarrierPartialScanScheduled = true; + } + private void updateUserDisabledList(List<ScanDetail> scanDetails) { List<String> results = new ArrayList<>(); List<ScanResult> passpointAp = new ArrayList<>(); @@ -1388,6 +1517,16 @@ public class WifiConnectivityManager { mWifiCountryCode = wifiCountryCode; mWifiDialogManager = wifiDialogManager; + mDelayedCarrierSelectionTimeMs = mContext.getResources().getInteger( + R.integer.config_wifiDelayedCarrierSelectionTimeMs); + int[] delayedSelectionCarrierIds = mContext.getResources().getIntArray( + R.array.config_wifiDelayedSelectionCarrierIds); + if (delayedSelectionCarrierIds != null && delayedSelectionCarrierIds.length != 0) { + for (Integer carrierId : delayedSelectionCarrierIds) { + mDelayedSelectionCarrierIds.add(carrierId); + } + } + // Listen to WifiConfigManager network update events mEventHandler.postToFront(() -> mConfigManager.addOnNetworkUpdateListener(new OnNetworkUpdateListener())); @@ -1817,8 +1956,10 @@ public class WifiConnectivityManager { // Need to connect to a different network id // Framework specifies the connection target BSSID if firmware doesn't support // {@link android.net.wifi.WifiManager#WIFI_FEATURE_CONTROL_ROAMING} or the - // candidate configuration contains a specified BSSID. + // candidate configuration contains a specified BSSID, or the feature to set target BSSID + // is enabled. if (mConnectivityHelper.isFirmwareRoamingSupported() + && !mWifiGlobals.isNetworkSelectionSetTargetBssid() && (targetNetwork.BSSID == null || targetNetwork.BSSID.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY))) { targetBssid = ClientModeImpl.SUPPLICANT_BSSID_ANY; @@ -2173,7 +2314,7 @@ public class WifiConnectivityManager { getScheduledSingleScanType(mCurrentSingleScanScheduleIndex)); // Note, initial partial scan may fail due to lack of channel history - // Hence, we verify state before changing to AWIATING_RESPONSE + // Hence, we verify state before changing to AWAITING_RESPONSE if (mInitialScanState == INITIAL_SCAN_STATE_START) { setInitialScanState(INITIAL_SCAN_STATE_AWAITING_RESPONSE); mWifiMetrics.incrementInitialPartialScanCount(); @@ -2540,9 +2681,12 @@ public class WifiConnectivityManager { config.isPasspoint() ? config.FQDN : config.SSID) || (config.enterpriseConfig != null && config.enterpriseConfig.isAuthenticationSimBased() - && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) + && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID && !mWifiCarrierInfoManager.isSimReady( - mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))); + mWifiCarrierInfoManager.getBestMatchSubscriptionId(config))) + || (config.subscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID + && !mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled( + config.subscriptionId, config.carrierMerged))); return networks; } @@ -2710,18 +2854,22 @@ public class WifiConnectivityManager { } // Schedules a delayed partial scan, which will scan the frequencies in mCachedWifiCandidates. - private void scheduleDelayedPartialScan(long delayMillis) { + private void scheduleHighMvmtDelayedPartialScan(long delayMillis) { mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mClock.getElapsedSinceBootMillis() + delayMillis, DELAYED_PARTIAL_SCAN_TIMER_TAG, - mDelayedPartialScanTimerListener, mEventHandler); - mDelayedPartialScanTimerSet = true; + mHighMvmtDelayedPartialScanListener, mEventHandler); + mHighMvmtDelayedPartialScanTimerSet = true; } - // Cancel the delayed partial scan timer. - private void cancelDelayedPartialScan() { - if (mDelayedPartialScanTimerSet) { - mAlarmManager.cancel(mDelayedPartialScanTimerListener); - mDelayedPartialScanTimerSet = false; + // Cancel all scheduled delayed partial scans. + private void cancelDelayedPartialScans() { + if (mHighMvmtDelayedPartialScanTimerSet) { + mAlarmManager.cancel(mHighMvmtDelayedPartialScanListener); + mHighMvmtDelayedPartialScanTimerSet = false; + } + if (mDelayedCarrierPartialScanScheduled) { + mEventHandler.removeCallbacksAndMessages(mDelayedCarrierPartialScanToken); + mDelayedCarrierPartialScanScheduled = false; } } @@ -2825,7 +2973,7 @@ public class WifiConnectivityManager { // Due to b/28020168, timer based single scan will be scheduled // to provide periodic scan in an exponential backoff fashion. cancelPeriodicScanTimer(); - cancelDelayedPartialScan(); + cancelDelayedPartialScans(); stopPnoScan(); } @@ -3157,6 +3305,7 @@ public class WifiConnectivityManager { // Only attempt to reconnect when connection on the primary CMM fails, since MBB // CMM will be destroyed after the connection failure. if (clientModeManager.getRole() == ROLE_CLIENT_PRIMARY + && failureCode != FAILURE_NO_RESPONSE // Do not retry since this is a timeout && !mWifiPermissionsUtil.isAdminRestrictedNetwork(config)) { retryConnectionOnLatestCandidates(clientModeManager, bssid, config, failureCode == FAILURE_AUTHENTICATION_FAILURE @@ -3395,14 +3544,24 @@ public class WifiConnectivityManager { mConnectivityHelper.getFirmwareRoamingInfo(); mWifiChannelUtilization.init(getPrimaryClientModeManager().getWifiLinkLayerStats()); clearConnectionAttemptTimeStamps(); // clear connection attempts. - - if (mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { - setInitialScanState(INITIAL_SCAN_STATE_START); - } - mRunning = true; mLatestCandidates = null; mLatestCandidatesTimestampMs = 0; + if (mContext.getResources().getBoolean(R.bool.config_wifiEnablePartialInitialScan)) { + setInitialScanState(INITIAL_SCAN_STATE_START); + if (mScreenOn) { + // force trigger partial scan at start up to make sure this happens before Settings + // scan + startSingleScan(false, WIFI_WORK_SOURCE, DEFAULT_SCANNING_TYPE[0]); + + // Note, initial partial scan may fail due to lack of channel history + // Hence, we verify state before changing to AWAITING_RESPONSE + if (mInitialScanState == INITIAL_SCAN_STATE_START) { + setInitialScanState(INITIAL_SCAN_STATE_AWAITING_RESPONSE); + mWifiMetrics.incrementInitialPartialScanCount(); + } + } + } } /** @@ -3506,6 +3665,22 @@ public class WifiConnectivityManager { } /** + * Set auto join restriction on select security types + */ + public void setAutojoinDisallowedSecurityTypes(int restrictions) { + localLog("Set auto join restriction on select security types - restrictions: " + + restrictions); + mAutojoinDisallowedSecurityTypes = restrictions; + } + + /** + * Return auto join restriction on select security types + */ + public int getAutojoinDisallowedSecurityTypes() { + return mAutojoinDisallowedSecurityTypes; + } + + /** * Check if multi internet connection exists. * * @return true if multi internet connection exists. diff --git a/service/java/com/android/server/wifi/WifiCountryCode.java b/service/java/com/android/server/wifi/WifiCountryCode.java index 4d4bc0bb0c..c307c010b8 100644 --- a/service/java/com/android/server/wifi/WifiCountryCode.java +++ b/service/java/com/android/server/wifi/WifiCountryCode.java @@ -21,7 +21,9 @@ import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_DEFAULT_COUNT import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; +import android.net.wifi.util.WifiResourceCache; import android.os.SystemProperties; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -65,7 +67,7 @@ public class WifiCountryCode { static final int MAX_DURATION_SINCE_LAST_UPDATE_TIME_MS = 500_000; static final int MIN_SCAN_RSSI_DBM = -85; private final String mWorldModeCountryCode; - private final Context mContext; + private final WifiContext mContext; private final TelephonyManager mTelephonyManager; private final ActiveModeWarden mActiveModeWarden; private final WifiP2pMetrics mWifiP2pMetrics; @@ -74,6 +76,7 @@ public class WifiCountryCode { private final Clock mClock; private final WifiPermissionsUtil mWifiPermissionsUtil; private final WifiCarrierInfoManager mWifiCarrierInfoManager; + private final WifiResourceCache mResourceCache; private List<ChangeListener> mListeners = new ArrayList<>(); private boolean mVerboseLoggingEnabled = false; private boolean mIsCountryCodePendingToUpdateToCmm = true; // default to true for first update. @@ -199,7 +202,7 @@ public class WifiCountryCode { } public WifiCountryCode( - Context context, + WifiContext context, ActiveModeWarden activeModeWarden, WifiP2pMetrics wifiP2pMetrics, ClientModeImplMonitor clientModeImplMonitor, @@ -217,12 +220,13 @@ public class WifiCountryCode { mClock = clock; mWifiPermissionsUtil = wifiPermissionsUtil; mWifiCarrierInfoManager = wifiCarrierInfoManager; + mResourceCache = mContext.getResourceCache(); mActiveModeWarden.registerModeChangeCallback(new ModeChangeCallbackInternal()); clientModeImplMonitor.registerListener(new ClientModeListenerInternal()); mWifiNative.registerCountryCodeEventListener(new CountryChangeListenerInternal()); - mWorldModeCountryCode = mContext.getResources() + mWorldModeCountryCode = mResourceCache .getString(R.string.config_wifiDriverWorldModeCountryCode); Log.d(TAG, "Default country code from system property " @@ -383,7 +387,7 @@ public class WifiCountryCode { // Empty country code. if (TextUtils.isEmpty(countryCode)) { - if (mContext.getResources() + if (mResourceCache .getBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss)) { Log.d(TAG, "Received empty country code, reset to default country code"); mTelephonyCountryCode = null; @@ -457,7 +461,7 @@ public class WifiCountryCode { } private boolean isCcUpdateGenericEnabled() { - return mContext.getResources().getBoolean( + return mResourceCache.getBoolean( R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric); } @@ -587,7 +591,7 @@ public class WifiCountryCode { */ public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("mRevertCountryCodeOnCellularLoss: " - + mContext.getResources().getBoolean( + + mResourceCache.getBoolean( R.bool.config_wifi_revert_country_code_on_cellular_loss)); pw.println("DefaultCountryCode(system property): " + getOemDefaultCountryCode()); pw.println("DefaultCountryCode(config store): " @@ -612,7 +616,7 @@ public class WifiCountryCode { } private boolean isDriverSupportedRegChangedEvent() { - return mContext.getResources().getBoolean( + return mResourceCache.getBoolean( R.bool.config_wifiDriverSupportedNl80211RegChangedEvent); } @@ -664,7 +668,7 @@ public class WifiCountryCode { Set<ActiveModeManager> amms = mAmmToReadyForChangeMap.keySet(); boolean isConcreteClientModeManagerUpdated = false; boolean anyAmmConfigured = false; - final boolean isNeedToUpdateCCToSta = mContext.getResources() + final boolean isNeedToUpdateCCToSta = mResourceCache .getBoolean(R.bool.config_wifiStaDynamicCountryCodeUpdateSupported) || isAllCmmReady(); if (!isNeedToUpdateCCToSta) { @@ -674,13 +678,11 @@ public class WifiCountryCode { boolean isCountryCodeChanged = !TextUtils.equals(mDriverCountryCode, country); Log.d(TAG, "setCountryCodeNative: " + country + ", isClientModeOnly: " + isClientModeOnly + " mDriverCountryCode: " + mDriverCountryCode); + // We intend to change Country code, assume to pending to update for Cmm first. + mIsCountryCodePendingToUpdateToCmm = true; for (ActiveModeManager am : amms) { - if (!isConcreteClientModeManagerUpdated + if (isNeedToUpdateCCToSta && !isConcreteClientModeManagerUpdated && am instanceof ConcreteClientModeManager) { - mIsCountryCodePendingToUpdateToCmm = !isNeedToUpdateCCToSta; - if (!isNeedToUpdateCCToSta) { - continue; - } // Set the country code using one of the active mode managers. Since // country code is a chip level global setting, it can be set as long // as there is at least one active interface to communicate to Wifi chip @@ -696,6 +698,8 @@ public class WifiCountryCode { if (!SdkLevel.isAtLeastS() && !isDriverSupportedRegChangedEvent()) { handleCountryCodeChanged(country); } + // Country code was updated to cmmm succeeded, change pending to false. + mIsCountryCodePendingToUpdateToCmm = false; } } else if (!isClientModeOnly && am instanceof SoftApManager) { SoftApManager sm = (SoftApManager) am; diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java index 64e370bd9e..45aa5f7fd5 100644 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ b/service/java/com/android/server/wifi/WifiDataStall.java @@ -306,6 +306,59 @@ public class WifiDataStall { return mRxTputKbps; } + public static class Speeds { + public int DownstreamKbps = INVALID_THROUGHPUT; + public int UpstreamKbps = INVALID_THROUGHPUT; + } + + /** + * Returns link capacity estimate derived from ThrouhgputPredictor. + */ + public Speeds getThrouhgputPredictorSpeeds( + WifiInfo wifiInfo, + ConnectionCapabilities connectionCapabilities) { + // Defaults to INVALID_THROUGHPUT. + Speeds speeds = new Speeds(); + + if (wifiInfo == null) { + return speeds; + } + int currFrequency = wifiInfo.getFrequency(); + int rssi = wifiInfo.getRssi(); + if (rssi == WifiInfo.INVALID_RSSI) { + return speeds; + } + + if (connectionCapabilities == null) { + return speeds; + } + + int ccaLevel = mWifiChannelUtilization.getUtilizationRatio(currFrequency); + + speeds.DownstreamKbps = mThroughputPredictor.predictRxThroughput(connectionCapabilities, + rssi, currFrequency, ccaLevel) * 1000; + speeds.UpstreamKbps = mThroughputPredictor.predictTxThroughput(connectionCapabilities, + rssi, currFrequency, ccaLevel) * 1000; + + return speeds; + } + + /** + * Get the number of tx bytes transmitted on current interface since the interface is created + * @return the number of tx bytes transmitted + */ + public long getTxTransmittedBytes() { + return mLastTxBytes; + } + + /** + * Get the number of rx bytes transmitted on current interface since the interface is created + * @return the number of tx bytes transmitted + */ + public long getRxTransmittedBytes() { + return mLastRxBytes; + } + /** * Update data stall detection, check throughput sufficiency and report wifi health stat * with the latest link layer stats diff --git a/service/java/com/android/server/wifi/WifiGlobals.java b/service/java/com/android/server/wifi/WifiGlobals.java index f83dd79ef8..1b37c07f91 100644 --- a/service/java/com/android/server/wifi/WifiGlobals.java +++ b/service/java/com/android/server/wifi/WifiGlobals.java @@ -52,50 +52,22 @@ public class WifiGlobals { private final WifiResourceCache mWifiResourceCache; private final AtomicInteger mPollRssiIntervalMillis = new AtomicInteger(-1); + private final AtomicInteger mPollRssiShortIntervalMillis = new AtomicInteger(); + private final AtomicInteger mPollRssiLongIntervalMillis = new AtomicInteger(); + private boolean mIsPollRssiIntervalOverridden = false; private final AtomicBoolean mIpReachabilityDisconnectEnabled = new AtomicBoolean(true); private final AtomicBoolean mIsBluetoothConnected = new AtomicBoolean(false); // Set default to false to check if the value will be overridden by WifiSettingConfigStore. private final AtomicBoolean mIsWepAllowed = new AtomicBoolean(false); private final AtomicBoolean mIsD2dStaConcurrencySupported = new AtomicBoolean(false); private final AtomicInteger mSendDhcpHostnameRestriction = new AtomicInteger(); - - // These are read from the overlay, cache them after boot up. - private final boolean mIsWpa3SaeUpgradeEnabled; private boolean mIsWpa3SaeUpgradeOffloadEnabled; - private final boolean mIsOweUpgradeEnabled; - private final boolean mFlushAnqpCacheOnWifiToggleOffEvent; - private final boolean mIsWpa3SaeH2eSupported; - private final String mP2pDeviceNamePrefix; - private final int mP2pDeviceNamePostfixNumDigits; - private final int mClientModeImplNumLogRecs; - private final boolean mSaveFactoryMacToConfigStoreEnabled; - private final int mWifiLowConnectedScoreThresholdToTriggerScanForMbb; - private final int mWifiLowConnectedScoreScanPeriodSeconds; - private final boolean mWifiAllowInsecureEnterpriseConfiguration; - private final boolean mIsP2pMacRandomizationSupported; - private final int mPollRssiShortIntervalMillis; - private final int mPollRssiLongIntervalMillis; - private final int mClientRssiMonitorThresholdDbm; - private final int mClientRssiMonitorHysteresisDb; + private boolean mIsWpa3SaeH2eSupported; private boolean mDisableFirmwareRoamingInIdleMode = false; - private final boolean mIsSupportMultiInternetDual5G; - private final int mRepeatedNudFailuresThreshold; - private final int mRepeatedNudFailuresWindowMs; - private final boolean mAdjustPollRssiIntervalEnabled; - private final boolean mWifiInterfaceAddedSelfRecoveryEnabled; - private final int mNetworkNotFoundEventThreshold; - private boolean mIsSwPnoEnabled; - private boolean mWepAllowedControlSupported; - private final boolean mIsWpaPersonalDeprecated; private final Map<String, List<String>> mCountryCodeToAfcServers; - private final long mWifiConfigMaxDisableDurationMs; // This is set by WifiManager#setVerboseLoggingEnabled(int). private int mVerboseLoggingLevel = WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED; private boolean mIsUsingExternalScorer = false; - private boolean mDisableUnwantedNetworkOnLowRssi = false; - private final boolean mIsAfcSupportedOnDevice; - private boolean mDisableNudDisconnectsForWapiInSpecificCc = false; - private boolean mD2dAllowedControlSupportedWhenInfraStaDisabled = false; private Set<String> mMacRandomizationUnsupportedSsidPrefixes = new ArraySet<>(); private SparseArray<SparseArray<CarrierSpecificEapFailureConfig>> @@ -105,74 +77,17 @@ public class WifiGlobals { public WifiGlobals(WifiContext context) { mContext = context; mWifiResourceCache = context.getResourceCache(); - mIsWpa3SaeUpgradeEnabled = mContext.getResources() - .getBoolean(R.bool.config_wifiSaeUpgradeEnabled); - mIsWpa3SaeUpgradeOffloadEnabled = mContext.getResources() + mIsWpa3SaeUpgradeOffloadEnabled = mWifiResourceCache .getBoolean(R.bool.config_wifiSaeUpgradeOffloadEnabled); - mIsOweUpgradeEnabled = mContext.getResources() - .getBoolean(R.bool.config_wifiOweUpgradeEnabled); - mFlushAnqpCacheOnWifiToggleOffEvent = mContext.getResources() - .getBoolean(R.bool.config_wifiFlushAnqpCacheOnWifiToggleOffEvent); - mIsWpa3SaeH2eSupported = mContext.getResources() - .getBoolean(R.bool.config_wifiSaeH2eSupported); - mP2pDeviceNamePrefix = mContext.getResources() - .getString(R.string.config_wifiP2pDeviceNamePrefix); - mP2pDeviceNamePostfixNumDigits = mContext.getResources() - .getInteger(R.integer.config_wifiP2pDeviceNamePostfixNumDigits); - mClientModeImplNumLogRecs = mContext.getResources() - .getInteger(R.integer.config_wifiClientModeImplNumLogRecs); - mSaveFactoryMacToConfigStoreEnabled = mContext.getResources() - .getBoolean(R.bool.config_wifiSaveFactoryMacToWifiConfigStore); - mWifiLowConnectedScoreThresholdToTriggerScanForMbb = mContext.getResources().getInteger( - R.integer.config_wifiLowConnectedScoreThresholdToTriggerScanForMbb); - mWifiLowConnectedScoreScanPeriodSeconds = mContext.getResources().getInteger( - R.integer.config_wifiLowConnectedScoreScanPeriodSeconds); - mWifiAllowInsecureEnterpriseConfiguration = mContext.getResources().getBoolean( - R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW); - mIsP2pMacRandomizationSupported = mContext.getResources().getBoolean( - R.bool.config_wifi_p2p_mac_randomization_supported); - mPollRssiIntervalMillis.set(mContext.getResources().getInteger( + mPollRssiIntervalMillis.set(mWifiResourceCache.getInteger( R.integer.config_wifiPollRssiIntervalMilliseconds)); - mPollRssiShortIntervalMillis = mContext.getResources().getInteger( - R.integer.config_wifiPollRssiIntervalMilliseconds); - mPollRssiLongIntervalMillis = mContext.getResources().getInteger( - R.integer.config_wifiPollRssiLongIntervalMilliseconds); - mClientRssiMonitorThresholdDbm = mContext.getResources().getInteger( - R.integer.config_wifiClientRssiMonitorThresholdDbm); - mClientRssiMonitorHysteresisDb = mContext.getResources().getInteger( - R.integer.config_wifiClientRssiMonitorHysteresisDb); - mAdjustPollRssiIntervalEnabled = mContext.getResources().getBoolean( - R.bool.config_wifiAdjustPollRssiIntervalEnabled); - mDisableFirmwareRoamingInIdleMode = mContext.getResources() - .getBoolean(R.bool.config_wifiDisableFirmwareRoamingInIdleMode); - mIsSupportMultiInternetDual5G = mContext.getResources().getBoolean( - R.bool.config_wifiAllowMultiInternetConnectDual5GFrequency); - mRepeatedNudFailuresThreshold = mContext.getResources() - .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresThreshold); - mRepeatedNudFailuresWindowMs = mContext.getResources() - .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresWindowMs); - mWifiInterfaceAddedSelfRecoveryEnabled = mContext.getResources().getBoolean( - R.bool.config_wifiInterfaceAddedSelfRecoveryEnabled); - mDisableUnwantedNetworkOnLowRssi = mContext.getResources().getBoolean( - R.bool.config_wifiDisableUnwantedNetworkOnLowRssi); - mDisableNudDisconnectsForWapiInSpecificCc = mContext.getResources().getBoolean( - R.bool.config_wifiDisableNudDisconnectsForWapiInSpecificCc); - mNetworkNotFoundEventThreshold = mContext.getResources().getInteger( - R.integer.config_wifiNetworkNotFoundEventThreshold); - mIsSwPnoEnabled = mContext.getResources() - .getBoolean(R.bool.config_wifiSwPnoEnabled); - mWepAllowedControlSupported = mContext.getResources() - .getBoolean(R.bool.config_wifiWepAllowedControlSupported); - mIsWpaPersonalDeprecated = mContext.getResources() - .getBoolean(R.bool.config_wifiWpaPersonalDeprecated); - mIsAfcSupportedOnDevice = mContext.getResources().getBoolean(R.bool.config_wifiAfcSupported) - && mContext.getResources().getBoolean(R.bool.config_wifiSoftap6ghzSupported) - && mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport); - mWifiConfigMaxDisableDurationMs = mContext.getResources() - .getInteger(R.integer.config_wifiDisableTemporaryMaximumDurationMs); - mD2dAllowedControlSupportedWhenInfraStaDisabled = mContext.getResources() - .getBoolean(R.bool.config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled); - Set<String> unsupportedSsidPrefixes = new ArraySet<>(mContext.getResources().getStringArray( + mPollRssiShortIntervalMillis.set(mWifiResourceCache.getInteger( + R.integer.config_wifiPollRssiIntervalMilliseconds)); + mPollRssiLongIntervalMillis.set(mWifiResourceCache.getInteger( + R.integer.config_wifiPollRssiLongIntervalMilliseconds)); + mIsWpa3SaeH2eSupported = mWifiResourceCache + .getBoolean(R.bool.config_wifiSaeH2eSupported); + Set<String> unsupportedSsidPrefixes = new ArraySet<>(mWifiResourceCache.getStringArray( R.array.config_wifiForceDisableMacRandomizationSsidPrefixList)); mCountryCodeToAfcServers = getCountryCodeToAfcServersMap(); if (!unsupportedSsidPrefixes.isEmpty()) { @@ -209,7 +124,7 @@ public class WifiGlobals { } private void loadCarrierSpecificEapFailureConfigMap() { - String[] eapFailureOverrides = mContext.getResources().getStringArray( + String[] eapFailureOverrides = mWifiResourceCache.getStringArray( R.array.config_wifiEapFailureConfig); if (eapFailureOverrides == null) { return; @@ -248,7 +163,7 @@ public class WifiGlobals { private Map<String, List<String>> getCountryCodeToAfcServersMap() { Map<String, List<String>> countryCodeToAfcServers = new HashMap<>(); - String[] countryCodeToAfcServersFromConfig = mContext.getResources().getStringArray( + String[] countryCodeToAfcServersFromConfig = mWifiResourceCache.getStringArray( R.array.config_wifiAfcServerUrlsForCountry); if (countryCodeToAfcServersFromConfig == null) { @@ -300,7 +215,9 @@ public class WifiGlobals { * Returns whether this device supports AFC. */ public boolean isAfcSupportedOnDevice() { - return mIsAfcSupportedOnDevice; + return mWifiResourceCache.getBoolean(R.bool.config_wifiAfcSupported) + && mWifiResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported) + && mWifiResourceCache.getBoolean(R.bool.config_wifi6ghzSupport); } /** Sets whether CMD_IP_REACHABILITY_LOST events should trigger disconnects. */ @@ -335,7 +252,7 @@ public class WifiGlobals { * @return boolean true if Connected MAC randomization is supported, false otherwise */ public boolean isConnectedMacRandomizationEnabled() { - return mContext.getResources().getBoolean( + return mWifiResourceCache.getBoolean( R.bool.config_wifi_connected_mac_randomization_supported); } @@ -345,9 +262,9 @@ public class WifiGlobals { * @return boolean true if WEP networks are deprecated, false otherwise. */ public boolean isWepDeprecated() { - return mWifiResourceCache.getBoolean(R.bool.config_wifiWepDeprecated, - "config_wifiWepDeprecated") - || (mWepAllowedControlSupported && !mIsWepAllowed.get()); + return mWifiResourceCache.getBoolean(R.bool.config_wifiWepDeprecated) + || (mWifiResourceCache.getBoolean(R.bool.config_wifiWepAllowedControlSupported) + && !mIsWepAllowed.get()); } /** @@ -356,8 +273,8 @@ public class WifiGlobals { * @return boolean true if WEP networks are supported, false otherwise. */ public boolean isWepSupported() { - return !mWifiResourceCache.getBoolean(R.bool.config_wifiWepDeprecated, - "config_wifiWepDeprecated"); + return !mWifiResourceCache.getBoolean(R.bool.config_wifiWepDeprecated + ); } /** @@ -366,7 +283,8 @@ public class WifiGlobals { * @return boolean true if WPA-Personal networks are deprecated, false otherwise. */ public boolean isWpaPersonalDeprecated() { - return mIsWpaPersonalDeprecated; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiWpaPersonalDeprecated); } /** @@ -374,7 +292,8 @@ public class WifiGlobals { * @return if the device should disable firmware roaming in idle mode. */ public boolean isDisableFirmwareRoamingInIdleMode() { - return mDisableFirmwareRoamingInIdleMode; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiDisableFirmwareRoamingInIdleMode); } /** @@ -382,21 +301,24 @@ public class WifiGlobals { * connect simultaneously to both 5GHz high and 5GHz low. */ public boolean isSupportMultiInternetDual5G() { - return mIsSupportMultiInternetDual5G; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiAllowMultiInternetConnectDual5GFrequency); } /** * Get number of repeated NUD failures needed to disable a network. */ public int getRepeatedNudFailuresThreshold() { - return mRepeatedNudFailuresThreshold; + return mWifiResourceCache + .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresThreshold); } /** * Get the time window in millis to count for repeated NUD failures. */ public int getRepeatedNudFailuresWindowMs() { - return mRepeatedNudFailuresWindowMs; + return mWifiResourceCache + .getInteger(R.integer.config_wifiDisableReasonRepeatedNudFailuresWindowMs); } /** @@ -422,7 +344,8 @@ public class WifiGlobals { * @return boolean true if auto-upgrade is enabled, false otherwise. */ public boolean isWpa3SaeUpgradeEnabled() { - return mIsWpa3SaeUpgradeEnabled; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiSaeUpgradeEnabled); } /** @@ -451,7 +374,8 @@ public class WifiGlobals { */ public boolean isOweUpgradeEnabled() { // OWE auto-upgrade is supported on S or newer releases. - return SdkLevel.isAtLeastS() && mIsOweUpgradeEnabled; + return SdkLevel.isAtLeastS() && mWifiResourceCache + .getBoolean(R.bool.config_wifiOweUpgradeEnabled); } /** @@ -460,7 +384,8 @@ public class WifiGlobals { * @return boolean true to flush ANQP cache on Wi-Fi toggle off event, false otherwise. */ public boolean flushAnqpCacheOnWifiToggleOffEvent() { - return mFlushAnqpCacheOnWifiToggleOffEvent; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiFlushAnqpCacheOnWifiToggleOffEvent); } /* @@ -473,6 +398,14 @@ public class WifiGlobals { } /** + * Helper method to enable WPA3 SAE Hash-to-Element support based on the supplicant aidl + * version. + */ + public void enableWpa3SaeH2eSupport() { + mIsWpa3SaeH2eSupported = true; + } + + /** * Record the verbose logging level */ public void setVerboseLoggingLevel(int level) { @@ -501,47 +434,59 @@ public class WifiGlobals { /** Get the prefix of the default wifi p2p device name. */ public String getWifiP2pDeviceNamePrefix() { - return mP2pDeviceNamePrefix; + return mWifiResourceCache + .getString(R.string.config_wifiP2pDeviceNamePrefix); } /** Get the number of the default wifi p2p device name postfix digit. */ public int getWifiP2pDeviceNamePostfixNumDigits() { - return mP2pDeviceNamePostfixNumDigits; + return mWifiResourceCache + .getInteger(R.integer.config_wifiP2pDeviceNamePostfixNumDigits); } /** Get the number of log records to maintain. */ public int getClientModeImplNumLogRecs() { - return mClientModeImplNumLogRecs; + return mWifiResourceCache.getInteger(R.integer.config_wifiClientModeImplNumLogRecs); } /** Get whether to use the saved factory MAC address when available **/ public boolean isSaveFactoryMacToConfigStoreEnabled() { - return mSaveFactoryMacToConfigStoreEnabled; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiSaveFactoryMacToWifiConfigStore); } /** Get the low score threshold to do scan for MBB when external scorer is not used. **/ public int getWifiLowConnectedScoreThresholdToTriggerScanForMbb() { - return mWifiLowConnectedScoreThresholdToTriggerScanForMbb; + return mWifiResourceCache.getInteger( + R.integer.config_wifiLowConnectedScoreThresholdToTriggerScanForMbb); } /** Get the minimum period between the extra scans triggered for MBB when score is low **/ public int getWifiLowConnectedScoreScanPeriodSeconds() { - return mWifiLowConnectedScoreScanPeriodSeconds; + return mWifiResourceCache.getInteger( + R.integer.config_wifiLowConnectedScoreScanPeriodSeconds); } /** Get whether or not insecure enterprise configuration is allowed. */ public boolean isInsecureEnterpriseConfigurationAllowed() { - return mWifiAllowInsecureEnterpriseConfiguration; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiAllowInsecureEnterpriseConfigurationsForSettingsAndSUW); } /** Get whether or not P2P MAC randomization is supported */ public boolean isP2pMacRandomizationSupported() { - return mIsP2pMacRandomizationSupported; + return mWifiResourceCache.getBoolean( + R.bool.config_wifi_p2p_mac_randomization_supported); } /** Get the regular (short) interval between RSSI polls, in milliseconds. */ public int getPollRssiShortIntervalMillis() { - return mPollRssiShortIntervalMillis; + return mPollRssiShortIntervalMillis.get(); + } + + /** Set the regular (short) interval between RSSI polls, in milliseconds. */ + public void setPollRssiShortIntervalMillis(int newPollIntervalMillis) { + mPollRssiShortIntervalMillis.set(newPollIntervalMillis); } /** @@ -550,7 +495,16 @@ public class WifiGlobals { * interval. */ public int getPollRssiLongIntervalMillis() { - return mPollRssiLongIntervalMillis; + return mPollRssiLongIntervalMillis.get(); + } + + /** + * Set the long interval between RSSI polls, in milliseconds. The long interval is to + * reduce power consumption of the polls. This value should be greater than the regular + * interval. + */ + public void setPollRssiLongIntervalMillis(int newPollIntervalMillis) { + mPollRssiLongIntervalMillis.set(newPollIntervalMillis); } /** @@ -560,7 +514,8 @@ public class WifiGlobals { * Threshold, set regular interval and disable RSSI monitoring. */ public int getClientRssiMonitorThresholdDbm() { - return mClientRssiMonitorThresholdDbm; + return mWifiResourceCache.getInteger( + R.integer.config_wifiClientRssiMonitorThresholdDbm); } /** @@ -568,7 +523,8 @@ public class WifiGlobals { * frequent switch between regular and long polling intervals. */ public int getClientRssiMonitorHysteresisDb() { - return mClientRssiMonitorHysteresisDb; + return mWifiResourceCache.getInteger( + R.integer.config_wifiClientRssiMonitorHysteresisDb); } /** @@ -576,14 +532,26 @@ public class WifiGlobals { * is enabled. */ public boolean isAdjustPollRssiIntervalEnabled() { - return mAdjustPollRssiIntervalEnabled; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiAdjustPollRssiIntervalEnabled); + } + + /** Set whether the RSSI polling interval is overridden to a fixed value **/ + public void setPollRssiIntervalOverridden(boolean isPollRssiIntervalOverridden) { + mIsPollRssiIntervalOverridden = isPollRssiIntervalOverridden; + } + + /** Get whether the RSSI polling interval is overridden to a fixed value **/ + public boolean isPollRssiIntervalOverridden() { + return mIsPollRssiIntervalOverridden; } /** * Get whether hot-plugging an interface will trigger a restart of the wifi stack. */ public boolean isWifiInterfaceAddedSelfRecoveryEnabled() { - return mWifiInterfaceAddedSelfRecoveryEnabled; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiInterfaceAddedSelfRecoveryEnabled); } /** @@ -591,36 +559,40 @@ public class WifiGlobals { */ public boolean isBackgroundScanSupported() { return mWifiResourceCache - .getBoolean(R.bool.config_wifi_background_scan_support, - "config_wifi_background_scan_support"); + .getBoolean(R.bool.config_wifi_background_scan_support + ); }; /** * Get whether software pno is enabled. */ public boolean isSwPnoEnabled() { - return mIsSwPnoEnabled; + return mWifiResourceCache + .getBoolean(R.bool.config_wifiSwPnoEnabled); }; /** * Get whether to temporarily disable a unwanted network that has low RSSI. */ public boolean disableUnwantedNetworkOnLowRssi() { - return mDisableUnwantedNetworkOnLowRssi; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiDisableUnwantedNetworkOnLowRssi); } /** * Get whether to disable NUD disconnects for WAPI configurations in a specific CC. */ public boolean disableNudDisconnectsForWapiInSpecificCc() { - return mDisableNudDisconnectsForWapiInSpecificCc; + return mWifiResourceCache.getBoolean( + R.bool.config_wifiDisableNudDisconnectsForWapiInSpecificCc); } /** * Get the threshold to use for blocking a network due to NETWORK_NOT_FOUND_EVENT failure. */ public int getNetworkNotFoundEventThreshold() { - return mNetworkNotFoundEventThreshold; + return mWifiResourceCache.getInteger( + R.integer.config_wifiNetworkNotFoundEventThreshold); } /** @@ -648,10 +620,15 @@ public class WifiGlobals { * Returns whether the device supports device-to-device when infra STA is disabled. */ public boolean isD2dSupportedWhenInfraStaDisabled() { - return mD2dAllowedControlSupportedWhenInfraStaDisabled + return mWifiResourceCache + .getBoolean(R.bool.config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled) && !mIsD2dStaConcurrencySupported.get(); } + public boolean isNetworkSelectionSetTargetBssid() { + return mWifiResourceCache.getBoolean(R.bool.config_wifiNetworkSelectionSetTargetBssid); + } + /** * Set the global dhcp hostname restriction. */ @@ -672,50 +649,27 @@ public class WifiGlobals { * Get the maximum Wifi temporary disable duration. */ public long getWifiConfigMaxDisableDurationMs() { - return mWifiConfigMaxDisableDurationMs; + return mWifiResourceCache + .getInteger(R.integer.config_wifiDisableTemporaryMaximumDurationMs); } /** Dump method for debugging */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dump of WifiGlobals"); pw.println("mPollRssiIntervalMillis=" + mPollRssiIntervalMillis.get()); + pw.println("mIsPollRssiIntervalOverridden=" + mIsPollRssiIntervalOverridden); + pw.println("mPollRssiShortIntervalMillis=" + mPollRssiShortIntervalMillis.get()); + pw.println("mPollRssiLongIntervalMillis=" + mPollRssiLongIntervalMillis.get()); pw.println("mIpReachabilityDisconnectEnabled=" + mIpReachabilityDisconnectEnabled.get()); pw.println("mIsBluetoothConnected=" + mIsBluetoothConnected.get()); - pw.println("mIsWpa3SaeUpgradeEnabled=" + mIsWpa3SaeUpgradeEnabled); pw.println("mIsWpa3SaeUpgradeOffloadEnabled=" + mIsWpa3SaeUpgradeOffloadEnabled); - pw.println("mIsOweUpgradeEnabled=" + mIsOweUpgradeEnabled); - pw.println("mFlushAnqpCacheOnWifiToggleOffEvent=" + mFlushAnqpCacheOnWifiToggleOffEvent); - pw.println("mIsWpa3SaeH2eSupported=" + mIsWpa3SaeH2eSupported); - pw.println("mP2pDeviceNamePrefix=" + mP2pDeviceNamePrefix); - pw.println("mP2pDeviceNamePostfixNumDigits=" + mP2pDeviceNamePostfixNumDigits); - pw.println("mClientModeImplNumLogRecs=" + mClientModeImplNumLogRecs); - pw.println("mSaveFactoryMacToConfigStoreEnabled=" + mSaveFactoryMacToConfigStoreEnabled); - pw.println("mWifiLowConnectedScoreThresholdToTriggerScanForMbb=" - + mWifiLowConnectedScoreThresholdToTriggerScanForMbb); - pw.println("mWifiLowConnectedScoreScanPeriodSeconds=" - + mWifiLowConnectedScoreScanPeriodSeconds); pw.println("mIsUsingExternalScorer=" + mIsUsingExternalScorer); - pw.println("mWifiAllowInsecureEnterpriseConfiguration=" - + mWifiAllowInsecureEnterpriseConfiguration); - pw.println("mIsP2pMacRandomizationSupported" + mIsP2pMacRandomizationSupported); - pw.println("mWifiInterfaceAddedSelfRecoveryEnabled=" - + mWifiInterfaceAddedSelfRecoveryEnabled); - pw.println("mDisableUnwantedNetworkOnLowRssi=" + mDisableUnwantedNetworkOnLowRssi); - pw.println("mNetworkNotFoundEventThreshold=" + mNetworkNotFoundEventThreshold); - pw.println("mIsSwPnoEnabled=" + mIsSwPnoEnabled); - pw.println("mIsWpaPersonalDeprecated=" + mIsWpaPersonalDeprecated); pw.println("mIsWepAllowed=" + mIsWepAllowed.get()); - pw.println("mWepAllowedControlSupported=" + mWepAllowedControlSupported); pw.println("mDisableFirmwareRoamingInIdleMode=" + mDisableFirmwareRoamingInIdleMode); - pw.println("mRepeatedNudFailuresThreshold=" + mRepeatedNudFailuresThreshold); - pw.println("mRepeatedNudFailuresWindowMs=" + mRepeatedNudFailuresWindowMs); - pw.println("mCarrierSpecificEapFailureConfigMapPerCarrierId mapping below:"); - pw.println("mWifiConfigMaxDisableDurationMs=" + mWifiConfigMaxDisableDurationMs); - pw.println("mD2dAllowedControlSupportedWhenInfraStaDisabled=" - + mD2dAllowedControlSupportedWhenInfraStaDisabled); pw.println("IsD2dSupportedWhenInfraStaDisabled=" + isD2dSupportedWhenInfraStaDisabled()); + pw.println("mIsWpa3SaeH2eSupported=" + mIsWpa3SaeH2eSupported); for (int i = 0; i < mCarrierSpecificEapFailureConfigMapPerCarrierId.size(); i++) { int carrierId = mCarrierSpecificEapFailureConfigMapPerCarrierId.keyAt(i); SparseArray<CarrierSpecificEapFailureConfig> perFailureMap = @@ -729,7 +683,6 @@ public class WifiGlobals { + ", durationMs=" + perFailureMap.valueAt(j).durationMs); } } - pw.println("mIsSupportMultiInternetDual5G=" + mIsSupportMultiInternetDual5G); pw.println("mSendDhcpHostnameRestriction=" + mSendDhcpHostnameRestriction.get()); } } diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 9553434380..e43234e7a8 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -269,6 +269,9 @@ public class WifiInjector { private final WifiRoamingModeManager mWifiRoamingModeManager; private final TwtManager mTwtManager; private final WifiVoipDetector mWifiVoipDetector; + private final boolean mHasActiveModem; + private final RunnerHandler mWifiHandler; + private boolean mVerboseLoggingEnabled; public WifiInjector(WifiContext context) { if (context == null) { @@ -297,20 +300,20 @@ public class WifiInjector { mWifiMonitor = new WifiMonitor(); mBatteryStats = context.getSystemService(BatteryStatsManager.class); mWifiP2pMetrics = new WifiP2pMetrics(mClock, mContext); - RunnerHandler wifiHandler = new RunnerHandler(wifiLooper, context.getResources().getInteger( + mWifiHandler = new RunnerHandler(wifiLooper, context.getResources().getInteger( R.integer.config_wifiConfigurationWifiRunnerThresholdInMs), mWifiHandlerLocalLog); - mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(context, wifiHandler); + mWifiDeviceStateChangeManager = new WifiDeviceStateChangeManager(context, mWifiHandler); + mWifiGlobals = new WifiGlobals(mContext); mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, wifiLooper, awareMetrics, rttMetrics, new WifiPowerMetrics(mBatteryStats), mWifiP2pMetrics, - mDppMetrics, mWifiMonitor, mWifiDeviceStateChangeManager); + mDppMetrics, mWifiMonitor, mWifiDeviceStateChangeManager, mWifiGlobals); mWifiDiagnosticsHandlerThread = new HandlerThread("WifiDiagnostics"); mWifiDiagnosticsHandlerThread.start(); mWifiNotificationManager = new WifiNotificationManager(mContext); - mWifiGlobals = new WifiGlobals(mContext); mScoringParams = new ScoringParams(mContext); mWifiChannelUtilizationScan = new WifiChannelUtilization(mClock, mContext); mSettingsMigrationDataHolder = new SettingsMigrationDataHolder(mContext); @@ -324,35 +327,35 @@ public class WifiInjector { mWifiBackupRestore = new WifiBackupRestore(mWifiPermissionsUtil); mSoftApBackupRestore = new SoftApBackupRestore(mContext, mSettingsMigrationDataHolder); mWifiStateTracker = new WifiStateTracker(mBatteryStats); - mWifiThreadRunner = new WifiThreadRunner(wifiHandler); + mWifiThreadRunner = new WifiThreadRunner(mWifiHandler); mWifiDialogManager = new WifiDialogManager(mContext, mWifiThreadRunner, mFrameworkFacade, this); - mSsidTranslator = new SsidTranslator(mContext, wifiHandler); + mSsidTranslator = new SsidTranslator(mContext, mWifiHandler); mPasspointProvisionerHandlerThread = new HandlerThread("PasspointProvisionerHandlerThread"); mPasspointProvisionerHandlerThread.start(); - mDeviceConfigFacade = new DeviceConfigFacade(mContext, wifiHandler, mWifiMetrics); + mDeviceConfigFacade = new DeviceConfigFacade(mContext, mWifiHandler, mWifiMetrics); mFeatureFlags = mDeviceConfigFacade.getFeatureFlags(); mAdaptiveConnectivityEnabledSettingObserver = - new AdaptiveConnectivityEnabledSettingObserver(wifiHandler, mWifiMetrics, + new AdaptiveConnectivityEnabledSettingObserver(mWifiHandler, mWifiMetrics, mFrameworkFacade, mContext); // Modules interacting with Native. - mHalDeviceManager = new HalDeviceManager(mContext, mClock, this, wifiHandler); + mHalDeviceManager = new HalDeviceManager(mContext, mClock, this, mWifiHandler); mInterfaceConflictManager = new InterfaceConflictManager(this, mContext, mFrameworkFacade, mHalDeviceManager, mWifiThreadRunner, mWifiDialogManager, new LocalLog( mContext.getSystemService(ActivityManager.class).isLowRamDevice() ? 128 : 256)); - mWifiVendorHal = new WifiVendorHal(mContext, mHalDeviceManager, wifiHandler, mWifiGlobals, + mWifiVendorHal = new WifiVendorHal(mContext, mHalDeviceManager, mWifiHandler, mWifiGlobals, mSsidTranslator); mSupplicantStaIfaceHal = new SupplicantStaIfaceHal( - mContext, mWifiMonitor, mFrameworkFacade, wifiHandler, mClock, mWifiMetrics, + mContext, mWifiMonitor, mFrameworkFacade, mWifiHandler, mClock, mWifiMetrics, mWifiGlobals, mSsidTranslator, this); - mHostapdHal = new HostapdHal(mContext, wifiHandler); + mHostapdHal = new HostapdHal(mContext, mWifiHandler); mWifiCondManager = (WifiNl80211Manager) mContext.getSystemService( Context.WIFI_NL80211_SERVICE); mWifiNative = new WifiNative( mWifiVendorHal, mSupplicantStaIfaceHal, mHostapdHal, mWifiCondManager, mWifiMonitor, mPropertyService, mWifiMetrics, - wifiHandler, new Random(), mBuildProperties, this); + mWifiHandler, new Random(), mBuildProperties, this); mWifiP2pMonitor = new WifiP2pMonitor(); mSupplicantP2pIfaceHal = new SupplicantP2pIfaceHal(mWifiP2pMonitor, mWifiGlobals, this); mWifiP2pNative = new WifiP2pNative(mWifiCondManager, mWifiNative, mWifiMetrics, @@ -362,7 +365,7 @@ public class WifiInjector { if (SdkLevel.isAtLeastS()) { mCoexManager = new CoexManager(mContext, mWifiNative, makeTelephonyManager(), subscriptionManager, mContext.getSystemService(CarrierConfigManager.class), - wifiHandler); + mWifiHandler); } else { mCoexManager = null; } @@ -390,7 +393,7 @@ public class WifiInjector { wifiLooper); mWifiCarrierInfoManager = new WifiCarrierInfoManager(makeTelephonyManager(), subscriptionManager, this, mFrameworkFacade, mContext, - mWifiConfigStore, wifiHandler, mWifiMetrics, mClock, mWifiPseudonymManager); + mWifiConfigStore, mWifiHandler, mWifiMetrics, mClock, mWifiPseudonymManager); String l2KeySeed = Secure.getString(mContext.getContentResolver(), Secure.ANDROID_ID); mWifiScoreCard = new WifiScoreCard(mClock, l2KeySeed, mDeviceConfigFacade, mContext, mWifiGlobals); @@ -438,8 +441,8 @@ public class WifiInjector { new RandomizedMacStoreData(), mLruConnectionTracker, this, - wifiHandler); - mSettingsConfigStore = new WifiSettingsConfigStore(context, wifiHandler, + mWifiHandler); + mSettingsConfigStore = new WifiSettingsConfigStore(context, mWifiHandler, mSettingsMigrationDataHolder, mWifiConfigManager, mWifiConfigStore); mWifiSettingsBackupRestore = new WifiSettingsBackupRestore(mSettingsConfigStore); mSettingsStore = new WifiSettingsStore(mContext, mSettingsConfigStore, mWifiThreadRunner, @@ -471,12 +474,12 @@ public class WifiInjector { mThroughputScorer = new ThroughputScorer(mContext, mScoringParams); mWifiNetworkSelector.registerCandidateScorer(mThroughputScorer); mWifiMetrics.setWifiNetworkSelector(mWifiNetworkSelector); - mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, wifiHandler, + mWifiNetworkSuggestionsManager = new WifiNetworkSuggestionsManager(mContext, mWifiHandler, this, mWifiPermissionsUtil, mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker, mClock); mPasspointManager = new PasspointManager(mContext, this, - wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(), + mWifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(), mWifiConfigManager, mWifiConfigStore, mSettingsStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil, mWifiPermissionsUtil); mNominateHelper = @@ -498,7 +501,7 @@ public class WifiInjector { mDefaultClientModeManager = new DefaultClientModeManager(); mExternalScoreUpdateObserverProxy = new ExternalScoreUpdateObserverProxy(mWifiThreadRunner); - mDppManager = new DppManager(this, wifiHandler, mWifiNative, + mDppManager = new DppManager(this, mWifiHandler, mWifiNative, mWifiConfigManager, mContext, mDppMetrics, mScanRequestProxy, mWifiPermissionsUtil); mActiveModeWarden = new ActiveModeWarden(this, wifiLooper, mWifiNative, mDefaultClientModeManager, mBatteryStats, mWifiDiagnostics, @@ -506,10 +509,10 @@ public class WifiInjector { mExternalScoreUpdateObserverProxy, mDppManager, mWifiGlobals); mWifiMetrics.setActiveModeWarden(mActiveModeWarden); mWifiHealthMonitor = new WifiHealthMonitor(mContext, this, mClock, mWifiConfigManager, - mWifiScoreCard, wifiHandler, mWifiNative, l2KeySeed, mDeviceConfigFacade, + mWifiScoreCard, mWifiHandler, mWifiNative, l2KeySeed, mDeviceConfigFacade, mActiveModeWarden); mWifiDataStall = new WifiDataStall(mWifiMetrics, mContext, - mDeviceConfigFacade, wifiChannelUtilizationConnected, mClock, wifiHandler, + mDeviceConfigFacade, wifiChannelUtilizationConnected, mClock, mWifiHandler, mThroughputPredictor, mActiveModeWarden, mCmiMonitor, mWifiGlobals); mWifiMetrics.setWifiDataStall(mWifiDataStall); mWifiMetrics.setWifiHealthMonitor(mWifiHealthMonitor); @@ -524,8 +527,8 @@ public class WifiInjector { new ConnectToNetworkNotificationBuilder(mContext, mFrameworkFacade), mMakeBeforeBreakManager, mWifiNotificationManager, mWifiPermissionsUtil); mMultiInternetManager = new MultiInternetManager(mActiveModeWarden, mFrameworkFacade, - mContext, mCmiMonitor, mSettingsStore, wifiHandler, mClock); - mExternalPnoScanRequestManager = new ExternalPnoScanRequestManager(wifiHandler, mContext); + mContext, mCmiMonitor, mSettingsStore, mWifiHandler, mClock); + mExternalPnoScanRequestManager = new ExternalPnoScanRequestManager(mWifiHandler, mContext); mCountryCode = new WifiCountryCode(mContext, mActiveModeWarden, mWifiP2pMetrics, mCmiMonitor, mWifiNative, mSettingsConfigStore, mClock, mWifiPermissionsUtil, mWifiCarrierInfoManager); @@ -533,7 +536,7 @@ public class WifiInjector { mContext, mScoringParams, mWifiConfigManager, mWifiNetworkSuggestionsManager, mWifiNetworkSelector, mWifiConnectivityHelper, mWifiLastResortWatchdog, mOpenNetworkNotifier, - mWifiMetrics, wifiHandler, + mWifiMetrics, mWifiHandler, mClock, mConnectivityLocalLog, mWifiScoreCard, mWifiBlocklistMonitor, mWifiChannelUtilizationScan, mPasspointManager, mMultiInternetManager, mDeviceConfigFacade, mActiveModeWarden, mFrameworkFacade, mWifiGlobals, @@ -544,7 +547,7 @@ public class WifiInjector { mWifiThreadRunner); mConnectionFailureNotifier = new ConnectionFailureNotifier( mContext, mFrameworkFacade, mWifiConfigManager, - mWifiConnectivityManager, wifiHandler, + mWifiConnectivityManager, mWifiHandler, mWifiNotificationManager, mConnectionFailureNotificationBuilder, mWifiDialogManager); mWifiNetworkFactory = new WifiNetworkFactory( @@ -575,27 +578,28 @@ public class WifiInjector { mWifiPermissionsUtil, mMultiInternetManager, mWifiConnectivityManager, mConnectivityLocalLog); mWifiScanAlwaysAvailableSettingsCompatibility = - new WifiScanAlwaysAvailableSettingsCompatibility(mContext, wifiHandler, + new WifiScanAlwaysAvailableSettingsCompatibility(mContext, mWifiHandler, mSettingsStore, mActiveModeWarden, mFrameworkFacade); mWifiApConfigStore = new WifiApConfigStore( - mContext, this, wifiHandler, mBackupManagerProxy, + mContext, this, mWifiHandler, mBackupManagerProxy, mWifiConfigStore, mWifiConfigManager, mActiveModeWarden, mWifiMetrics); WakeupNotificationFactory wakeupNotificationFactory = new WakeupNotificationFactory(mContext, mFrameworkFacade); WakeupOnboarding wakeupOnboarding = new WakeupOnboarding(mContext, mWifiConfigManager, - wifiHandler, mFrameworkFacade, wakeupNotificationFactory, mWifiNotificationManager); - mWakeupController = new WakeupController(mContext, wifiHandler, + mWifiHandler, mFrameworkFacade, wakeupNotificationFactory, + mWifiNotificationManager); + mWakeupController = new WakeupController(mContext, mWifiHandler, new WakeupLock(mWifiConfigManager, mWifiMetrics.getWakeupMetrics(), mClock), new WakeupEvaluator(mScoringParams), wakeupOnboarding, mWifiConfigManager, mWifiConfigStore, mWifiNetworkSuggestionsManager, mWifiMetrics.getWakeupMetrics(), this, mFrameworkFacade, mClock, mActiveModeWarden); mLockManager = new WifiLockManager(mContext, mBatteryStats, mActiveModeWarden, - mFrameworkFacade, wifiHandler, mClock, mWifiMetrics, mDeviceConfigFacade, + mFrameworkFacade, mWifiHandler, mClock, mWifiMetrics, mDeviceConfigFacade, mWifiPermissionsUtil, mWifiDeviceStateChangeManager); mSelfRecovery = new SelfRecovery(mContext, mActiveModeWarden, mClock, mWifiNative, mWifiGlobals); mWifiMulticastLockManager = new WifiMulticastLockManager(mActiveModeWarden, mBatteryStats, - wifiLooper); + wifiLooper, mContext); mApplicationQosPolicyRequestHandler = new ApplicationQosPolicyRequestHandler( mActiveModeWarden, mWifiNative, mWifiHandlerThread, mDeviceConfigFacade, mContext); @@ -606,7 +610,7 @@ public class WifiInjector { mSimRequiredNotifier = new SimRequiredNotifier(mContext, mFrameworkFacade, mWifiNotificationManager); mWifiPulledAtomLogger = new WifiPulledAtomLogger( - mContext.getSystemService(StatsManager.class), wifiHandler, + mContext.getSystemService(StatsManager.class), mWifiHandler, mContext, this); mAfcLocationUtil = new AfcLocationUtil(); mAfcClient = new AfcClient(BackgroundThread.getHandler()); @@ -620,15 +624,16 @@ public class WifiInjector { mActiveModeWarden, new WifiRoamingConfigStore(mWifiConfigManager, mWifiConfigStore)); - mTwtManager = new TwtManager(this, mCmiMonitor, mWifiNative, wifiHandler, mClock, + mTwtManager = new TwtManager(this, mCmiMonitor, mWifiNative, mWifiHandler, mClock, WifiTwtSession.MAX_TWT_SESSIONS, 1); mBackupRestoreController = new BackupRestoreController(mWifiSettingsBackupRestore, mClock); - if (mFeatureFlags.voipDetection() && SdkLevel.isAtLeastV()) { - mWifiVoipDetector = new WifiVoipDetector(mContext, wifiHandler, this, + if (mFeatureFlags.voipDetectionBugfix() && SdkLevel.isAtLeastV()) { + mWifiVoipDetector = new WifiVoipDetector(mContext, mWifiHandler, this, mWifiCarrierInfoManager); } else { mWifiVoipDetector = null; } + mHasActiveModem = makeTelephonyManager().getActiveModemCount() > 0; } /** @@ -651,6 +656,7 @@ public class WifiInjector { */ public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) { Log.i(TAG, "enableVerboseLogging " + verboseEnabled + " hal " + halVerboseEnabled); + mVerboseLoggingEnabled = verboseEnabled; mWifiLastResortWatchdog.enableVerboseLogging(verboseEnabled); mWifiBackupRestore.enableVerboseLogging(verboseEnabled); mHalDeviceManager.enableVerboseLogging(verboseEnabled); @@ -688,6 +694,7 @@ public class WifiInjector { mExternalPnoScanRequestManager.enableVerboseLogging(verboseEnabled); mMultiInternetWifiNetworkFactory.enableVerboseLogging(verboseEnabled); mWifiRoamingModeManager.enableVerboseLogging(verboseEnabled); + mWifiHandler.enableVerboseLogging(verboseEnabled); } public UserManager getUserManager() { @@ -1295,4 +1302,18 @@ public class WifiInjector { public WifiVoipDetector getWifiVoipDetector() { return mWifiVoipDetector; } + + /** + * Return true if there is any active modem on the device. + */ + public boolean hasActiveModem() { + return mHasActiveModem; + } + + /** + * Check if verbose logging enabled + */ + public boolean isVerboseLoggingEnabled() { + return mVerboseLoggingEnabled; + } } diff --git a/service/java/com/android/server/wifi/WifiLinkLayerStats.java b/service/java/com/android/server/wifi/WifiLinkLayerStats.java index 2db7c24e28..0276514a63 100644 --- a/service/java/com/android/server/wifi/WifiLinkLayerStats.java +++ b/service/java/com/android/server/wifi/WifiLinkLayerStats.java @@ -16,10 +16,13 @@ package com.android.server.wifi; +import android.net.wifi.WifiManager; import android.net.wifi.WifiUsabilityStatsEntry.LinkState; +import android.net.wifi.WifiUsabilityStatsEntry.WifiChannelBandwidth; import android.util.SparseArray; import java.util.Arrays; +import java.util.List; /** * A class representing link layer statistics collected over a Wifi Interface. @@ -155,11 +158,29 @@ public class WifiLinkLayerStats { */ public PeerInfo[] peerInfo; + public List<ScanResultWithSameFreq> scan_results_same_freq; } public LinkSpecificStats[] links; /** + * Scan result who has the same frequency with WiFi Link + */ + public static class ScanResultWithSameFreq { + /** + * timestamp in microseconds (since boot) when + * this result was last seen. + */ + public long scan_result_timestamp_micros; + /** The detected signal level in dBm, also known as the RSSI */ + public int rssi; + /** The center frequency of the primary 20 MHz frequency (in MHz) of the channel */ + public int frequencyMhz; + /** BSSID of access point */ + public String bssid; + } + + /** * The stats below which is already captured in WifiLinkLayerStats#LinkSpecificStats will be * having an aggregated value. The aggregation logic is defined at * wifiNative#setAggregatedLinkLayerStats(). @@ -303,6 +324,18 @@ public class WifiLinkLayerStats { */ public int frequency; /** + * Center frequency in MHz for first segment + */ + public int frequencyFirstSegment; + /** + * Center frequency in MHz for second segment + */ + public int frequencySecondSegment; + /** + * Channel Width as {@link WifiChannelBandwidth} + */ + public @WifiChannelBandwidth int channelWidth; + /** * Cumulative milliseconds radio is awake on this channel */ public int radioOnTimeMs; @@ -454,6 +487,10 @@ public class WifiLinkLayerStats { * Channel stats list */ public final SparseArray<ChannelStats> channelStatsMap = new SparseArray<>(); + /** + * Time for which the radio is in active tranmission per tx level + */ + public int[] tx_time_in_ms_per_level; } /** @@ -461,6 +498,8 @@ public class WifiLinkLayerStats { */ public RadioStat[] radioStats; + public @WifiManager.MloMode int wifiMloMode; + @Override public String toString() { StringBuilder sbuf = new StringBuilder(); diff --git a/service/java/com/android/server/wifi/WifiLockManager.java b/service/java/com/android/server/wifi/WifiLockManager.java index 8ba475923b..80d4ee379b 100644 --- a/service/java/com/android/server/wifi/WifiLockManager.java +++ b/service/java/com/android/server/wifi/WifiLockManager.java @@ -43,6 +43,7 @@ import com.android.wifi.resources.R; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Executor; @@ -849,13 +850,13 @@ public class WifiLockManager { return mLatencyModeSupport; } - long supportedFeatures = + BitSet supportedFeatures = mActiveModeWarden.getPrimaryClientModeManager().getSupportedFeatures(); - if (supportedFeatures == 0L) { + if (supportedFeatures.isEmpty()) { return LOW_LATENCY_SUPPORT_UNDEFINED; } - if ((supportedFeatures & WifiManager.WIFI_FEATURE_LOW_LATENCY) != 0) { + if (supportedFeatures.get(WifiManager.WIFI_FEATURE_LOW_LATENCY)) { mLatencyModeSupport = LOW_LATENCY_SUPPORTED; } else { mLatencyModeSupport = LOW_LATENCY_NOT_SUPPORTED; @@ -966,6 +967,7 @@ public class WifiLockManager { } } mWifiLowLatencyLockListeners.finishBroadcast(); + mWifiMetrics.setLowLatencyState(mIsLowLatencyActivated); } private void notifyLowLatencyOwnershipChanged() { diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 93cb2ab8d8..132790f6aa 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -21,6 +21,29 @@ import static android.net.wifi.WifiConfiguration.MeteredOverride; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONFIG_SAVED; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_SIM_INSERTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_SCORING_DISABLED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_OFF; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_UNAVAILABLE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_OTHERS; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FIRMWARE_ALERT; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_IP_REACHABILITY_LOST; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_CONNECTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING; + import static java.lang.StrictMath.toIntExact; @@ -32,6 +55,8 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.net.ConnectivityManager; +import android.net.Network; import android.net.NetworkCapabilities; import android.net.wifi.EAPConstants; import android.net.wifi.IOnWifiUsabilityStatsListener; @@ -79,6 +104,7 @@ import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceReasonCode; import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceStatusCode; +import com.android.server.wifi.WifiNative.ConnectionCapabilities; import com.android.server.wifi.aware.WifiAwareMetrics; import com.android.server.wifi.hotspot2.ANQPNetworkKey; import com.android.server.wifi.hotspot2.NetworkDetail; @@ -101,15 +127,19 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts; import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount; import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount; +import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason; import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions; +import com.android.server.wifi.proto.nano.WifiMetricsProto.PacketStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount; import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats.ProvisionFailureCount; +import com.android.server.wifi.proto.nano.WifiMetricsProto.PeerInfo; import com.android.server.wifi.proto.nano.WifiMetricsProto.PnoScanMetrics; import com.android.server.wifi.proto.nano.WifiMetricsProto.RadioStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.RateStats; +import com.android.server.wifi.proto.nano.WifiMetricsProto.ScanResultWithSameFreq; import com.android.server.wifi.proto.nano.WifiMetricsProto.SoftApConnectedClientsEvent; import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent; import com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.ConfigInfo; @@ -126,8 +156,8 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestion import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToWifiSwitchStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; -import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; +import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; // This contains a time series of WifiUsabilityStatsEntry along with some metadata, such as the label of the time series or trigger type. +import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; // This contains all the stats for a single point in time. import com.android.server.wifi.rtt.RttMetrics; import com.android.server.wifi.scanner.KnownBandsChannelHelper; import com.android.server.wifi.util.InformationElementUtil; @@ -138,6 +168,7 @@ import com.android.server.wifi.util.IntHistogram; import com.android.server.wifi.util.MetricsUtils; import com.android.server.wifi.util.ObjectCounter; import com.android.server.wifi.util.StringUtil; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import org.json.JSONArray; @@ -212,12 +243,15 @@ public class WifiMetrics { // Minimum time wait before generating next WifiIsUnusableEvent from data stall public static final int MIN_DATA_STALL_WAIT_MS = 120 * 1000; // 2 minutes // Max number of WifiUsabilityStatsEntry elements to store in the ringbuffer. - public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE = 40; - // Max number of WifiUsabilityStats elements to store for each type. - public static final int MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE = 10; + public static final int MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE = 40; + // Max number of WifiUsabilityStats records to store for each type. + public static final int MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE = 10; // Max number of WifiUsabilityStats per labeled type to upload to server - public static final int MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD = 2; + public static final int MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE_TO_UPLOAD = 2; + // One WifiGood WifiUsabilityStats record will be created each time we see this many + // WifiUsabilityStatsEntry time samples. public static final int NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD = 100; + // At most, one WifiGood WifiUsabilityStats record will be created during this time period. public static final int MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS = 1000 * 3600; // 1 hour public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_ESS = 0; public static final int PASSPOINT_DEAUTH_IMMINENT_SCOPE_BSS = 1; @@ -243,6 +277,9 @@ public class WifiMetrics { // Number of WME Access Categories private static final int NUM_WME_ACCESS_CATEGORIES = 4; private static final int MBB_LINGERING_DURATION_MAX_SECONDS = 30; + public static final int MIN_DOWNSTREAM_BANDWIDTH_KBPS = 1000; + public static final int MIN_UPSTREAM_BANDWIDTH_KBPS = 1000; + public static final int INVALID_SPEED = -1; private Clock mClock; private boolean mScreenOn; @@ -267,9 +304,10 @@ public class WifiMetrics { private WifiHealthMonitor mWifiHealthMonitor; private WifiScoreCard mWifiScoreCard; private SessionData mPreviousSession; - private SessionData mCurrentSession; - private String mLastBssid; - private int mLastFrequency = -1; + @VisibleForTesting + public SessionData mCurrentSession; + private Map<String, String> mLastBssidPerIfaceMap = new ArrayMap<>(); + private Map<String, Integer> mLastFrequencyPerIfaceMap = new ArrayMap<>(); private int mSeqNumInsideFramework = 0; private int mLastWifiUsabilityScore = -1; private int mLastWifiUsabilityScoreNoReset = -1; @@ -281,6 +319,7 @@ public class WifiMetrics { private int mProbeElapsedTimeSinceLastUpdateMs = -1; private int mProbeMcsRateSinceLastUpdate = -1; private long mScoreBreachLowTimeMillis = -1; + private int mAccumulatedLabelBadCount = 0; public static final int MAX_STA_EVENTS = 768; @VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200; @@ -301,6 +340,14 @@ public class WifiMetrics { private boolean mFirstConnectionAfterBoot = true; private long mLastTotalBeaconRx = 0; private int mScorerUid = Process.WIFI_UID; + @VisibleForTesting + int mUnusableEventType = WifiIsUnusableEvent.TYPE_UNKNOWN; + private int mWifiFrameworkState = 0; + private SpeedSufficient mSpeedSufficientNetworkCapabilities = new SpeedSufficient(); + private SpeedSufficient mSpeedSufficientThroughputPredictor = new SpeedSufficient(); + private int mLastUwbState = -1; + private boolean mIsLowLatencyActivated = false; + private int mVoipMode = -1; /** * Wi-Fi usability state per interface as predicted by the network scorer. @@ -446,11 +493,19 @@ public class WifiMetrics { private int mLinkProbeStaEventCount = 0; @VisibleForTesting static final int MAX_LINK_PROBE_STA_EVENTS = MAX_STA_EVENTS / 4; - private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesList = + // Each WifiUsabilityStatsEntry contains the stats for one instant in time. This LinkedList + // is used as a ring buffer and contains the history of the most recent + // MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE WifiUsabilityStatsEntry values. + private final LinkedList<WifiUsabilityStatsEntry> mWifiUsabilityStatsEntriesRingBuffer = new LinkedList<>(); + // One WifiUsabilityStats contains a single time series of WifiUsabilityStatsEntry along with + // some metadata. These LinkedList's below contain sets of time series that are labeled as + // either 'good' or 'bad'. private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListBad = new LinkedList<>(); private final LinkedList<WifiUsabilityStats> mWifiUsabilityStatsListGood = new LinkedList<>(); - private int mWifiUsabilityStatsCounter = 0; + // Counts the number of WifiUsabilityStatsEntry's that we have seen so that we only create a + // WifiUsabilityStats every NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD time samples. + private int mWifiUsabilityStatsEntryCounter = 0; private final Random mRand = new Random(); private final RemoteCallbackList<IOnWifiUsabilityStatsListener> mOnWifiUsabilityListeners; @@ -480,6 +535,7 @@ public class WifiMetrics { private final WifiMonitor mWifiMonitor; private ActiveModeWarden mActiveModeWarden; + private WifiGlobals mWifiGlobals; private final Map<String, ActiveModeManager.ClientRole> mIfaceToRoleMap = new ArrayMap<>(); /** WifiConfigStore read duration histogram. */ @@ -488,7 +544,7 @@ public class WifiMetrics { /** WifiConfigStore write duration histogram. */ private SparseIntArray mWifiConfigStoreWriteDurationHistogram = new SparseIntArray(); - /** New API surface metrics */ + /** New API surface metrics */ private final WifiNetworkRequestApiLog mWifiNetworkRequestApiLog = new WifiNetworkRequestApiLog(); private static final int[] NETWORK_REQUEST_API_MATCH_SIZE_HISTOGRAM_BUCKETS = @@ -612,6 +668,12 @@ public class WifiMetrics { private final WifiToWifiSwitchStats mWifiToWifiSwitchStats = new WifiToWifiSwitchStats(); + private long mLastScreenOnTimeMillis = 0; + @VisibleForTesting + long mLastScreenOffTimeMillis = 0; + @VisibleForTesting + long mLastIgnoredPollTimeMillis = 0; + /** Wi-Fi link specific metrics (MLO). */ public static class LinkMetrics { private long mTotalBeaconRx = 0; @@ -660,13 +722,15 @@ public class WifiMetrics { } } - private static class SessionData { + @VisibleForTesting + public static class SessionData { private String mSsid; - private long mSessionStartTimeMillis; + @VisibleForTesting + public long mSessionStartTimeMillis; private long mSessionEndTimeMillis; private int mBand; private int mAuthType; - private ConnectionEvent mConnectionEvent; + public ConnectionEvent mConnectionEvent; private long mLastRoamCompleteMillis; SessionData(ConnectionEvent connectionEvent, String ssid, long sessionStartTimeMillis, @@ -1184,7 +1248,8 @@ public class WifiMetrics { private int mPasspointRoamingType; private int mTofuConnectionState; - private ConnectionEvent() { + @VisibleForTesting + ConnectionEvent() { mConnectionEvent = new WifiMetricsProto.ConnectionEvent(); mRouterFingerPrint = new RouterFingerPrint(); mConnectionEvent.routerFingerprint = mRouterFingerPrint.mRouterFingerPrintProto; @@ -1618,7 +1683,8 @@ public class WifiMetrics { WifiP2pMetrics wifiP2pMetrics, DppMetrics dppMetrics, WifiMonitor wifiMonitor, - WifiDeviceStateChangeManager wifiDeviceStateChangeManager) { + WifiDeviceStateChangeManager wifiDeviceStateChangeManager, + WifiGlobals wifiGlobals) { mContext = context; mFacade = facade; mClock = clock; @@ -1650,9 +1716,10 @@ public class WifiMetrics { new WifiDeviceStateChangeManager.StateChangeCallback() { @Override public void onScreenStateChanged(boolean screenOn) { - setScreenState(screenOn); + handleScreenStateChanged(screenOn); } }); + mWifiGlobals = wifiGlobals; } /** Sets internal ScoringParams member */ @@ -4927,8 +4994,8 @@ public class WifiMetrics { } pw.println("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")); - pw.println("mWifiUsabilityStatsEntriesList:"); - for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesList) { + pw.println("mWifiUsabilityStatsEntriesRingBuffer:"); + for (WifiUsabilityStatsEntry stats : mWifiUsabilityStatsEntriesRingBuffer) { printWifiUsabilityStatsEntry(pw, stats); } pw.println("mWifiUsabilityStatsList:"); @@ -5093,6 +5160,11 @@ public class WifiMetrics { line.append(",roam_scan_time_ms=" + radioStat.totalRoamScanTimeMs); line.append(",pno_scan_time_ms=" + radioStat.totalPnoScanTimeMs); line.append(",hotspot_2_scan_time_ms=" + radioStat.totalHotspot2ScanTimeMs); + if (radioStat.txTimeMsPerLevel != null && radioStat.txTimeMsPerLevel.length > 0) { + for (int i = 0; i < radioStat.txTimeMsPerLevel.length; ++i) { + line.append(",tx_time_ms_per_level=" + radioStat.txTimeMsPerLevel[i]); + } + } } } line.append(",total_radio_on_time_ms=" + entry.totalRadioOnTimeMs); @@ -5148,6 +5220,94 @@ public class WifiMetrics { line.append(",retries=" + rateStat.retries); } } + line.append(",wifi_link_count=" + entry.wifiLinkCount); + for (LinkStats linkStat : entry.linkStats) { + line.append(",Link Stats from link_id=" + linkStat.linkId); + line.append(",state=" + linkStat.state); + line.append(",radio_id=" + linkStat.radioId); + line.append(",frequency_mhz=" + linkStat.frequencyMhz); + line.append(",beacon_rx=" + linkStat.beaconRx); + line.append(",rssi_mgmt=" + linkStat.rssiMgmt); + line.append(",time_slice_duty_cycle_in_percent=" + + linkStat.timeSliceDutyCycleInPercent); + line.append(",rssi=" + linkStat.rssi); + line.append(",channel_width=" + linkStat.channelWidth); + line.append(",center_freq_first_seg=" + linkStat.centerFreqFirstSeg); + line.append(",center_freq_second_seg=" + linkStat.centerFreqSecondSeg); + line.append(",on_time_in_ms=" + linkStat.onTimeInMs); + line.append(",cca_busy_time_in_ms=" + linkStat.ccaBusyTimeInMs); + if (linkStat.contentionTimeStats != null) { + for (ContentionTimeStats contentionTimeStat : linkStat.contentionTimeStats) { + line.append(",access_category=" + contentionTimeStat.accessCategory); + line.append(",contention_time_min_micros=" + + contentionTimeStat.contentionTimeMinMicros); + line.append(",contention_time_max_micros=" + + contentionTimeStat.contentionTimeMaxMicros); + line.append(",contention_time_avg_micros=" + + contentionTimeStat.contentionTimeAvgMicros); + line.append(",contention_num_samples=" + + contentionTimeStat.contentionNumSamples); + } + } + if (linkStat.packetStats != null) { + for (PacketStats packetStats : linkStat.packetStats) { + line.append(",access_category=" + packetStats.accessCategory); + line.append(",tx_success=" + packetStats.txSuccess); + line.append(",tx_retries=" + packetStats.txRetries); + line.append(",tx_bad=" + packetStats.txBad); + line.append(",rx_success=" + packetStats.rxSuccess); + } + } + if (linkStat.peerInfo != null) { + for (PeerInfo peerInfo : linkStat.peerInfo) { + line.append(",sta_count=" + peerInfo.staCount); + line.append(",chan_util=" + peerInfo.chanUtil); + if (peerInfo.rateStats != null) { + for (RateStats rateStat : peerInfo.rateStats) { + line.append(",preamble=" + rateStat.preamble); + line.append(",nss=" + rateStat.nss); + line.append(",bw=" + rateStat.bw); + line.append(",rate_mcs_idx=" + rateStat.rateMcsIdx); + line.append(",bit_rate_in_kbps=" + rateStat.bitRateInKbps); + line.append(",tx_mpdu=" + rateStat.txMpdu); + line.append(",rx_mpdu=" + rateStat.rxMpdu); + line.append(",mpdu_lost=" + rateStat.mpduLost); + line.append(",retries=" + rateStat.retries); + } + } + } + } + if (linkStat.scanResultWithSameFreq != null) { + for (ScanResultWithSameFreq scanResultWithSameFreq + : linkStat.scanResultWithSameFreq) { + line.append(",scan_result_timestamp_micros=" + + scanResultWithSameFreq.scanResultTimestampMicros); + line.append(",rssi=" + scanResultWithSameFreq.rssi); + line.append(",frequencyMhz=" + scanResultWithSameFreq.frequencyMhz); + } + } + line.append(",tx_linkspeed=" + linkStat.txLinkspeed); + line.append(",rx_linkspeed=" + linkStat.rxLinkspeed); + } + line.append(",mlo_mode=" + entry.mloMode); + line.append(",tx_transmitted_bytes=" + entry.txTransmittedBytes); + line.append(",rx_transmitted_bytes=" + entry.rxTransmittedBytes); + line.append(",label_bad_event_count=" + entry.labelBadEventCount); + line.append(",wifi_framework_state=" + entry.wifiFrameworkState); + line.append(",is_network_capabilities_downstream_sufficient=" + + entry.isNetworkCapabilitiesDownstreamSufficient); + line.append(",is_network_capabilities_upstream_sufficient=" + + entry.isNetworkCapabilitiesUpstreamSufficient); + line.append(",is_throughput_predictor_downstream_sufficient=" + + entry.isThroughputPredictorDownstreamSufficient); + line.append(",is_throughput_predictor_upstream_sufficient=" + + entry.isThroughputPredictorUpstreamSufficient); + line.append(",is_bluetooth_connected=" + entry.isBluetoothConnected); + line.append(",uwb_adapter_state=" + entry.uwbAdapterState); + line.append(",is_low_latency_activated=" + entry.isLowLatencyActivated); + line.append(",max_supported_tx_linkspeed=" + entry.maxSupportedTxLinkspeed); + line.append(",max_supported_rx_linkspeed=" + entry.maxSupportedRxLinkspeed); + line.append(",voip_mode=" + entry.voipMode); pw.println(line.toString()); } @@ -5624,7 +5784,7 @@ public class WifiMetrics { final int numUsabilityStats = Math.min( Math.min(mWifiUsabilityStatsListBad.size(), mWifiUsabilityStatsListGood.size()), - MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD); + MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE_TO_UPLOAD); LinkedList<WifiUsabilityStats> usabilityStatsGoodCopy = new LinkedList<>(mWifiUsabilityStatsListGood); LinkedList<WifiUsabilityStats> usabilityStatsBadCopy = @@ -5973,13 +6133,13 @@ public class WifiMetrics { mInstalledPasspointProfileTypeForR2.clear(); mWifiUsabilityStatsListGood.clear(); mWifiUsabilityStatsListBad.clear(); - mWifiUsabilityStatsEntriesList.clear(); + mWifiUsabilityStatsEntriesRingBuffer.clear(); mMobilityStatePnoStatsMap.clear(); mWifiP2pMetrics.clear(); mDppMetrics.clear(); - mWifiUsabilityStatsCounter = 0; - mLastBssid = null; - mLastFrequency = -1; + mWifiUsabilityStatsEntryCounter = 0; + mLastBssidPerIfaceMap.clear(); + mLastFrequencyPerIfaceMap.clear(); mSeqNumInsideFramework = 0; mLastWifiUsabilityScore = -1; mLastWifiUsabilityScoreNoReset = -1; @@ -5991,6 +6151,7 @@ public class WifiMetrics { mProbeElapsedTimeSinceLastUpdateMs = -1; mProbeMcsRateSinceLastUpdate = -1; mScoreBreachLowTimeMillis = -1; + mAccumulatedLabelBadCount = 0; mMeteredNetworkStatsBuilder.clear(); mWifiConfigStoreReadDurationHistogram.clear(); mWifiConfigStoreWriteDurationHistogram.clear(); @@ -6049,11 +6210,16 @@ public class WifiMetrics { } /** - * Set screen state (On/Off) + * Handle screen state changing. */ - private void setScreenState(boolean screenOn) { + private void handleScreenStateChanged(boolean screenOn) { synchronized (mLock) { mScreenOn = screenOn; + if (screenOn) { + mLastScreenOnTimeMillis = mClock.getElapsedSinceBootMillis(); + } else { + mLastScreenOffTimeMillis = mClock.getElapsedSinceBootMillis(); + } } } @@ -6574,6 +6740,16 @@ public class WifiMetrics { return "DISCONNECT_VCN_REQUEST"; case StaEvent.DISCONNECT_UNKNOWN_NETWORK: return "DISCONNECT_UNKNOWN_NETWORK"; + case StaEvent.DISCONNECT_NETWORK_UNTRUSTED: + return "DISCONNECT_NETWORK_UNTRUSTED"; + case StaEvent.DISCONNECT_NETWORK_WIFI7_TOGGLED: + return "DISCONNECT_NETWORK_WIFI7_TOGGLED"; + case StaEvent.DISCONNECT_IP_CONFIGURATION_LOST: + return "DISCONNECT_IP_CONFIGURATION_LOST"; + case StaEvent.DISCONNECT_IP_REACHABILITY_LOST: + return "DISCONNECT_IP_REACHABILITY_LOST"; + case StaEvent.DISCONNECT_NO_CREDENTIALS: + return "DISCONNECT_NO_CREDENTIALS"; default: return "DISCONNECT_UNKNOWN=" + frameworkDisconnectReason; } @@ -6936,6 +7112,7 @@ public class WifiMetrics { WifiIsUnusableEvent event = new WifiIsUnusableEvent(); event.type = triggerType; + mUnusableEventType = triggerType; if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) { event.firmwareAlertCode = firmwareAlertCode; } @@ -6995,12 +7172,16 @@ public class WifiMetrics { } } + public boolean isWiFiScorerNewStatsCollected() { + return Flags.wifiScorerNewStatsCollection(); + } + /** * Extract data from |info| and |stats| to build a WifiUsabilityStatsEntry and then adds it * into an internal ring buffer. + * @param ifaceName * @param info * @param stats - * @param ifaceName */ public void updateWifiUsabilityStatsEntries(String ifaceName, WifiInfo info, WifiLinkLayerStats stats) { @@ -7020,9 +7201,211 @@ public class WifiMetrics { stats.rxmpdu_be = info.rxSuccess; } WifiUsabilityStatsEntry wifiUsabilityStatsEntry = - mWifiUsabilityStatsEntriesList.size() - < MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesList.remove(); + mWifiUsabilityStatsEntriesRingBuffer.size() + < MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE + ? new WifiUsabilityStatsEntry() : mWifiUsabilityStatsEntriesRingBuffer.remove(); + if (isWiFiScorerNewStatsCollected()) { + SparseArray<MloLink> mloLinks = new SparseArray<>(); + for (MloLink link: info.getAffiliatedMloLinks()) { + mloLinks.put(link.getLinkId(), link); + } + if (stats.links != null && stats.links.length > 0) { + int numLinks = stats.links.length; + wifiUsabilityStatsEntry.wifiLinkCount = numLinks; + wifiUsabilityStatsEntry.linkStats = new LinkStats[numLinks]; + for (int i = 0; i < numLinks; ++i) { + LinkStats linkStats = new LinkStats(); + WifiLinkLayerStats.LinkSpecificStats link = stats.links[i]; + linkStats.linkId = link.link_id; + linkStats.state = link.state; + linkStats.radioId = link.radio_id; + linkStats.frequencyMhz = link.frequencyMhz; + linkStats.beaconRx = link.beacon_rx; + linkStats.rssiMgmt = link.rssi_mgmt; + linkStats.timeSliceDutyCycleInPercent = link.timeSliceDutyCycleInPercent; + linkStats.rssi = (mloLinks.size() > 0) ? mloLinks.get(link.link_id, + new MloLink()).getRssi() : info.getRssi(); + linkStats.txLinkspeed = (mloLinks.size() > 0) ? mloLinks.get(link.link_id, + new MloLink()).getTxLinkSpeedMbps() : info.getTxLinkSpeedMbps(); + linkStats.rxLinkspeed = (mloLinks.size() > 0) ? mloLinks.get(link.link_id, + new MloLink()).getRxLinkSpeedMbps() : info.getRxLinkSpeedMbps(); + WifiLinkLayerStats.ChannelStats channlStatsEntryOnFreq = + stats.channelStatsMap.get(link.frequencyMhz); + if (channlStatsEntryOnFreq != null) { + linkStats.channelWidth = channlStatsEntryOnFreq.channelWidth; + linkStats.centerFreqFirstSeg = + channlStatsEntryOnFreq.frequencyFirstSegment; + linkStats.centerFreqSecondSeg = + channlStatsEntryOnFreq.frequencySecondSegment; + linkStats.onTimeInMs = channlStatsEntryOnFreq.radioOnTimeMs; + linkStats.ccaBusyTimeInMs = channlStatsEntryOnFreq.ccaBusyTimeMs; + } + linkStats.contentionTimeStats = + new ContentionTimeStats[NUM_WME_ACCESS_CATEGORIES]; + linkStats.packetStats = new PacketStats[NUM_WME_ACCESS_CATEGORIES]; + for (int ac = 0; ac < NUM_WME_ACCESS_CATEGORIES; ac++) { + ContentionTimeStats contentionTimeStats = new ContentionTimeStats(); + PacketStats packetStats = new PacketStats(); + switch (ac) { + case ContentionTimeStats.WME_ACCESS_CATEGORY_BE: + contentionTimeStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_BE; + contentionTimeStats.contentionTimeMinMicros = + stats.contentionTimeMinBeInUsec; + contentionTimeStats.contentionTimeMaxMicros = + stats.contentionTimeMaxBeInUsec; + contentionTimeStats.contentionTimeAvgMicros = + stats.contentionTimeAvgBeInUsec; + contentionTimeStats.contentionNumSamples = + stats.contentionNumSamplesBe; + packetStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_BE; + packetStats.txSuccess = link.txmpdu_be; + packetStats.txRetries = link.retries_be; + packetStats.txBad = link.lostmpdu_be; + packetStats.rxSuccess = link.rxmpdu_be; + break; + case ContentionTimeStats.WME_ACCESS_CATEGORY_BK: + contentionTimeStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_BK; + contentionTimeStats.contentionTimeMinMicros = + stats.contentionTimeMinBkInUsec; + contentionTimeStats.contentionTimeMaxMicros = + stats.contentionTimeMaxBkInUsec; + contentionTimeStats.contentionTimeAvgMicros = + stats.contentionTimeAvgBkInUsec; + contentionTimeStats.contentionNumSamples = + stats.contentionNumSamplesBk; + packetStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_BK; + packetStats.txSuccess = link.txmpdu_bk; + packetStats.txRetries = link.retries_bk; + packetStats.txBad = link.lostmpdu_bk; + packetStats.rxSuccess = link.rxmpdu_bk; + break; + case ContentionTimeStats.WME_ACCESS_CATEGORY_VI: + contentionTimeStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_VI; + contentionTimeStats.contentionTimeMinMicros = + stats.contentionTimeMinViInUsec; + contentionTimeStats.contentionTimeMaxMicros = + stats.contentionTimeMaxViInUsec; + contentionTimeStats.contentionTimeAvgMicros = + stats.contentionTimeAvgViInUsec; + contentionTimeStats.contentionNumSamples = + stats.contentionNumSamplesVi; + packetStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_VI; + packetStats.txSuccess = link.txmpdu_vi; + packetStats.txRetries = link.retries_vi; + packetStats.txBad = link.lostmpdu_vi; + packetStats.rxSuccess = link.rxmpdu_vi; + break; + case ContentionTimeStats.WME_ACCESS_CATEGORY_VO: + contentionTimeStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_VO; + contentionTimeStats.contentionTimeMinMicros = + stats.contentionTimeMinVoInUsec; + contentionTimeStats.contentionTimeMaxMicros = + stats.contentionTimeMaxVoInUsec; + contentionTimeStats.contentionTimeAvgMicros = + stats.contentionTimeAvgVoInUsec; + contentionTimeStats.contentionNumSamples = + stats.contentionNumSamplesVo; + packetStats.accessCategory = + ContentionTimeStats.WME_ACCESS_CATEGORY_VO; + packetStats.txSuccess = link.txmpdu_vo; + packetStats.txRetries = link.retries_vo; + packetStats.txBad = link.lostmpdu_vo; + packetStats.rxSuccess = link.rxmpdu_vo; + break; + default: + Log.e(TAG, "Unknown WME Access Category: " + ac); + } + linkStats.contentionTimeStats[ac] = contentionTimeStats; + linkStats.packetStats[ac] = packetStats; + } + if (link.peerInfo != null && link.peerInfo.length > 0) { + int numPeers = link.peerInfo.length; + linkStats.peerInfo = new PeerInfo[numPeers]; + for (int peerIndex = 0; peerIndex < numPeers; ++peerIndex) { + PeerInfo peerInfo = new PeerInfo(); + WifiLinkLayerStats.PeerInfo curPeer = link.peerInfo[peerIndex]; + peerInfo.staCount = curPeer.staCount; + peerInfo.chanUtil = curPeer.chanUtil; + if (curPeer.rateStats != null && curPeer.rateStats.length > 0) { + int numRates = curPeer.rateStats.length; + peerInfo.rateStats = new RateStats[numRates]; + for (int rateIndex = 0; rateIndex < numRates; rateIndex++) { + RateStats rateStats = new RateStats(); + WifiLinkLayerStats.RateStat curRate = + curPeer.rateStats[rateIndex]; + rateStats.preamble = curRate.preamble; + rateStats.nss = curRate.nss; + rateStats.bw = curRate.bw; + rateStats.rateMcsIdx = curRate.rateMcsIdx; + rateStats.bitRateInKbps = curRate.bitRateInKbps; + rateStats.txMpdu = curRate.txMpdu; + rateStats.rxMpdu = curRate.rxMpdu; + rateStats.mpduLost = curRate.mpduLost; + rateStats.retries = curRate.retries; + peerInfo.rateStats[rateIndex] = rateStats; + } + } + linkStats.peerInfo[peerIndex] = peerInfo; + } + } + List<ScanResultWithSameFreq> scanResultsWithSameFreq = new ArrayList<>(); + if (link.scan_results_same_freq != null + && link.scan_results_same_freq.size() > 0) { + for (int scanResultsIndex = 0; scanResultsIndex + < link.scan_results_same_freq.size(); ++scanResultsIndex) { + WifiLinkLayerStats.ScanResultWithSameFreq linkLayerScanResult = + link.scan_results_same_freq.get(scanResultsIndex); + if (linkLayerScanResult != null) { + String wifiLinkBssid = (mloLinks.size() > 0) + ? mloLinks.get(link.link_id, new MloLink()) + .getApMacAddress().toString() : info.getBSSID(); + if (!linkLayerScanResult.bssid.equals(wifiLinkBssid)) { + ScanResultWithSameFreq scanResultWithSameFreq = + new ScanResultWithSameFreq(); + scanResultWithSameFreq.scanResultTimestampMicros = + linkLayerScanResult.scan_result_timestamp_micros; + scanResultWithSameFreq.rssi = linkLayerScanResult.rssi; + scanResultWithSameFreq.frequencyMhz = + linkLayerScanResult.frequencyMhz; + scanResultsWithSameFreq.add(scanResultWithSameFreq); + } + } + } + } + linkStats.scanResultWithSameFreq = + scanResultsWithSameFreq.toArray(new ScanResultWithSameFreq[0]); + wifiUsabilityStatsEntry.linkStats[i] = linkStats; + } + } + wifiUsabilityStatsEntry.mloMode = stats.wifiMloMode; + wifiUsabilityStatsEntry.labelBadEventCount = mAccumulatedLabelBadCount; + wifiUsabilityStatsEntry.wifiFrameworkState = mWifiFrameworkState; + wifiUsabilityStatsEntry.isNetworkCapabilitiesDownstreamSufficient = + mSpeedSufficientNetworkCapabilities.Downstream; + wifiUsabilityStatsEntry.isNetworkCapabilitiesUpstreamSufficient = + mSpeedSufficientNetworkCapabilities.Upstream; + wifiUsabilityStatsEntry.isThroughputPredictorDownstreamSufficient = + mSpeedSufficientThroughputPredictor.Downstream; + wifiUsabilityStatsEntry.isThroughputPredictorUpstreamSufficient = + mSpeedSufficientThroughputPredictor.Upstream; + wifiUsabilityStatsEntry.isBluetoothConnected = + mWifiGlobals.isBluetoothConnected(); + wifiUsabilityStatsEntry.uwbAdapterState = getLastUwbState(); + wifiUsabilityStatsEntry.isLowLatencyActivated = getLowLatencyState(); + wifiUsabilityStatsEntry.maxSupportedTxLinkspeed = + info.getMaxSupportedTxLinkSpeedMbps(); + wifiUsabilityStatsEntry.maxSupportedRxLinkspeed = + info.getMaxSupportedRxLinkSpeedMbps(); + wifiUsabilityStatsEntry.voipMode = getVoipMode(); + } + wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs; wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; @@ -7050,6 +7433,19 @@ public class WifiMetrics { radioStats.totalRoamScanTimeMs = radio.on_time_roam_scan; radioStats.totalPnoScanTimeMs = radio.on_time_pno_scan; radioStats.totalHotspot2ScanTimeMs = radio.on_time_hs20_scan; + if (isWiFiScorerNewStatsCollected()) { + if (radio.tx_time_in_ms_per_level != null + && radio.tx_time_in_ms_per_level.length > 0) { + int txTimePerLevelLength = radio.tx_time_in_ms_per_level.length; + radioStats.txTimeMsPerLevel = new int[txTimePerLevelLength]; + for (int txTimePerLevelIndex = 0; + txTimePerLevelIndex < txTimePerLevelLength; + ++txTimePerLevelIndex) { + radioStats.txTimeMsPerLevel[txTimePerLevelIndex] = + radio.tx_time_in_ms_per_level[txTimePerLevelIndex]; + } + } + } wifiUsabilityStatsEntry.radioStats[i] = radioStats; } } @@ -7074,11 +7470,12 @@ public class WifiMetrics { mLastTotalBeaconRx = stats.beacon_rx; wifiUsabilityStatsEntry.timeSliceDutyCycleInPercent = stats.timeSliceDutyCycleInPercent; - boolean isSameBssidAndFreq = mLastBssid == null || mLastFrequency == -1 - || (mLastBssid.equals(info.getBSSID()) - && mLastFrequency == info.getFrequency()); - mLastBssid = info.getBSSID(); - mLastFrequency = info.getFrequency(); + String lastBssid = mLastBssidPerIfaceMap.get(ifaceName); + int lastFrequency = mLastFrequencyPerIfaceMap.getOrDefault(ifaceName, -1); + boolean isSameBssidAndFreq = lastBssid == null || lastFrequency == -1 + || (lastBssid.equals(info.getBSSID()) && lastFrequency == info.getFrequency()); + mLastBssidPerIfaceMap.put(ifaceName, info.getBSSID()); + mLastFrequencyPerIfaceMap.put(ifaceName, info.getFrequency()); wifiUsabilityStatsEntry.wifiScore = mLastScoreNoReset; wifiUsabilityStatsEntry.wifiUsabilityScore = mLastWifiUsabilityScoreNoReset; wifiUsabilityStatsEntry.seqNumToFramework = mSeqNumToFramework; @@ -7168,13 +7565,19 @@ public class WifiMetrics { } if (mWifiChannelUtilization != null) { wifiUsabilityStatsEntry.channelUtilizationRatio = - mWifiChannelUtilization.getUtilizationRatio(mLastFrequency); + mWifiChannelUtilization.getUtilizationRatio(lastFrequency); } if (mWifiDataStall != null) { wifiUsabilityStatsEntry.isThroughputSufficient = mWifiDataStall.isThroughputSufficient(); wifiUsabilityStatsEntry.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable(); + if (isWiFiScorerNewStatsCollected()) { + wifiUsabilityStatsEntry.txTransmittedBytes = + mWifiDataStall.getTxTransmittedBytes(); + wifiUsabilityStatsEntry.rxTransmittedBytes = + mWifiDataStall.getRxTransmittedBytes(); + } } if (mWifiSettingsStore != null) { wifiUsabilityStatsEntry.isWifiScoringEnabled = @@ -7205,9 +7608,9 @@ public class WifiMetrics { } } - mWifiUsabilityStatsEntriesList.add(wifiUsabilityStatsEntry); - mWifiUsabilityStatsCounter++; - if (mWifiUsabilityStatsCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) { + mWifiUsabilityStatsEntriesRingBuffer.add(wifiUsabilityStatsEntry); + mWifiUsabilityStatsEntryCounter++; + if (mWifiUsabilityStatsEntryCounter >= NUM_WIFI_USABILITY_STATS_ENTRIES_PER_WIFI_GOOD) { addToWifiUsabilityStatsList(ifaceName, WifiUsabilityStats.LABEL_GOOD, WifiUsabilityStats.TYPE_UNKNOWN, -1); } @@ -7313,6 +7716,60 @@ public class WifiMetrics { return contentionTimeStatsArray; } + private android.net.wifi.WifiUsabilityStatsEntry.PacketStats[] + convertPacketStats(WifiLinkLayerStats.LinkSpecificStats stats) { + android.net.wifi.WifiUsabilityStatsEntry.PacketStats[] packetStatsArray = + new android.net.wifi.WifiUsabilityStatsEntry.PacketStats[ + android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES]; + for (int ac = 0; ac < android.net.wifi.WifiUsabilityStatsEntry.NUM_WME_ACCESS_CATEGORIES; + ac++) { + android.net.wifi.WifiUsabilityStatsEntry.PacketStats packetStats = null; + switch (ac) { + case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BE: + packetStats = + new android.net.wifi.WifiUsabilityStatsEntry.PacketStats( + stats.txmpdu_be, + stats.retries_be, + stats.lostmpdu_be, + stats.rxmpdu_be + ); + break; + case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_BK: + packetStats = + new android.net.wifi.WifiUsabilityStatsEntry.PacketStats( + stats.txmpdu_bk, + stats.retries_bk, + stats.lostmpdu_bk, + stats.rxmpdu_bk + ); + break; + case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VO: + packetStats = + new android.net.wifi.WifiUsabilityStatsEntry.PacketStats( + stats.txmpdu_vo, + stats.retries_vo, + stats.lostmpdu_vo, + stats.rxmpdu_vo + ); + break; + case android.net.wifi.WifiUsabilityStatsEntry.WME_ACCESS_CATEGORY_VI: + packetStats = + new android.net.wifi.WifiUsabilityStatsEntry.PacketStats( + stats.txmpdu_vi, + stats.retries_vi, + stats.lostmpdu_vi, + stats.rxmpdu_vi + ); + break; + default: + Log.d(TAG, "Unknown WME Access Category: " + ac); + packetStats = null; + } + packetStatsArray[ac] = packetStats; + } + return packetStatsArray; + } + private android.net.wifi.WifiUsabilityStatsEntry.RateStats[] convertRateStats( WifiLinkLayerStats.LinkSpecificStats stats) { android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats = null; @@ -7336,6 +7793,43 @@ public class WifiMetrics { return rateStats; } + private android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[] convertPeerInfo( + WifiLinkLayerStats.LinkSpecificStats stats) { + android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[] peerInfos = null; + if (stats.peerInfo != null && stats.peerInfo.length > 0) { + int numPeers = stats.peerInfo.length; + peerInfos = new android.net.wifi.WifiUsabilityStatsEntry.PeerInfo[numPeers]; + for (int i = 0; i < numPeers; i++) { + WifiLinkLayerStats.PeerInfo curPeer = stats.peerInfo[i]; + android.net.wifi.WifiUsabilityStatsEntry.RateStats[] rateStats = null; + if (curPeer.rateStats != null && curPeer.rateStats.length > 0) { + int numRates = curPeer.rateStats.length; + rateStats = new android.net.wifi.WifiUsabilityStatsEntry.RateStats[numRates]; + for (int rateIndex = 0; rateIndex < numRates; ++rateIndex) { + WifiLinkLayerStats.RateStat curRate = curPeer.rateStats[rateIndex]; + rateStats[rateIndex] = + new android.net.wifi.WifiUsabilityStatsEntry.RateStats( + convertPreambleTypeEnumToUsabilityStatsType( + curRate.preamble), + convertSpatialStreamEnumToUsabilityStatsType(curRate.nss), + convertBandwidthEnumToUsabilityStatsType(curRate.bw), + curRate.rateMcsIdx, + curRate.bitRateInKbps, + curRate.txMpdu, + curRate.rxMpdu, + curRate.mpduLost, + curRate.retries); + } + } + android.net.wifi.WifiUsabilityStatsEntry.PeerInfo peerInfo = + new android.net.wifi.WifiUsabilityStatsEntry.PeerInfo( + curPeer.staCount, curPeer.chanUtil, rateStats); + peerInfos[i] = peerInfo; + } + } + return peerInfos; + } + private SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> convertLinkStats( WifiLinkLayerStats stats, WifiInfo info) { SparseArray<android.net.wifi.WifiUsabilityStatsEntry.LinkStats> linkStats = @@ -7356,6 +7850,30 @@ public class WifiMetrics { mLastLinkMetrics.put(inStat.link_id, linkMetrics); WifiLinkLayerStats.ChannelStats channelStatsMap = stats.channelStatsMap.get( inStat.frequencyMhz); + List<android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq> + scanResultsWithSameFreq = new ArrayList<>(); + + if (inStat.scan_results_same_freq != null + && inStat.scan_results_same_freq.size() > 0) { + for (int scanResultsIndex = 0; scanResultsIndex + < inStat.scan_results_same_freq.size(); ++scanResultsIndex) { + WifiLinkLayerStats.ScanResultWithSameFreq linkLayerScanResult = + inStat.scan_results_same_freq.get(scanResultsIndex); + if (linkLayerScanResult != null) { + if (!linkLayerScanResult.bssid.equals(info.getBSSID())) { + android.net.wifi.WifiUsabilityStatsEntry.ScanResultWithSameFreq + scanResultWithSameFreq = + new android.net.wifi.WifiUsabilityStatsEntry + .ScanResultWithSameFreq( + linkLayerScanResult.scan_result_timestamp_micros, + linkLayerScanResult.rssi, + linkLayerScanResult.frequencyMhz + ); + scanResultsWithSameFreq.add(scanResultWithSameFreq); + } + } + } + } // Note: RSSI, Tx & Rx link speed are derived from signal poll stats which is updated in // Mlolink or WifiInfo (non-MLO case). android.net.wifi.WifiUsabilityStatsEntry.LinkStats outStat = @@ -7363,6 +7881,10 @@ public class WifiMetrics { inStat.state, inStat.radio_id, (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id, new MloLink()).getRssi() : info.getRssi(), + inStat.frequencyMhz, inStat.rssi_mgmt, + (channelStatsMap != null) ? channelStatsMap.channelWidth : 0, + (channelStatsMap != null) ? channelStatsMap.frequencyFirstSegment : 0, + (channelStatsMap != null) ? channelStatsMap.frequencySecondSegment : 0, (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id, new MloLink()).getTxLinkSpeedMbps() : info.getTxLinkSpeedMbps(), (mloLinks.size() > 0) ? mloLinks.get(inStat.link_id, @@ -7378,8 +7900,11 @@ public class WifiMetrics { inStat.beacon_rx, inStat.timeSliceDutyCycleInPercent, (channelStatsMap != null) ? channelStatsMap.ccaBusyTimeMs : 0 , (channelStatsMap != null) ? channelStatsMap.radioOnTimeMs : 0, - convertContentionTimeStats(inStat), - convertRateStats(inStat)); + convertContentionTimeStats(inStat), convertRateStats(inStat), + convertPacketStats(inStat), convertPeerInfo(inStat), + scanResultsWithSameFreq.toArray( + new android.net.wifi.WifiUsabilityStatsEntry + .ScanResultWithSameFreq[0])); linkStats.put(inStat.link_id, outStat); } @@ -7427,7 +7952,14 @@ public class WifiMetrics { s.rxLinkSpeedMbps, s.timeSliceDutyCycleInPercent, contentionTimeStats, rateStats, radioStats, s.channelUtilizationRatio, s.isThroughputSufficient, s.isWifiScoringEnabled, s.isCellularDataAvailable, 0, 0, 0, false, - convertLinkStats(stats, info) + convertLinkStats(stats, info), s.wifiLinkCount, s.mloMode, + s.txTransmittedBytes, s.rxTransmittedBytes, s.labelBadEventCount, + s.wifiFrameworkState, s.isNetworkCapabilitiesDownstreamSufficient, + s.isNetworkCapabilitiesUpstreamSufficient, + s.isThroughputPredictorDownstreamSufficient, + s.isThroughputPredictorUpstreamSufficient, s.isBluetoothConnected, + s.uwbAdapterState, s.isLowLatencyActivated, s.maxSupportedTxLinkspeed, + s.maxSupportedRxLinkspeed, s.voipMode ); } @@ -7559,6 +8091,14 @@ public class WifiMetrics { return; } for (int i = 0; i < stats.length; i++) { + int[] txTimeMsPerLevel = null; + if (stats[i].txTimeMsPerLevel != null && stats[i].txTimeMsPerLevel.length > 0) { + int txTimeMsPerLevelLength = stats[i].txTimeMsPerLevel.length; + txTimeMsPerLevel = new int[txTimeMsPerLevelLength]; + for (int j = 0; j < txTimeMsPerLevelLength; ++j) { + txTimeMsPerLevel[j] = stats[i].txTimeMsPerLevel[j]; + } + } statsParcelable[i] = new android.net.wifi.WifiUsabilityStatsEntry.RadioStats( stats[i].radioId, @@ -7570,7 +8110,8 @@ public class WifiMetrics { stats[i].totalBackgroundScanTimeMs, stats[i].totalRoamScanTimeMs, stats[i].totalPnoScanTimeMs, - stats[i].totalHotspot2ScanTimeMs); + stats[i].totalHotspot2ScanTimeMs, + txTimeMsPerLevel); } } @@ -7616,6 +8157,23 @@ public class WifiMetrics { out.staCount = s.staCount; out.channelUtilization = s.channelUtilization; out.radioStats = s.radioStats; + out.wifiLinkCount = s.wifiLinkCount; + out.linkStats = s.linkStats; + out.mloMode = s.mloMode; + out.txTransmittedBytes = s.txTransmittedBytes; + out.rxTransmittedBytes = s.rxTransmittedBytes; + out.labelBadEventCount = s.labelBadEventCount; + out.wifiFrameworkState = s.wifiFrameworkState; + out.isNetworkCapabilitiesDownstreamSufficient = s.isNetworkCapabilitiesDownstreamSufficient; + out.isNetworkCapabilitiesUpstreamSufficient = s.isNetworkCapabilitiesUpstreamSufficient; + out.isThroughputPredictorDownstreamSufficient = s.isThroughputPredictorDownstreamSufficient; + out.isThroughputPredictorUpstreamSufficient = s.isThroughputPredictorUpstreamSufficient; + out.isBluetoothConnected = s.isBluetoothConnected; + out.uwbAdapterState = s.uwbAdapterState; + out.isLowLatencyActivated = s.isLowLatencyActivated; + out.maxSupportedTxLinkspeed = s.maxSupportedTxLinkspeed; + out.maxSupportedRxLinkspeed = s.maxSupportedRxLinkspeed; + out.voipMode = s.voipMode; return out; } @@ -7627,16 +8185,18 @@ public class WifiMetrics { wifiUsabilityStats.firmwareAlertCode = firmwareAlertCode; wifiUsabilityStats.timeStampMs = mClock.getElapsedSinceBootMillis(); wifiUsabilityStats.stats = - new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesList.size()]; - for (int i = 0; i < mWifiUsabilityStatsEntriesList.size(); i++) { + new WifiUsabilityStatsEntry[mWifiUsabilityStatsEntriesRingBuffer.size()]; + for (int i = 0; i < mWifiUsabilityStatsEntriesRingBuffer.size(); i++) { wifiUsabilityStats.stats[i] = - createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesList.get(i)); + createNewWifiUsabilityStatsEntry(mWifiUsabilityStatsEntriesRingBuffer.get(i)); } return wifiUsabilityStats; } /** - * Label the current snapshot of WifiUsabilityStatsEntrys and save the labeled data in memory. + * Label the current snapshot of WifiUsabilityStatsEntriesRingBuffer and save the labeled data + * inside a WifiUsabilityStats ptoto. + * * @param label WifiUsabilityStats.LABEL_GOOD or WifiUsabilityStats.LABEL_BAD * @param triggerType what event triggers WifiUsabilityStats * @param firmwareAlertCode the firmware alert code when the stats was triggered by a @@ -7648,7 +8208,7 @@ public class WifiMetrics { if (!isPrimary(ifaceName)) { return; } - if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) { + if (mWifiUsabilityStatsEntriesRingBuffer.isEmpty() || !mScreenOn) { return; } if (label == WifiUsabilityStats.LABEL_GOOD) { @@ -7658,9 +8218,9 @@ public class WifiMetrics { || mWifiUsabilityStatsListGood.getLast().stats[mWifiUsabilityStatsListGood .getLast().stats.length - 1].timeStampMs + MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS - < mWifiUsabilityStatsEntriesList.getLast().timeStampMs) { + < mWifiUsabilityStatsEntriesRingBuffer.getLast().timeStampMs) { while (mWifiUsabilityStatsListGood.size() - >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) { + >= MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE) { mWifiUsabilityStatsListGood.remove( mRand.nextInt(mWifiUsabilityStatsListGood.size())); } @@ -7676,9 +8236,9 @@ public class WifiMetrics { || (mWifiUsabilityStatsListBad.getLast().stats[mWifiUsabilityStatsListBad .getLast().stats.length - 1].timeStampMs + MIN_DATA_STALL_WAIT_MS - < mWifiUsabilityStatsEntriesList.getLast().timeStampMs)) { + < mWifiUsabilityStatsEntriesRingBuffer.getLast().timeStampMs)) { while (mWifiUsabilityStatsListBad.size() - >= MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE) { + >= MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE) { mWifiUsabilityStatsListBad.remove( mRand.nextInt(mWifiUsabilityStatsListBad.size())); } @@ -7686,9 +8246,10 @@ public class WifiMetrics { createWifiUsabilityStatsWithLabel(label, triggerType, firmwareAlertCode)); } + mAccumulatedLabelBadCount++; } - mWifiUsabilityStatsCounter = 0; - mWifiUsabilityStatsEntriesList.clear(); + mWifiUsabilityStatsEntryCounter = 0; + mWifiUsabilityStatsEntriesRingBuffer.clear(); } } @@ -8770,6 +9331,244 @@ public class WifiMetrics { } } + @VisibleForTesting + int getDeviceStateForScorer(boolean hasActiveModem, boolean hasActiveSubInfo, + boolean isMobileDataEnabled, boolean isCellularDataAvailable, + boolean adaptiveConnectivityEnabled) { + if (!hasActiveModem) { + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM; + } + if (!hasActiveSubInfo) { + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_SIM_INSERTED; + } + if (!adaptiveConnectivityEnabled) { + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_SCORING_DISABLED; + } + if (!isMobileDataEnabled) { + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_OFF; + } + if (!isCellularDataAvailable) { + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_UNAVAILABLE; + } + return SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_OTHERS; + } + + @VisibleForTesting + int convertWifiUnusableTypeForScorer(int triggerType) { + switch (triggerType) { + case WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX: + case WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX: + case WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH: + return SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL; + case WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT: + return SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FIRMWARE_ALERT; + case WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST: + return SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_IP_REACHABILITY_LOST; + default: + return SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE; + } + } + + @VisibleForTesting + int getFrameworkStateForScorer(boolean lingering) { + // The first poll after the screen turns on is termed the AWAKENING state. + if (mLastIgnoredPollTimeMillis <= mLastScreenOffTimeMillis) { + mLastIgnoredPollTimeMillis = mClock.getElapsedSinceBootMillis(); + return SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING; + } + if (lingering) { + return SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING; + } + return SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_CONNECTED; + } + + private class ConnectivityManagerCache { + ConnectivityManagerCache() { } + + private ConnectivityManager mConnectivityManager; + + /** + * Returns the cached ConnectivityManager or performs a system call to fetch it before + * returning. + * + * Note that this function can still return null if getSystemService cannot find the + * connectivity manager. + */ + public ConnectivityManager getConnectivityManager() { + if (mConnectivityManager == null) { + mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); + } + return mConnectivityManager; + } + } + private final ConnectivityManagerCache mConnectivityManagerCache = + new ConnectivityManagerCache(); + + @VisibleForTesting + public static class Speeds { + public int DownstreamKbps = INVALID_SPEED; + public int UpstreamKbps = INVALID_SPEED; + } + + /** + * Returns the NetworkCapabilites based link capacity estimates. + */ + Speeds getNetworkCapabilitiesSpeeds() { + Speeds speeds = new Speeds(); + + ConnectivityManager connectivityManager = + mConnectivityManagerCache.getConnectivityManager(); + if (connectivityManager == null) { + return speeds; + } + + Network activeNetwork = connectivityManager.getActiveNetwork(); + if (activeNetwork == null) { + return speeds; + } + + NetworkCapabilities networkCapabilities = + connectivityManager.getNetworkCapabilities(activeNetwork); + if (networkCapabilities == null) { + return speeds; + } + + // Normally, we will not get called when WiFi is not active. This deals with a corner case + // where we have switched to cellular but we end up getting called one last time. + if (!networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + return speeds; + } + + speeds.DownstreamKbps = networkCapabilities.getLinkDownstreamBandwidthKbps(); + speeds.UpstreamKbps = networkCapabilities.getLinkUpstreamBandwidthKbps(); + + return speeds; + } + + @VisibleForTesting + public static class SpeedSufficient { + // Note the default value of 0 maps to '.*UNKNOWN' for the speed sufficient enums that we + // use below. Specifically they map to 0 for: + // SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN + // SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN + // SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN + // SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + public int Downstream = 0; + public int Upstream = 0; + } + + @VisibleForTesting + SpeedSufficient calcSpeedSufficientNetworkCapabilities(Speeds speeds) { + SpeedSufficient speedSufficient = new SpeedSufficient(); + + if (speeds == null) { + return speedSufficient; + } + + if (speeds.DownstreamKbps != INVALID_SPEED) { + speedSufficient.Downstream = (speeds.DownstreamKbps < MIN_DOWNSTREAM_BANDWIDTH_KBPS) + ? SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__FALSE + : SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE; + + } + + if (speeds.UpstreamKbps != INVALID_SPEED) { + speedSufficient.Upstream = (speeds.UpstreamKbps < MIN_UPSTREAM_BANDWIDTH_KBPS) + ? SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__FALSE + : SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__TRUE; + } + + return speedSufficient; + } + + @VisibleForTesting + SpeedSufficient calcSpeedSufficientThroughputPredictor(WifiDataStall.Speeds speeds) { + SpeedSufficient speedSufficient = new SpeedSufficient(); + + if (speeds == null) { + return speedSufficient; + } + + if (speeds.DownstreamKbps != WifiDataStall.INVALID_THROUGHPUT) { + speedSufficient.Downstream = (speeds.DownstreamKbps < MIN_DOWNSTREAM_BANDWIDTH_KBPS) + ? SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__FALSE + : SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE; + + } + + if (speeds.UpstreamKbps != WifiDataStall.INVALID_THROUGHPUT) { + speedSufficient.Upstream = (speeds.UpstreamKbps < MIN_UPSTREAM_BANDWIDTH_KBPS) + ? SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__FALSE + : SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__TRUE; + } + + return speedSufficient; + } + + public void updateWiFiEvaluationAndScorerStats(boolean lingering, WifiInfo wifiInfo, + ConnectionCapabilities connectionCapabilities) { + mWifiFrameworkState = getFrameworkStateForScorer(lingering); + Speeds speedsNetworkCapabilities = getNetworkCapabilitiesSpeeds(); + mSpeedSufficientNetworkCapabilities = + calcSpeedSufficientNetworkCapabilities(speedsNetworkCapabilities); + WifiDataStall.Speeds speedsThroughputPredictor = + mWifiDataStall.getThrouhgputPredictorSpeeds(wifiInfo, connectionCapabilities); + mSpeedSufficientThroughputPredictor = + calcSpeedSufficientThroughputPredictor(speedsThroughputPredictor); + } + + /** + * Log a ScorerPredictionResultReported atom. + */ + public void logScorerPredictionResult(boolean hasActiveModem, + boolean hasActiveSubInfo, + boolean isMobileDataEnabled, + int pollingIntervalMs, + int aospScorerPrediction, + int externalScorerPrediction + ) { + boolean isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable(); + boolean isThroughputSufficient = mWifiDataStall.isThroughputSufficient(); + int deviceState = getDeviceStateForScorer( + hasActiveModem, + hasActiveSubInfo, isMobileDataEnabled, isCellularDataAvailable, + mAdaptiveConnectivityEnabled); + int scorerUnusableEvent = convertWifiUnusableTypeForScorer(mUnusableEventType); + + WifiStatsLog.write_non_chained(SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, + null, + aospScorerPrediction, + scorerUnusableEvent, + isThroughputSufficient, deviceState, pollingIntervalMs, + mWifiFrameworkState, mSpeedSufficientNetworkCapabilities.Downstream, + mSpeedSufficientNetworkCapabilities.Upstream, + mSpeedSufficientThroughputPredictor.Downstream, + mSpeedSufficientThroughputPredictor.Upstream); + if (mScorerUid != Process.WIFI_UID) { + WifiStatsLog.write_non_chained(SCORER_PREDICTION_RESULT_REPORTED, + mScorerUid, + null, // TODO(b/354737760): log the attribution tag + externalScorerPrediction, + scorerUnusableEvent, + isThroughputSufficient, deviceState, pollingIntervalMs, + mWifiFrameworkState, mSpeedSufficientNetworkCapabilities.Downstream, + mSpeedSufficientNetworkCapabilities.Upstream, + mSpeedSufficientThroughputPredictor.Downstream, + mSpeedSufficientThroughputPredictor.Upstream); + } + + // We'd better reset to TYPE_NONE if it is defined in the future. + mUnusableEventType = WifiIsUnusableEvent.TYPE_UNKNOWN; + } + + /** + * Clear the saved unusable event type. + */ + public void resetWifiUnusableEvent() { + mUnusableEventType = WifiIsUnusableEvent.TYPE_UNKNOWN; + } + /** * Get total beacon receive count */ @@ -9448,7 +10247,8 @@ public class WifiMetrics { boolean isStaApSupported, boolean isStaDbsSupported, int staFreqMhz, - @SoftApConfiguration.SecurityType int securityType) { + @SoftApConfiguration.SecurityType int securityType, + WorkSource source) { WifiStatsLog.write(WifiStatsLog.SOFT_AP_STARTED, getSoftApStartedStartResult(startResult), getSoftApStartedRole(role), @@ -9457,7 +10257,8 @@ public class WifiMetrics { isDbsSupported, getSoftApStartedStaApConcurrency(isStaApSupported, isStaDbsSupported), getSoftApStartedStaStatus(staFreqMhz), - getSoftApStartedAuthType(securityType)); + getSoftApStartedAuthType(securityType), + source.getUid(0)); if (startResult == SoftApManager.START_RESULT_SUCCESS) { WifiStatsLog.write(WifiStatsLog.SOFT_AP_STATE_CHANGED, WifiStatsLog.SOFT_AP_STATE_CHANGED__HOTSPOT_ON__STATE_ON); @@ -9649,4 +10450,28 @@ public class WifiMetrics { WifiStatsLog.write(WifiStatsLog.SOFT_AP_STATE_CHANGED, WifiStatsLog.SOFT_AP_STATE_CHANGED__HOTSPOT_ON__STATE_OFF); } + + public int getLastUwbState() { + return mLastUwbState; + } + + public void setLastUwbState(int state) { + mLastUwbState = state; + } + + public boolean getLowLatencyState() { + return mIsLowLatencyActivated; + } + + public void setLowLatencyState(boolean state) { + mIsLowLatencyActivated = state; + } + + public int getVoipMode() { + return mVoipMode; + } + + public void setVoipMode(int mode) { + mVoipMode = mode; + } } diff --git a/service/java/com/android/server/wifi/WifiMulticastLockManager.java b/service/java/com/android/server/wifi/WifiMulticastLockManager.java index 07de76a46e..fa40fd7d3b 100644 --- a/service/java/com/android/server/wifi/WifiMulticastLockManager.java +++ b/service/java/com/android/server/wifi/WifiMulticastLockManager.java @@ -17,6 +17,8 @@ package com.android.server.wifi; import android.annotation.Nullable; +import android.app.ActivityManager; +import android.content.Context; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Handler; @@ -30,7 +32,9 @@ import com.android.server.wifi.proto.WifiStatsLog; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * WifiMulticastLockManager tracks holders of multicast locks and @@ -38,10 +42,15 @@ import java.util.List; */ public class WifiMulticastLockManager { private static final String TAG = "WifiMulticastLockManager"; + private static final int IMPORTANCE_THRESHOLD = + ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; private final List<Multicaster> mMulticasters = new ArrayList<>(); + private final Map<Integer, Integer> mNumLocksPerActiveOwner = new HashMap<>(); + private final Map<Integer, Integer> mNumLocksPerInactiveOwner = new HashMap<>(); private int mMulticastEnabled = 0; private int mMulticastDisabled = 0; private final Handler mHandler; + private final Object mLock = new Object(); private boolean mVerboseLoggingEnabled = false; private final BatteryStatsManager mBatteryStats; private final ActiveModeWarden mActiveModeWarden; @@ -58,13 +67,22 @@ public class WifiMulticastLockManager { public WifiMulticastLockManager( ActiveModeWarden activeModeWarden, BatteryStatsManager batteryStats, - Looper looper) { + Looper looper, + Context context) { mBatteryStats = batteryStats; mActiveModeWarden = activeModeWarden; mHandler = new Handler(looper); mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback( new PrimaryClientModeManagerChangedCallback()); + + ActivityManager activityManager = context.getSystemService(ActivityManager.class); + activityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() { + @Override + public void onUidImportance(final int uid, final int importance) { + handleImportanceChanged(uid, importance); + } + }, IMPORTANCE_THRESHOLD); } private class Multicaster implements IBinder.DeathRecipient { @@ -72,9 +90,9 @@ public class WifiMulticastLockManager { int mUid; IBinder mBinder; - Multicaster(String tag, IBinder binder) { + Multicaster(int uid, IBinder binder, String tag) { mTag = tag; - mUid = Binder.getCallingUid(); + mUid = uid; mBinder = binder; try { mBinder.linkToDeath(this, 0); @@ -87,7 +105,7 @@ public class WifiMulticastLockManager { public void binderDied() { mHandler.post(() -> { Log.e(TAG, "Multicaster binderDied"); - synchronized (mMulticasters) { + synchronized (mLock) { int i = mMulticasters.indexOf(this); if (i != -1) { removeMulticasterLocked(i, mUid, mTag); @@ -108,16 +126,71 @@ public class WifiMulticastLockManager { return mTag; } + public IBinder getBinder() { + return mBinder; + } + public String toString() { return "Multicaster{" + mTag + " uid=" + mUid + "}"; } } + private boolean uidIsLockOwner(int uid) { + return mNumLocksPerActiveOwner.containsKey(uid) + || mNumLocksPerInactiveOwner.containsKey(uid); + } + + private void transitionUidToActive(int uid) { + if (mNumLocksPerInactiveOwner.containsKey(uid)) { + mNumLocksPerActiveOwner.put(uid, mNumLocksPerInactiveOwner.get(uid)); + mNumLocksPerInactiveOwner.remove(uid); + } + } + + private void transitionUidToInactive(int uid) { + if (mNumLocksPerActiveOwner.containsKey(uid)) { + mNumLocksPerInactiveOwner.put(uid, mNumLocksPerActiveOwner.get(uid)); + mNumLocksPerActiveOwner.remove(uid); + } + } + + private void handleImportanceChanged(int uid, int importance) { + mHandler.post(() -> { + synchronized (mLock) { + if (!uidIsLockOwner(uid)) { + return; + } + + boolean uidIsNowActive = importance < IMPORTANCE_THRESHOLD; + boolean prevIsMulticastEnabled = isMulticastEnabled(); + Log.i(TAG, "Handling importance changed for uid=" + uid + + ", isNowActive=" + uidIsNowActive + ", importance=" + importance); + if (uidIsNowActive) { + transitionUidToActive(uid); + } else { + transitionUidToInactive(uid); + } + + boolean currentIsMulticastEnabled = isMulticastEnabled(); + if (prevIsMulticastEnabled != currentIsMulticastEnabled) { + if (currentIsMulticastEnabled) { + // Filtering should be stopped if multicast is enabled + stopFilteringMulticastPackets(); + } else { + startFilteringMulticastPackets(); + } + } + } + }); + } + protected void dump(PrintWriter pw) { pw.println("mMulticastEnabled " + mMulticastEnabled); pw.println("mMulticastDisabled " + mMulticastDisabled); - pw.println("Multicast Locks held:"); - synchronized (mMulticasters) { + synchronized (mLock) { + pw.println("Active lock owners: " + mNumLocksPerActiveOwner); + pw.println("Inactive lock owners: " + mNumLocksPerInactiveOwner); + pw.println("Multicast Locks held:"); for (Multicaster l : mMulticasters) { pw.print(" "); pw.println(l); @@ -129,11 +202,10 @@ public class WifiMulticastLockManager { mVerboseLoggingEnabled = verboseEnabled; } - /** Start filtering if no multicasters exist. */ - public void initializeFiltering() { - synchronized (mMulticasters) { - // if anybody had requested filters be off, leave off - if (mMulticasters.size() == 0) { + /** Start filtering multicast packets if no locks are actively held */ + public void startFilteringMulticastPackets() { + synchronized (mLock) { + if (!isMulticastEnabled()) { mActiveModeWarden.getPrimaryClientModeManager() .getMcastLockManagerFilterController() .startFilteringMulticastPackets(); @@ -141,15 +213,29 @@ public class WifiMulticastLockManager { } } + private void stopFilteringMulticastPackets() { + mActiveModeWarden.getPrimaryClientModeManager() + .getMcastLockManagerFilterController() + .stopFilteringMulticastPackets(); + } + /** * Acquire a multicast lock. * @param binder a binder used to ensure caller is still alive * @param tag string name of the caller. */ - public void acquireLock(IBinder binder, String tag) { - synchronized (mMulticasters) { + public void acquireLock(int uid, IBinder binder, String tag) { + synchronized (mLock) { mMulticastEnabled++; - mMulticasters.add(new Multicaster(tag, binder)); + + // Assume that the application is active if it is requesting a lock + if (mNumLocksPerInactiveOwner.containsKey(uid)) { + transitionUidToActive(uid); + } + int numLocksHeldByUid = mNumLocksPerActiveOwner.getOrDefault(uid, 0); + mNumLocksPerActiveOwner.put(uid, numLocksHeldByUid + 1); + mMulticasters.add(new Multicaster(uid, binder, tag)); + // Note that we could call stopFilteringMulticastPackets only when // our new size == 1 (first call), but this function won't // be called often and by making the stopPacket call each @@ -159,7 +245,6 @@ public class WifiMulticastLockManager { .stopFilteringMulticastPackets(); } - int uid = Binder.getCallingUid(); final long ident = Binder.clearCallingIdentity(); mBatteryStats.reportWifiMulticastEnabled(new WorkSource(uid)); WifiStatsLog.write_non_chained( @@ -169,14 +254,14 @@ public class WifiMulticastLockManager { } /** Releases a multicast lock */ - public void releaseLock(String tag) { - int uid = Binder.getCallingUid(); - synchronized (mMulticasters) { + public void releaseLock(int uid, IBinder binder, String tag) { + synchronized (mLock) { mMulticastDisabled++; int size = mMulticasters.size(); for (int i = size - 1; i >= 0; i--) { Multicaster m = mMulticasters.get(i); - if ((m != null) && (m.getUid() == uid) && (m.getTag().equals(tag))) { + if ((m != null) && (m.getUid() == uid) && (m.getTag().equals(tag)) + && (m.getBinder() == binder)) { removeMulticasterLocked(i, uid, tag); break; } @@ -184,13 +269,28 @@ public class WifiMulticastLockManager { } } + private void decrementNumLocksForUid(int uid, Map<Integer, Integer> map) { + int numLocksHeldByUid = map.get(uid) - 1; + if (numLocksHeldByUid == 0) { + map.remove(uid); + } else { + map.put(uid, numLocksHeldByUid); + } + } + private void removeMulticasterLocked(int i, int uid, String tag) { Multicaster removed = mMulticasters.remove(i); - if (removed != null) { removed.unlinkDeathRecipient(); } - if (mMulticasters.size() == 0) { + + if (mNumLocksPerActiveOwner.containsKey(uid)) { + decrementNumLocksForUid(uid, mNumLocksPerActiveOwner); + } else if (mNumLocksPerInactiveOwner.containsKey(uid)) { + decrementNumLocksForUid(uid, mNumLocksPerInactiveOwner); + } + + if (!isMulticastEnabled()) { mActiveModeWarden.getPrimaryClientModeManager() .getMcastLockManagerFilterController() .startFilteringMulticastPackets(); @@ -206,8 +306,9 @@ public class WifiMulticastLockManager { /** Returns whether multicast should be allowed (filtering disabled). */ public boolean isMulticastEnabled() { - synchronized (mMulticasters) { - return mMulticasters.size() > 0; + synchronized (mLock) { + // Multicast is enabled if any active lock owners exist + return !mNumLocksPerActiveOwner.isEmpty(); } } diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 9ec97ee493..e272126595 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -21,11 +21,14 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN; -import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; +import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; +import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES; import static com.android.server.wifi.p2p.WifiP2pNative.P2P_IFACE_NAME; import static com.android.server.wifi.p2p.WifiP2pNative.P2P_INTERFACE_PROPERTY; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; +import static com.android.wifi.flags.Flags.rsnOverriding; import android.annotation.IntDef; import android.annotation.NonNull; @@ -36,6 +39,7 @@ import android.net.MacAddress; import android.net.TrafficStats; import android.net.apf.ApfCapabilities; import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.MscsParams; import android.net.wifi.OuiKeyedData; import android.net.wifi.QosPolicyParams; @@ -75,6 +79,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.SupplicantStaIfaceHal.QosPolicyStatus; +import com.android.server.wifi.WifiLinkLayerStats.ScanResultWithSameFreq; import com.android.server.wifi.hal.WifiChip; import com.android.server.wifi.hal.WifiHal; import com.android.server.wifi.hal.WifiNanIface; @@ -134,12 +139,13 @@ public class WifiNative { private NetdWrapper mNetdWrapper; private boolean mVerboseLoggingEnabled = false; private boolean mIsEnhancedOpenSupported = false; + @VisibleForTesting boolean mIsRsnOverridingSupported = false; private final List<CoexUnsafeChannel> mCachedCoexUnsafeChannels = new ArrayList<>(); private int mCachedCoexRestrictions; private CountryCodeChangeListenerInternal mCountryCodeChangeListener; private boolean mUseFakeScanDetails; private final ArrayList<ScanDetail> mFakeScanDetails = new ArrayList<>(); - private long mCachedFeatureSet; + private BitSet mCachedFeatureSet = null; private boolean mQosPolicyFeatureEnabled = false; private final Map<String, String> mWifiCondIfacesForBridgedAp = new ArrayMap<>(); private MockWifiServiceUtil mMockWifiModem = null; @@ -289,7 +295,8 @@ public class WifiNative { @Override public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) { mSoftApHalCallback.onConnectedClientsChanged(mIfaceName, - client.getMacAddress(), isConnected); + client.getMacAddress(), isConnected, + DeauthenticationReasonCode.REASON_UNKNOWN); } } @@ -354,9 +361,11 @@ public class WifiNative { * @param clientAddress Macaddress of the client. * @param isConnected Indication as to whether the client is connected (true), or * disconnected (false). + * @param disconnectReason The reason for disconnection, if applicable. This + * parameter is only meaningful when {@code isConnected} is false. */ void onConnectedClientsChanged(String apIfaceInstance, MacAddress clientAddress, - boolean isConnected); + boolean isConnected, @WifiAnnotations.SoftApDisconnectReason int disconnectReason); } /******************************************************** @@ -391,7 +400,7 @@ public class WifiNative { /** Network observer registered for this interface */ public NetworkObserverInternal networkObserver; /** Interface feature set / capabilities */ - public long featureSet; + public BitSet featureSet = new BitSet(); public int bandsSupported; public DeviceWiphyCapabilities phyCapabilities; public WifiHal.WifiInterface iface; @@ -415,6 +424,12 @@ public class WifiNative { case IFACE_TYPE_AP: typeString = "AP"; break; + case IFACE_TYPE_P2P: + typeString = "P2P"; + break; + case IFACE_TYPE_NAN: + typeString = "NAN"; + break; default: typeString = "<UNKNOWN>"; break; @@ -1311,8 +1326,12 @@ public class WifiNative { nanInterfaceDestroyedListener, handler, requestorWs); if (nanIface != null) { iface.iface = nanIface; - return iface; + iface.name = nanIface.getName(); + if (!TextUtils.isEmpty(iface.name)) { + return iface; + } } + mIfaceMgr.removeIface(iface.id); } Log.e(TAG, "Failed to allocate new Nan iface"); stopHalAndWificondIfNecessary(); @@ -1757,7 +1776,13 @@ public class WifiNative { iface.featureSet = getSupportedFeatureSetInternal(iface.name); saveCompleteFeatureSetInConfigStoreIfNecessary(iface.featureSet); updateSupportedBandForStaInternal(iface); - mIsEnhancedOpenSupported = (iface.featureSet & WIFI_FEATURE_OWE) != 0; + mIsEnhancedOpenSupported = iface.featureSet.get(WIFI_FEATURE_OWE); + if (rsnOverriding()) { + mIsRsnOverridingSupported = isSupplicantAidlServiceVersionAtLeast(4) + ? mSupplicantStaIfaceHal.isRsnOverridingSupported(iface.name) + : mContext.getResources().getBoolean( + R.bool.config_wifiRsnOverridingEnabled); + } Log.i(TAG, "Successfully switched to connectivity mode on iface=" + iface); return true; } @@ -2090,6 +2115,7 @@ public class WifiNative { ies, result.getCapabilities(), mIsEnhancedOpenSupported, + mIsRsnOverridingSupported, result.getFrequencyMhz(), mUnknownAkmMap); String flags = capabilities.generateCapabilitiesString(); @@ -3618,6 +3644,11 @@ public class WifiNative { * See WifiScanner.REASON_* for possible values. */ void onScanRequestFailed(int errorCode); + + /** + * Callback for all APs ScanResult + */ + void onFullScanResults(List<ScanResult> fullScanResult, int bucketsScanned); } /** @@ -3751,6 +3782,30 @@ public class WifiNative { WifiLinkLayerStats stats = mWifiVendorHal.getWifiLinkLayerStats(ifaceName); if (stats != null) { stats.aggregateLinkLayerStats(); + stats.wifiMloMode = getMloMode(); + ScanData scanData = getCachedScanResults(ifaceName); + if (scanData != null && scanData.getResults() != null + && scanData.getResults().length > 0) { + for (int linkIndex = 0; linkIndex < stats.links.length; ++linkIndex) { + List<ScanResultWithSameFreq> ScanResultsSameFreq = new ArrayList<>(); + for (int scanResultsIndex = 0; scanResultsIndex < scanData.getResults().length; + ++scanResultsIndex) { + if (scanData.getResults()[scanResultsIndex].frequency + != stats.links[linkIndex].frequencyMhz) { + continue; + } + ScanResultWithSameFreq ScanResultSameFreq = new ScanResultWithSameFreq(); + ScanResultSameFreq.scan_result_timestamp_micros = + scanData.getResults()[scanResultsIndex].timestamp; + ScanResultSameFreq.rssi = scanData.getResults()[scanResultsIndex].level; + ScanResultSameFreq.frequencyMhz = + scanData.getResults()[scanResultsIndex].frequency; + ScanResultSameFreq.bssid = scanData.getResults()[scanResultsIndex].BSSID; + ScanResultsSameFreq.add(ScanResultSameFreq); + } + stats.links[linkIndex].scan_results_same_freq = ScanResultsSameFreq; + } + } } return stats; } @@ -3931,19 +3986,18 @@ public class WifiNative { * @param ifaceName Name of the interface. * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ - public long getSupportedFeatureSet(String ifaceName) { + public @NonNull BitSet getSupportedFeatureSet(String ifaceName) { synchronized (mLock) { - long featureSet = 0; // First get the complete feature set stored in config store when supplicant was // started - featureSet = getCompleteFeatureSetFromConfigStore(); + BitSet featureSet = getCompleteFeatureSetFromConfigStore(); // Include the feature set saved in interface class. This is to make sure that // framework is returning the feature set for SoftAp only products and multi-chip // products. if (ifaceName != null) { Iface iface = mIfaceMgr.getIface(ifaceName); if (iface != null) { - featureSet |= iface.featureSet; + featureSet.or(iface.featureSet); } } return featureSet; @@ -3972,15 +4026,15 @@ public class WifiNative { * @param ifaceName Name of the interface. * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ - private long getSupportedFeatureSetInternal(@NonNull String ifaceName) { - long featureSet = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName) - | mWifiVendorHal.getSupportedFeatureSet(ifaceName) - | mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName); + private BitSet getSupportedFeatureSetInternal(@NonNull String ifaceName) { + BitSet featureSet = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName); + featureSet.or(mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName)); + featureSet.or(mWifiVendorHal.getSupportedFeatureSet(ifaceName)); if (SdkLevel.isAtLeastT()) { - if (((featureSet & WifiManager.WIFI_FEATURE_DPP) != 0) + if (featureSet.get(WifiManager.WIFI_FEATURE_DPP) && mContext.getResources().getBoolean(R.bool.config_wifiDppAkmSupported)) { // Set if DPP is filled by supplicant and DPP AKM is enabled by overlay. - featureSet |= WifiManager.WIFI_FEATURE_DPP_AKM; + featureSet.set(WifiManager.WIFI_FEATURE_DPP_AKM); Log.v(TAG, ": DPP AKM supported"); } } @@ -5159,12 +5213,12 @@ public class WifiNative { * Save the complete list of features retrieved from WiFi HAL and Supplicant HAL in * config store. */ - private void saveCompleteFeatureSetInConfigStoreIfNecessary(long featureSet) { - long cachedFeatureSet = getCompleteFeatureSetFromConfigStore(); - if (cachedFeatureSet != featureSet) { + private void saveCompleteFeatureSetInConfigStoreIfNecessary(BitSet featureSet) { + BitSet cachedFeatureSet = getCompleteFeatureSetFromConfigStore(); + if (!cachedFeatureSet.equals(featureSet)) { mCachedFeatureSet = featureSet; mWifiInjector.getSettingsConfigStore() - .put(WIFI_NATIVE_SUPPORTED_FEATURES, mCachedFeatureSet); + .put(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES, mCachedFeatureSet.toLongArray()); Log.i(TAG, "Supported features is updated in config store: " + mCachedFeatureSet); } } @@ -5172,10 +5226,18 @@ public class WifiNative { /** * Get the feature set from cache/config store */ - private long getCompleteFeatureSetFromConfigStore() { - if (mCachedFeatureSet == 0) { - mCachedFeatureSet = mWifiInjector.getSettingsConfigStore() - .get(WIFI_NATIVE_SUPPORTED_FEATURES); + private BitSet getCompleteFeatureSetFromConfigStore() { + if (mCachedFeatureSet == null) { + long[] extendedFeatures = mWifiInjector.getSettingsConfigStore() + .get(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES); + if (extendedFeatures == null || extendedFeatures.length == 0) { + // Retrieve the legacy feature set if the extended features are not available + long legacyFeatures = mWifiInjector.getSettingsConfigStore() + .get(WIFI_NATIVE_SUPPORTED_FEATURES); + mCachedFeatureSet = longToBitset(legacyFeatures); + } else { + mCachedFeatureSet = BitSet.valueOf(extendedFeatures); + } } return mCachedFeatureSet; } diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index dc58ee4154..bdb3309656 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -77,6 +77,7 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.ActionListenerWrapper; import com.android.server.wifi.util.WifiPermissionsUtil; +import com.android.wifi.flags.FeatureFlags; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -151,6 +152,7 @@ public class WifiNetworkFactory extends NetworkFactory { private final FrameworkFacade mFacade; private final MultiInternetManager mMultiInternetManager; private final NetworkCapabilities mCapabilitiesFilter; + private final FeatureFlags mFeatureFlags; private RemoteCallbackList<INetworkRequestMatchCallback> mRegisteredCallbacks; // Store all user approved access points for apps. @VisibleForTesting @@ -589,6 +591,7 @@ public class WifiNetworkFactory extends NetworkFactory { // Create the scan settings. mScanSettings = new WifiScanner.ScanSettings(); mScanSettings.type = WifiScanner.SCAN_TYPE_HIGH_ACCURACY; + mScanSettings.channels = new WifiScanner.ChannelSpec[0]; mScanSettings.band = WifiScanner.WIFI_BAND_ALL; mScanSettings.reportEvents = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN; mScanListener = new NetworkFactoryScanListener(); @@ -598,6 +601,7 @@ public class WifiNetworkFactory extends NetworkFactory { mFacade = facade; mMultiInternetManager = multiInternetManager; mCapabilitiesFilter = nc; + mFeatureFlags = mWifiInjector.getDeviceConfigFacade().getFeatureFlags(); // register the data store for serializing/deserializing data. configStore.registerStoreData( @@ -1163,9 +1167,10 @@ public class WifiNetworkFactory extends NetworkFactory { networkToConnect.BSSID = network.BSSID; } else { // If not pre-approved, find the best bssid matching the request. - networkToConnect.BSSID = - findBestBssidFromActiveMatchedScanResultsForNetwork( - ScanResultMatchInfo.fromWifiConfiguration(networkToConnect)); + ScanResult bestScanResult = findBestScanResultFromActiveMatchedScanResultsForNetwork( + ScanResultMatchInfo.fromWifiConfiguration(networkToConnect)); + networkToConnect.BSSID = bestScanResult != null ? bestScanResult.BSSID : null; + } networkToConnect.ephemeral = true; // Mark it user private to avoid conflicting with any saved networks the user might have. @@ -1210,7 +1215,8 @@ public class WifiNetworkFactory extends NetworkFactory { private void handleConnectToNetworkUserSelection(WifiConfiguration network, boolean didUserSeeUi) { - Log.d(TAG, "User initiated connect to network: " + network.SSID); + Log.d(TAG, "User initiated connect to network: " + network.SSID + " (apChannel:" + + network.apChannel + ")"); // Cancel the ongoing scans after user selection. cancelPeriodicScans(); @@ -1225,6 +1231,14 @@ public class WifiNetworkFactory extends NetworkFactory { private void handleRejectUserSelection() { Log.w(TAG, "User dismissed notification, cancelling " + mActiveSpecificNetworkRequest); + if (mFeatureFlags.localOnlyConnectionOptimization() + && mActiveSpecificNetworkRequestSpecifier != null + && mActiveSpecificNetworkRequest != null) { + sendConnectionFailureIfAllowed(mActiveSpecificNetworkRequest.getRequestorPackageName(), + mActiveSpecificNetworkRequest.getRequestorUid(), + mActiveSpecificNetworkRequestSpecifier, + WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT); + } teardownForActiveRequest(); mWifiMetrics.incrementNetworkRequestApiNumUserReject(); } @@ -1323,7 +1337,8 @@ public class WifiNetworkFactory extends NetworkFactory { } sendConnectionFailureIfAllowed(mActiveSpecificNetworkRequest.getRequestorPackageName(), mActiveSpecificNetworkRequest.getRequestorUid(), - mActiveSpecificNetworkRequestSpecifier, failureCode); + mActiveSpecificNetworkRequestSpecifier, + internalConnectionEventToLocalOnlyFailureCode(failureCode)); teardownForActiveRequest(); } @@ -1641,8 +1656,8 @@ public class WifiNetworkFactory extends NetworkFactory { mUserApprovedScanRetryCount++; // Create a worksource using the caller's UID. WorkSource workSource = new WorkSource(mActiveSpecificNetworkRequest.getRequestorUid()); - mWifiScanner.startScan( - mScanSettings, new HandlerExecutor(mHandler), mScanListener, workSource); + mWifiScanner.startScan(new WifiScanner.ScanSettings(mScanSettings), + new HandlerExecutor(mHandler), mScanListener, workSource); } private boolean doesScanResultMatchWifiNetworkSpecifier( @@ -1780,13 +1795,13 @@ public class WifiNetworkFactory extends NetworkFactory { return false; } - // Will return the best bssid to use for the current request's connection. + // Will return the best scan result to use for the current request's connection. // // Note: This will never return null, unless there is some internal error. // For ex: // i) The latest scan results were empty. // ii) The latest scan result did not contain any BSSID for the SSID user chose. - private @Nullable String findBestBssidFromActiveMatchedScanResultsForNetwork( + private @Nullable ScanResult findBestScanResultFromActiveMatchedScanResultsForNetwork( @NonNull ScanResultMatchInfo scanResultMatchInfo) { if (mActiveSpecificNetworkRequestSpecifier == null || mActiveMatchedScanResults == null) return null; @@ -1805,7 +1820,7 @@ public class WifiNetworkFactory extends NetworkFactory { if (mVerboseLoggingEnabled) { Log.v(TAG, "Best bssid selected for the request " + selectedScanResult); } - return selectedScanResult.BSSID; + return selectedScanResult; } private boolean isAccessPointApprovedInInternalApprovalList( @@ -2014,10 +2029,13 @@ public class WifiNetworkFactory extends NetworkFactory { WifiConfiguration config = mActiveSpecificNetworkRequestSpecifier.wifiConfiguration; config.SSID = "\"" + mActiveSpecificNetworkRequestSpecifier.ssidPatternMatcher.getPath() + "\""; - config.BSSID = findBestBssidFromActiveMatchedScanResultsForNetwork( + ScanResult bestScanResult = findBestScanResultFromActiveMatchedScanResultsForNetwork( ScanResultMatchInfo.fromWifiConfiguration(config)); + config.BSSID = bestScanResult != null ? bestScanResult.BSSID : null; + config.apChannel = bestScanResult != null ? bestScanResult.frequency : 0; Log.v(TAG, "Bypassing user dialog for connection to SSID=" - + config.SSID + ", BSSID=" + config.BSSID); + + config.SSID + ", BSSID=" + config.BSSID + ", apChannel=" + + config.apChannel); handleConnectToNetworkUserSelection(config, false); } } @@ -2121,7 +2139,8 @@ public class WifiNetworkFactory extends NetworkFactory { } private void sendConnectionFailureIfAllowed(String packageName, - int uid, @NonNull WifiNetworkSpecifier networkSpecifier, int connectionEvent) { + int uid, @NonNull WifiNetworkSpecifier networkSpecifier, + @WifiManager.LocalOnlyConnectionStatusCode int failureReason) { RemoteCallbackList<ILocalOnlyConnectionStatusListener> listenersTracker = mLocalOnlyStatusListenerPerApp.get(packageName); if (listenersTracker == null || listenersTracker.getRegisteredCallbackCount() == 0) { @@ -2135,7 +2154,7 @@ public class WifiNetworkFactory extends NetworkFactory { for (int i = 0; i < n; i++) { try { listenersTracker.getBroadcastItem(i).onConnectionStatus(networkSpecifier, - internalConnectionEventToLocalOnlyFailureCode(connectionEvent)); + failureReason); } catch (RemoteException e) { Log.e(TAG, "sendNetworkCallback: remote exception -- " + e); } diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java index 12598a5d7b..4f5a2b8568 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -467,7 +467,8 @@ public class WifiNetworkSelector { @SuppressLint("NewApi") private List<ScanDetail> filterScanResults(List<ScanDetail> scanDetails, - Set<String> bssidBlocklist, List<ClientModeManagerState> cmmStates) { + Set<String> bssidBlocklist, List<ClientModeManagerState> cmmStates, + int autojoinRestrictionSecurityTypes) { List<ScanDetail> validScanDetails = new ArrayList<>(); StringBuffer noValidSsid = new StringBuffer(); StringBuffer blockedBssid = new StringBuffer(); @@ -475,6 +476,7 @@ public class WifiNetworkSelector { StringBuffer mboAssociationDisallowedBssid = new StringBuffer(); StringBuffer adminRestrictedSsid = new StringBuffer(); StringJoiner deprecatedSecurityTypeSsid = new StringJoiner(" / "); + StringJoiner autojoinRestrictionSecurityTypesBssid = new StringJoiner(" / "); List<String> currentBssids = cmmStates.stream() .map(cmmState -> cmmState.wifiInfo.getBSSID()) .collect(Collectors.toList()); @@ -611,6 +613,22 @@ public class WifiNetworkSelector { } } + // Skip network with security type that is restricted to auto join + if (autojoinRestrictionSecurityTypes != 0/*restrict none*/) { + @WifiAnnotations.SecurityType int[] securityTypes = scanResult.getSecurityTypes(); + boolean securityTypeRestricted = true; + for (int type : securityTypes) { + if (((0x1 << type) & autojoinRestrictionSecurityTypes) == 0) { + securityTypeRestricted = false; + break; + } + } + if (securityTypeRestricted) { + autojoinRestrictionSecurityTypesBssid.add(scanId); + continue; + } + } + validScanDetails.add(scanDetail); } mWifiMetrics.incrementNetworkSelectionFilteredBssidCount(numBssidFiltered); @@ -663,6 +681,11 @@ public class WifiNetworkSelector { + deprecatedSecurityTypeSsid); } + if (autojoinRestrictionSecurityTypesBssid.length() != 0) { + localLog("Networks filtered out due to auto join restriction on the security type: " + + autojoinRestrictionSecurityTypesBssid); + } + return validScanDetails; } @@ -685,7 +708,7 @@ public class WifiNetworkSelector { mIsEnhancedOpenSupportedInitialized = true; ClientModeManager primaryManager = mWifiInjector.getActiveModeWarden().getPrimaryClientModeManager(); - mIsEnhancedOpenSupported = (primaryManager.getSupportedFeatures() & WIFI_FEATURE_OWE) != 0; + mIsEnhancedOpenSupported = primaryManager.getSupportedFeatures().get(WIFI_FEATURE_OWE); return mIsEnhancedOpenSupported; } @@ -1075,7 +1098,8 @@ public class WifiNetworkSelector { @NonNull List<ScanDetail> scanDetails, @NonNull Set<String> bssidBlocklist, @NonNull List<ClientModeManagerState> cmmStates, boolean untrustedNetworkAllowed, boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed, - Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck) { + Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck, + int autojoinRestrictionSecurityTypes) { mFilteredNetworks.clear(); mConnectableNetworks.clear(); if (scanDetails.size() == 0) { @@ -1092,7 +1116,8 @@ public class WifiNetworkSelector { } // Filter out unwanted networks. - mFilteredNetworks = filterScanResults(scanDetails, bssidBlocklist, cmmStates); + mFilteredNetworks = filterScanResults(scanDetails, bssidBlocklist, cmmStates, + autojoinRestrictionSecurityTypes); if (mFilteredNetworks.size() == 0) { return null; } @@ -1129,7 +1154,7 @@ public class WifiNetworkSelector { String currentBssid = cmmState.wifiInfo.getBSSID(); WifiConfiguration currentNetwork = mWifiConfigManager.getConfiguredNetwork(cmmState.wifiInfo.getNetworkId()); - if (currentNetwork != null) { + if (currentNetwork != null && currentBssid != null) { wifiCandidates.setCurrent(currentNetwork.networkId, currentBssid); // We always want the current network to be a candidate so that it can // participate. diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 60f4d948cb..ee4bb2f176 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -74,6 +74,7 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.BitSet; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; @@ -380,7 +381,7 @@ public class WifiNetworkSuggestionsManager { config.allowAutojoin = isAutojoinEnabled; if (config.enterpriseConfig != null && config.enterpriseConfig.isAuthenticationSimBased() - && anonymousIdentity != null) { + && !TextUtils.isEmpty(anonymousIdentity)) { config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity); } config.getNetworkSelectionStatus().setConnectChoice(connectChoice); @@ -1115,7 +1116,7 @@ public class WifiNetworkSuggestionsManager { return false; } - long supportedFeatures = mWifiInjector.getActiveModeWarden() + BitSet supportedFeatures = mWifiInjector.getActiveModeWarden() .getPrimaryClientModeManager().getSupportedFeatures(); for (WifiNetworkSuggestion wns : networkSuggestions) { @@ -1946,13 +1947,6 @@ public class WifiNetworkSuggestionsManager { */ public @NonNull List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( List<ScanResult> scanResults) { - // Create a temporary look-up table. - // As they are all single type configurations, they should have unique keys. - Map<String, WifiConfiguration> wifiConfigMap = new HashMap<>(); - WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs( - mWifiConfigManager.getConfiguredNetworks(), true) - .forEach(c -> wifiConfigMap.put(c.getProfileKey(), c)); - // Create a HashSet to avoid return multiple result for duplicate ScanResult. Set<String> networkKeys = new HashSet<>(); List<WifiConfiguration> sharedWifiConfigs = new ArrayList<>(); @@ -1996,7 +1990,8 @@ public class WifiNetworkSuggestionsManager { config, ewns.perAppInfo.packageName)) { continue; } - WifiConfiguration wCmWifiConfig = wifiConfigMap.get(config.getProfileKey()); + WifiConfiguration wCmWifiConfig = mWifiConfigManager + .getConfiguredNetwork(config.getProfileKey()); if (wCmWifiConfig == null) { continue; } @@ -2747,6 +2742,11 @@ public class WifiNetworkSuggestionsManager { } for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestionSet) { ewns.anonymousIdentity = config.enterpriseConfig.getAnonymousIdentity(); + if (TextUtils.isEmpty(ewns.anonymousIdentity)) { + // Update WifiConfig with App set AnonymousIdentity + updateWifiConfigInWcmIfPresent(ewns.createInternalWifiConfiguration( + mWifiCarrierInfoManager), ewns.perAppInfo.uid, ewns.perAppInfo.packageName); + } } saveToStore(); } diff --git a/service/java/com/android/server/wifi/WifiPulledAtomLogger.java b/service/java/com/android/server/wifi/WifiPulledAtomLogger.java index 44bc126557..36a54e68e6 100644 --- a/service/java/com/android/server/wifi/WifiPulledAtomLogger.java +++ b/service/java/com/android/server/wifi/WifiPulledAtomLogger.java @@ -26,6 +26,7 @@ import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiSsid; import android.os.Handler; import android.os.Process; +import android.text.TextUtils; import android.util.Log; import android.util.StatsEvent; @@ -149,6 +150,10 @@ public class WifiPulledAtomLogger { data.add(WifiStatsLog.buildStatsEvent(atomTag, WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__LOCATION_MODE, mWifiInjector.getWifiPermissionsUtil().isLocationModeEnabled())); + data.add(WifiStatsLog.buildStatsEvent(atomTag, + WifiStatsLog.WIFI_SETTING_INFO__SETTING_NAME__EXTERNAL_SCORER_DRY_RUN, + !TextUtils.isEmpty( + mWifiInjector.getDeviceConfigFacade().getDryRunScorerPkgName()))); return StatsManager.PULL_SUCCESS; } diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 107a6449bd..92b1835d21 100644 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ b/service/java/com/android/server/wifi/WifiScoreReport.java @@ -36,6 +36,7 @@ import android.os.Build; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.RequiresApi; @@ -43,6 +44,7 @@ import androidx.annotation.RequiresApi; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ActiveModeManager.ClientRole; +import com.android.server.wifi.proto.WifiStatsLog; import com.android.server.wifi.util.RssiUtil; import com.android.server.wifi.util.StringUtil; import com.android.wifi.resources.R; @@ -85,6 +87,10 @@ public class WifiScoreReport { private int mLegacyIntScore = ConnectedScore.WIFI_INITIAL_SCORE; // Cache of the last usability status private boolean mIsUsable = true; + private int mExternalScorerPredictionStatusForEvaluation = + WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE; + private int mAospScorerPredictionStatusForEvaluation = + WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE; /** * If true, indicates that the associated {@link ClientModeImpl} instance is lingering @@ -132,6 +138,8 @@ public class WifiScoreReport { /** * Callback from {@link ExternalScoreUpdateObserverProxy} + * + * Wifi Scorer calls these callbacks when it needs to send information to us. */ private class ScoreUpdateObserverProxy implements WifiManager.ScoreUpdateObserver { @Override @@ -145,6 +153,9 @@ public class WifiScoreReport { + " score=" + score); return; } + if (mIsExternalScorerDryRun) { + return; + } long millis = mClock.getWallClockMillis(); if (SdkLevel.isAtLeastS()) { mLegacyIntScore = score; @@ -198,6 +209,9 @@ public class WifiScoreReport { + " interfaceName=" + mInterfaceName); return; } + if (mIsExternalScorerDryRun) { + return; + } WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); // update mWifiInfo @@ -257,6 +271,11 @@ public class WifiScoreReport { + " isUsable=" + isUsable); return; } + mExternalScorerPredictionStatusForEvaluation = + convertToPredictionStatusForEvaluation(isUsable); + if (mIsExternalScorerDryRun) { + return; + } if (mNetworkAgent == null) { return; } @@ -310,6 +329,9 @@ public class WifiScoreReport { + " currentSessionId=" + getCurrentSessionId()); return; } + if (mIsExternalScorerDryRun) { + return; + } if (!mAdaptiveConnectivityEnabledSettingObserver.get() || !mWifiSettingsStore.isWifiScoringEnabled()) { if (mVerboseLoggingEnabled) { @@ -330,6 +352,9 @@ public class WifiScoreReport { + " mSessionIdNoReset=" + mSessionIdNoReset); return; } + if (mIsExternalScorerDryRun) { + return; + } if (!mAdaptiveConnectivityEnabledSettingObserver.get() || !mWifiSettingsStore.isWifiScoringEnabled()) { if (mVerboseLoggingEnabled) { @@ -379,6 +404,7 @@ public class WifiScoreReport { return; } if (mWifiConnectedNetworkScorerHolder != null + && !mIsExternalScorerDryRun && mContext.getResources().getBoolean( R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled) /// Turn off hysteresis/dampening for shell commands. @@ -547,6 +573,7 @@ public class WifiScoreReport { @Nullable private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder; + private boolean mIsExternalScorerDryRun; private final AdaptiveConnectivityEnabledSettingObserver mAdaptiveConnectivityEnabledSettingObserver; @@ -600,6 +627,7 @@ public class WifiScoreReport { */ public void reset() { mSessionNumber++; + clearScorerPredictionStatusForEvaluation(); mLegacyIntScore = isPrimary() ? ConnectedScore.WIFI_INITIAL_SCORE : ConnectedScore.WIFI_SECONDARY_INITIAL_SCORE; mIsUsable = true; @@ -626,19 +654,15 @@ public class WifiScoreReport { } /** - * Calculate wifi network score based on updated link layer stats and send the score to - * the WifiNetworkAgent. - * - * If the score has changed from the previous value, update the WifiNetworkAgent. + * Calculate the new wifi network score based on updated link layer stats. * * Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds. + * + * Note: This function will only notify connectivity services of the updated route if we are NOT + * using a connected external WiFi scorer. + * */ public void calculateAndReportScore() { - // Bypass AOSP scorer if Wifi connected network scorer is set - if (mWifiConnectedNetworkScorerHolder != null) { - return; - } - if (mWifiInfo.getRssi() == mWifiInfo.INVALID_RSSI) { Log.d(TAG, "Not reporting score because RSSI is invalid"); return; @@ -696,6 +720,13 @@ public class WifiScoreReport { score = 0; } + mAospScorerPredictionStatusForEvaluation = convertToPredictionStatusForEvaluation( + score >= transitionScore); + // Bypass AOSP scorer if Wifi connected network scorer is set + if (mWifiConnectedNetworkScorerHolder != null && !mIsExternalScorerDryRun) { + return; + } + if (score < mWifiGlobals.getWifiLowConnectedScoreThresholdToTriggerScanForMbb() && enoughTimePassedSinceLastLowConnectedScoreScan() && mActiveModeWarden.canRequestSecondaryTransientClientModeManager()) { @@ -988,13 +1019,18 @@ public class WifiScoreReport { return false; } mWifiConnectedNetworkScorerHolder = scorerHolder; - mWifiGlobals.setUsingExternalScorer(true); + mDeviceConfigFacade.setDryRunScorerPkgNameChangedListener(dryRunPkgName -> { + mIsExternalScorerDryRun = + isExternalScorerDryRun(dryRunPkgName, callerUid); + mWifiGlobals.setUsingExternalScorer(!mIsExternalScorerDryRun); + }); + mIsExternalScorerDryRun = + isExternalScorerDryRun(mDeviceConfigFacade.getDryRunScorerPkgName(), callerUid); + mWifiGlobals.setUsingExternalScorer(!mIsExternalScorerDryRun); // Register to receive updates from external scorer. mExternalScoreUpdateObserverProxy.registerCallback(mScoreUpdateObserverCallback); - // Disable AOSP scorer - mVelocityBasedConnectedScore = null; mWifiMetrics.setIsExternalWifiScorerOn(true, callerUid); // If there is already a connection, start a new session final int netId = getCurrentNetId(); @@ -1004,6 +1040,18 @@ public class WifiScoreReport { return true; } + private boolean isExternalScorerDryRun(String dryRunPkgName, int uid) { + Log.d(TAG, "isExternalScorerDryRun(" + dryRunPkgName + ", " + uid + ")"); + String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + for (String packageName : packageNames) { + if (!TextUtils.isEmpty(packageName) + && packageName.equalsIgnoreCase(dryRunPkgName)) { + return true; + } + } + return false; + } + /** * Clear an existing scorer for Wi-Fi connected network score handling. */ @@ -1019,7 +1067,7 @@ public class WifiScoreReport { * Notify the connected network scorer of the user accepting a network switch. */ public void onNetworkSwitchAccepted(int targetNetworkId, String targetBssid) { - if (mWifiConnectedNetworkScorerHolder == null) { + if (mWifiConnectedNetworkScorerHolder == null || mIsExternalScorerDryRun) { return; } mWifiConnectedNetworkScorerHolder.onNetworkSwitchAccepted( @@ -1030,7 +1078,7 @@ public class WifiScoreReport { * Notify the connected network scorer of the user rejecting a network switch. */ public void onNetworkSwitchRejected(int targetNetworkId, String targetBssid) { - if (mWifiConnectedNetworkScorerHolder == null) { + if (mWifiConnectedNetworkScorerHolder == null || mIsExternalScorerDryRun) { return; } mWifiConnectedNetworkScorerHolder.onNetworkSwitchRejected( @@ -1070,17 +1118,21 @@ public class WifiScoreReport { * @param netId identifies the current android.net.Network */ public void startConnectedNetworkScorer(int netId, boolean isUserSelected) { + Log.d(TAG, "startConnectedNetworkScorer(" + netId + ", " + isUserSelected + ")"); mIsUserSelected = isUserSelected; final int sessionId = getCurrentSessionId(); if (mWifiConnectedNetworkScorerHolder == null || netId != getCurrentNetId() || isLocalOnlyOrRestrictedConnection() || sessionId == INVALID_SESSION_ID) { - Log.w(TAG, "Cannot start external scoring" - + " netId=" + netId - + " currentNetId=" + getCurrentNetId() - + " currentNetCapabilities=" + getCurrentNetCapabilities() - + " sessionId=" + sessionId); + StringBuilder sb = new StringBuilder(); + sb.append("Cannot start external scoring netId=").append(netId) + .append(" currentNetId=").append(getCurrentNetId()); + if (mVerboseLoggingEnabled) { + sb.append(" currentNetCapabilities=").append(getCurrentNetCapabilities()); + } + sb.append(" sessionId=").append(sessionId); + Log.w(TAG, sb.toString()); return; } mCurrentWifiConfiguration = mWifiConfigManager.getConfiguredNetwork( @@ -1148,12 +1200,12 @@ public class WifiScoreReport { shouldForceKeepConnected ? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER : NetworkScore.KEEP_CONNECTED_NONE; - boolean exiting = SdkLevel.isAtLeastS() && mWifiConnectedNetworkScorerHolder != null + boolean exiting = (SdkLevel.isAtLeastS() && mWifiConnectedNetworkScorerHolder != null) ? !mIsUsable : mLegacyIntScore < ConnectedScore.WIFI_TRANSITION_SCORE; return new NetworkScore.Builder() .setLegacyInt(mShouldReduceNetworkScore ? LINGERING_SCORE : mLegacyIntScore) .setTransportPrimary(mCurrentRole == ActiveModeManager.ROLE_CLIENT_PRIMARY) - .setExiting(exiting) + .setExiting(exiting | mShouldReduceNetworkScore) .setKeepConnectedReason(keepConnectedReason); } @@ -1178,8 +1230,8 @@ public class WifiScoreReport { private void revertToDefaultConnectedScorer() { Log.d(TAG, "Using VelocityBasedConnectedScore"); - mVelocityBasedConnectedScore = new VelocityBasedConnectedScore(mScoringParams, mClock); mWifiConnectedNetworkScorerHolder = null; + mDeviceConfigFacade.setDryRunScorerPkgNameChangedListener(null); mWifiGlobals.setUsingExternalScorer(false); mExternalScoreUpdateObserverProxy.unregisterCallback(mScoreUpdateObserverCallback); mWifiMetrics.setIsExternalWifiScorerOn(false, Process.WIFI_UID); @@ -1201,6 +1253,43 @@ public class WifiScoreReport { } } + private int convertToPredictionStatusForEvaluation(boolean isUsable) { + return isUsable + ? WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE + : WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNUSABLE; + } + + /** + * Get whether an external scorer is registered. + */ + public boolean isExternalScorerRegistered() { + return mWifiConnectedNetworkScorerHolder != null; + } + + /** + * Get wifi predicted state for metrics + */ + public int getExternalScorerPredictionStatusForEvaluation() { + return mExternalScorerPredictionStatusForEvaluation; + } + + /** + * Get wifi predicted state for metrics + */ + public int getAospScorerPredictionStatusForEvaluation() { + return mAospScorerPredictionStatusForEvaluation; + } + + /** + * Clear the predicted states for metrics + */ + public void clearScorerPredictionStatusForEvaluation() { + mExternalScorerPredictionStatusForEvaluation = + WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE; + mAospScorerPredictionStatusForEvaluation = + WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE; + } + /** Called when the owner {@link ConcreteClientModeManager}'s role changes. */ public void onRoleChanged(@Nullable ClientRole role) { mCurrentRole = role; @@ -1208,4 +1297,13 @@ public class WifiScoreReport { if (mVelocityBasedConnectedScore != null) mVelocityBasedConnectedScore.onRoleChanged(role); sendNetworkScore(); } + + /** + * Get whether we are in the lingering state or not. + */ + public boolean getLingering() { + return (SdkLevel.isAtLeastS() && mWifiConnectedNetworkScorerHolder != null + && !mIsExternalScorerDryRun) + ? !mIsUsable : mLegacyIntScore < ConnectedScore.WIFI_TRANSITION_SCORE; + } } diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java index 30066a2387..59c462887d 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -28,15 +28,16 @@ import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERI import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; import static android.net.wifi.WifiManager.NOT_OVERRIDE_EXISTING_NETWORKS_ON_RESTORE; import static android.net.wifi.WifiManager.PnoScanResultsCallback.REGISTER_PNO_CALLBACK_PNO_NOT_SUPPORTED; +import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE; import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL; import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL; +import static android.net.wifi.WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY; import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING; import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; -import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AP; import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_AWARE; import static android.net.wifi.WifiManager.WIFI_INTERFACE_TYPE_DIRECT; @@ -99,7 +100,6 @@ import android.net.NetworkStack; import android.net.TetheringManager; import android.net.Uri; import android.net.ip.IpClientUtil; -import android.net.wifi.BaseWifiService; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.IActionListener; import android.net.wifi.IBooleanListener; @@ -132,6 +132,7 @@ import android.net.wifi.ITwtStatsListener; import android.net.wifi.IWifiBandsListener; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.IWifiLowLatencyLockListener; +import android.net.wifi.IWifiManager; import android.net.wifi.IWifiNetworkSelectionConfigListener; import android.net.wifi.IWifiNetworkStateChangedListener; import android.net.wifi.IWifiVerboseLoggingStatusChangedListener; @@ -199,6 +200,7 @@ import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseIntArray; +import android.uwb.UwbManager; import androidx.annotation.RequiresApi; @@ -206,6 +208,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.ParceledListSlice; +import com.android.modules.utils.StringParceledListSlice; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.Inet4AddressUtils; import com.android.server.wifi.coex.CoexManager; @@ -242,6 +245,7 @@ import java.security.cert.PKIXParameters; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -261,7 +265,7 @@ import java.util.function.IntConsumer; * WifiService handles remote WiFi operation requests by implementing * the IWifiManager interface. */ -public class WifiServiceImpl extends BaseWifiService { +public class WifiServiceImpl extends IWifiManager.Stub { private static final String TAG = "WifiService"; private static final boolean VDBG = false; @@ -335,7 +339,7 @@ public class WifiServiceImpl extends BaseWifiService { private static final String CERT_INSTALLER_PKG = "com.android.certinstaller"; private final WifiSettingsConfigStore mSettingsConfigStore; - private final WifiResourceCache mWifiResourceCache; + private final WifiResourceCache mResourceCache; /** * Callback for use with LocalOnlyHotspot to unregister requesting applications upon death. @@ -516,7 +520,7 @@ public class WifiServiceImpl extends BaseWifiService { public WifiServiceImpl(WifiContext context, WifiInjector wifiInjector) { mContext = context; - mWifiResourceCache = mContext.getResourceCache(); + mResourceCache = mContext.getResourceCache(); mWifiInjector = wifiInjector; mClock = wifiInjector.getClock(); @@ -693,21 +697,6 @@ public class WifiServiceImpl extends BaseWifiService { null, new Handler(mWifiHandlerThread.getLooper())); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent); - } - updateLocationMode(); - } - }, - new IntentFilter(LocationManager.MODE_CHANGED_ACTION), - null, - new Handler(mWifiHandlerThread.getLooper())); - updateLocationMode(); - if (SdkLevel.isAtLeastT()) { mContext.registerReceiver( new BroadcastReceiver() { @@ -886,6 +875,29 @@ public class WifiServiceImpl extends BaseWifiService { mWifiInjector.getWifiDeviceStateChangeManager().handleBootCompleted(); setPulledAtomCallbacks(); mTwtManager.registerWifiNativeTwtEvents(); + mContext.registerReceiverForAllUsers( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "onReceive: MODE_CHANGED_ACTION: intent=" + intent); + } + updateLocationMode(); + } + }, + new IntentFilter(LocationManager.MODE_CHANGED_ACTION), + null, + new Handler(mWifiHandlerThread.getLooper())); + updateLocationMode(); + + if (SdkLevel.isAtLeastT()) { + UwbManager uwbManager = + mContext.getSystemService(UwbManager.class); + if (uwbManager != null) { + uwbManager.registerAdapterStateCallback(new HandlerExecutor(new Handler( + mWifiHandlerThread.getLooper())), new UwbAdapterStateListener()); + } + } }, TAG + "#handleBootCompleted"); } @@ -1195,6 +1207,54 @@ public class WifiServiceImpl extends BaseWifiService { } /** + * Validates if the calling user is valid. + * + * @throws a {@link SecurityException} if the calling user is not valid. + */ + private void enforceValidCallingUser() { + if (!isValidCallingUser()) { + throw new SecurityException( + "Calling user " + Binder.getCallingUserHandle() + " is not the SYSTEM user, " + + "the current user, or a profile of the current user, " + + "thus not allowed to make changes to WIFI."); + } + } + + /** + * Checks if the calling user is valid on Automotive devices.. + * + * @return true if any of the following conditions are true: + * <li>The device is not an Automotive device. + * <li>the calling user is the system user. + * <li>the calling user is the current user. + * <li>the calling user belongs to the same profile group as the current user. + */ + private boolean isValidCallingUser() { + // TODO(b/360488316): Ideally UserManager#isVisibleBackgroundUsersEnabled() should be used + // but it is a hidden API. We rely on FEATURE_AUTOMOTIVE only, because we cannot access + // the RRO config for R.bool.config_multiuserVisibleBackgroundUsers. + if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { + return true; + } + UserHandle callingUser = Binder.getCallingUserHandle(); + + final long ident = Binder.clearCallingIdentity(); + try { + UserHandle currentUser = + UserHandle.of(mWifiInjector.getWifiPermissionsWrapper().getCurrentUser()); + if (UserHandle.SYSTEM.equals(callingUser) + || callingUser.equals(currentUser) + || mUserManager.isSameProfileGroup(callingUser, currentUser)) { + return true; + } + } finally { + Binder.restoreCallingIdentity(ident); + } + + return false; + } + + /** * Helper method to check if the app is allowed to access public API's deprecated in * {@link Build.VERSION_CODES#Q}. * Note: Invoke mAppOps.checkPackage(uid, packageName) before to ensure correct package name. @@ -1263,7 +1323,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public synchronized boolean setWifiEnabled(String packageName, boolean enable) { - if (enforceChangePermission(packageName) != MODE_ALLOWED) { + if (!isValidCallingUser() || enforceChangePermission(packageName) != MODE_ALLOWED) { return false; } int callingUid = Binder.getCallingUid(); @@ -1445,6 +1505,9 @@ public class WifiServiceImpl extends BaseWifiService { if (!SdkLevel.isAtLeastS()) { throw new UnsupportedOperationException(); } + if (callback == null) { + throw new IllegalArgumentException("Callback is null"); + } enforceAccessPermission(); if (mVerboseLoggingEnabled) { mLog.info("registerSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); @@ -1463,6 +1526,9 @@ public class WifiServiceImpl extends BaseWifiService { if (!SdkLevel.isAtLeastS()) { throw new UnsupportedOperationException(); } + if (callback == null) { + throw new IllegalArgumentException("Callback is null"); + } enforceAccessPermission(); if (mVerboseLoggingEnabled) { mLog.info("unregisterSubsystemRestartCallback uid=%").c(Binder.getCallingUid()).flush(); @@ -1601,7 +1667,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public boolean isDefaultCoexAlgorithmEnabled() { - return mContext.getResources().getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled); + return mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled); } /** @@ -1622,7 +1688,7 @@ public class WifiServiceImpl extends BaseWifiService { if (unsafeChannels == null) { throw new IllegalArgumentException("unsafeChannels cannot be null"); } - if (mContext.getResources().getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) { + if (mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) { Log.e(TAG, "setCoexUnsafeChannels called but default coex algorithm is enabled"); return; } @@ -1634,6 +1700,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#registerCoexCallback(WifiManager.CoexCallback)} */ + @Override @RequiresApi(Build.VERSION_CODES.S) public void registerCoexCallback(@NonNull ICoexCallback callback) { if (!SdkLevel.isAtLeastS()) { @@ -1672,6 +1739,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#unregisterCoexCallback(WifiManager.CoexCallback)} */ + @Override @RequiresApi(Build.VERSION_CODES.S) public void unregisterCoexCallback(@NonNull ICoexCallback callback) { if (!SdkLevel.isAtLeastS()) { @@ -1749,6 +1817,8 @@ public class WifiServiceImpl extends BaseWifiService { @Override public boolean startTetheredHotspot(@Nullable SoftApConfiguration softApConfig, @NonNull String packageName) { + enforceValidCallingUser(); + // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); int callingUid = Binder.getCallingUid(); @@ -1784,6 +1854,7 @@ public class WifiServiceImpl extends BaseWifiService { throw new IllegalArgumentException("callback must not be null"); } + enforceValidCallingUser(); // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); int callingUid = Binder.getCallingUid(); @@ -1890,6 +1961,8 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public boolean stopSoftAp() { + enforceValidCallingUser(); + // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); @@ -1989,7 +2062,6 @@ public class WifiServiceImpl extends BaseWifiService { + mCountryCode.getCurrentDriverCountryCode()); } // Store Soft AP channels for reference after a reboot before the driver is up. - Resources res = mContext.getResources(); mSettingsConfigStore.put(WifiSettingsConfigStore.WIFI_SOFT_AP_COUNTRY_CODE, countryCode); List<Integer> freqs = new ArrayList<>(); @@ -2000,7 +2072,7 @@ public class WifiServiceImpl extends BaseWifiService { continue; } List<Integer> freqsForBand = ApConfigUtil.getAvailableChannelFreqsForBand( - band, mWifiNative, res, true); + band, mWifiNative, mResourceCache, true); if (freqsForBand != null) { freqs.addAll(freqsForBand); int[] channel = new int[freqsForBand.size()]; @@ -2058,6 +2130,17 @@ public class WifiServiceImpl extends BaseWifiService { } } + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + class UwbAdapterStateListener implements UwbManager.AdapterStateCallback { + @Override + public void onStateChanged(int state, int reason) { + if (mVerboseLoggingEnabled) { + Log.d(TAG, "UwbManager.AdapterState=" + state); + } + mWifiMetrics.setLastUwbState(state); + } + } + /** * SoftAp callback */ @@ -2293,7 +2376,7 @@ public class WifiServiceImpl extends BaseWifiService { if (carrierConfig == null) return; int carrierMaxClient = carrierConfig.getInt( CarrierConfigManager.Wifi.KEY_HOTSPOT_MAX_CLIENT_COUNT); - int finalSupportedClientNumber = mContext.getResources().getInteger( + int finalSupportedClientNumber = mResourceCache.getInteger( R.integer.config_wifiHardwareSoftapMaxClientCount); if (carrierMaxClient > 0) { finalSupportedClientNumber = Math.min(finalSupportedClientNumber, @@ -2851,13 +2934,14 @@ public class WifiServiceImpl extends BaseWifiService { false, TAG + " registerLocalOnlyHotspotSoftApCallback"); if (mVerboseLoggingEnabled) { - mLog.info("registerSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); + mLog.info("registerLocalOnlyHotspotSoftApCallback uid=%") + .c(Binder.getCallingUid()).flush(); } // post operation to handler thread mWifiThreadRunner.post(() -> { if (!mLohsSoftApTracker.registerSoftApCallback(callback)) { - Log.e(TAG, "registerSoftApCallback: Failed to add callback"); + Log.e(TAG, "registerLocalOnlyHotspotSoftApCallback: Failed to add callback"); return; } }, TAG + "#registerLocalOnlyHotspotSoftApCallback"); @@ -2877,7 +2961,8 @@ public class WifiServiceImpl extends BaseWifiService { false, TAG + " registerLocalOnlyHotspotSoftApCallback"); if (mVerboseLoggingEnabled) { - mLog.info("unregisterSoftApCallback uid=%").c(Binder.getCallingUid()).flush(); + mLog.info("unregisterLocalOnlyHotspotSoftApCallback uid=%") + .c(Binder.getCallingUid()).flush(); } // post operation to handler thread @@ -3156,18 +3241,18 @@ public class WifiServiceImpl extends BaseWifiService { } /** - * Returns true if we should log the call to getSupportedFeatures. + * Returns true if we should log the call to isFeatureSupported. * - * Because of the way getSupportedFeatures is used in WifiManager, there are + * Because of the way isFeatureSupported is used in WifiManager, there are * often clusters of several back-to-back calls; avoid repeated logging if * the feature set has not changed and the time interval is short. */ - private boolean needToLogSupportedFeatures(long features) { + private boolean needToLogSupportedFeatures(BitSet features) { if (mVerboseLoggingEnabled) { long now = mClock.getElapsedSinceBootMillis(); synchronized (this) { if (now > mLastLoggedSupportedFeaturesTimestamp + A_FEW_MILLISECONDS - || features != mLastLoggedSupportedFeatures) { + || !features.equals(mLastLoggedSupportedFeatures)) { mLastLoggedSupportedFeaturesTimestamp = now; mLastLoggedSupportedFeatures = features; return true; @@ -3177,23 +3262,20 @@ public class WifiServiceImpl extends BaseWifiService { return false; } private static final int A_FEW_MILLISECONDS = 250; - private long mLastLoggedSupportedFeatures = -1; + private BitSet mLastLoggedSupportedFeatures = new BitSet(); private long mLastLoggedSupportedFeaturesTimestamp = 0; - /** - * see {@link android.net.wifi.WifiManager#getSupportedFeatures} - */ @Override - public long getSupportedFeatures() { + public boolean isFeatureSupported(int feature) { enforceAccessPermission(); - long features = getSupportedFeaturesInternal(); - if (needToLogSupportedFeatures(features)) { - mLog.info("getSupportedFeatures uid=% returns %") + BitSet supportedFeatures = getSupportedFeaturesInternal(); + if (needToLogSupportedFeatures(supportedFeatures)) { + mLog.info("isFeatureSupported uid=% returns %") .c(Binder.getCallingUid()) - .c(Long.toHexString(features)) + .c(supportedFeatures.toString()) .flush(); } - return features; + return supportedFeatures.get(feature); } @Override @@ -3208,7 +3290,7 @@ public class WifiServiceImpl extends BaseWifiService { .c(Binder.getCallingUid()) .flush(); } - if ((getSupportedFeatures() & WifiManager.WIFI_FEATURE_LINK_LAYER_STATS) == 0) { + if (!isFeatureSupported(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)) { try { listener.onWifiActivityEnergyInfo(null); } catch (RemoteException e) { @@ -3386,6 +3468,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#getPrivilegedConnectedNetwork()} */ + @Override public WifiConfiguration getPrivilegedConnectedNetwork(String packageName, String featureId, Bundle extras) { enforceReadCredentialPermission(); @@ -3535,7 +3618,7 @@ public class WifiServiceImpl extends BaseWifiService { // API was called to override the overlay value. return mSettingsConfigStore.get(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI); } else { - return mContext.getResources().getBoolean( + return mResourceCache.getBoolean( R.bool.config_showConfirmationDialogForThirdPartyAppsEnablingWifi); } } @@ -3631,20 +3714,21 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { + getAllMatchingPasspointProfilesForScanResults( + ParceledListSlice<ScanResult> scanResults) { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } if (mVerboseLoggingEnabled) { mLog.info("getMatchingPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); } - if (!ScanResultUtil.validateScanResultList(scanResults)) { + if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { Log.e(TAG, "Attempt to retrieve passpoint with invalid scanResult List"); return Collections.emptyMap(); } return mWifiThreadRunner.call( - () -> mPasspointManager.getAllMatchingPasspointProfilesForScanResults(scanResults), - Collections.emptyMap(), + () -> mPasspointManager.getAllMatchingPasspointProfilesForScanResults( + scanResults.getList()), Collections.emptyMap(), TAG + "#getAllMatchingPasspointProfilesForScanResults"); } @@ -3652,7 +3736,8 @@ public class WifiServiceImpl extends BaseWifiService { * See {@link WifiManager#setSsidsAllowlist(Set)} */ @Override - public void setSsidsAllowlist(@NonNull String packageName, @NonNull List<WifiSsid> ssids) { + public void setSsidsAllowlist(@NonNull String packageName, + @NonNull ParceledListSlice<WifiSsid> ssids) { int uid = Binder.getCallingUid(); mWifiPermissionsUtil.checkPackage(uid, packageName); boolean hasPermission = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) @@ -3667,15 +3752,16 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("setSsidsAllowlist uid=%").c(uid).flush(); } - mWifiThreadRunner.post(() -> - mWifiBlocklistMonitor.setSsidsAllowlist(ssids), TAG + "#setSsidsAllowlist"); + List<WifiSsid> ssidList = ssids == null ? null : ssids.getList(); + mWifiThreadRunner.post(() -> mWifiBlocklistMonitor.setSsidsAllowlist(ssidList), + TAG + "#setSsidsAllowlist"); } /** * See {@link WifiManager#getSsidsAllowlist()} */ @Override - public @NonNull List<WifiSsid> getSsidsAllowlist(String packageName) { + public @NonNull ParceledListSlice<WifiSsid> getSsidsAllowlist(String packageName) { int uid = Binder.getCallingUid(); mWifiPermissionsUtil.checkPackage(uid, packageName); boolean hasPermission = mWifiPermissionsUtil.checkNetworkSettingsPermission(uid) @@ -3690,9 +3776,9 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("getSsidsAllowlist uid=%").c(uid).flush(); } - return mWifiThreadRunner.call( + return new ParceledListSlice<>(mWifiThreadRunner.call( () -> mWifiBlocklistMonitor.getSsidsAllowlist(), Collections.EMPTY_LIST, - TAG + "#getSsidsAllowlist"); + TAG + "#getSsidsAllowlist")); } /** @@ -3703,21 +3789,20 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { + ParceledListSlice<ScanResult> scanResults) { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } if (mVerboseLoggingEnabled) { mLog.info("getMatchingOsuProviders uid=%").c(Binder.getCallingUid()).flush(); } - - if (!ScanResultUtil.validateScanResultList(scanResults)) { + if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { Log.w(TAG, "Attempt to retrieve OsuProviders with invalid scanResult List"); return Collections.emptyMap(); } return mWifiThreadRunner.call( - () -> mPasspointManager.getMatchingOsuProviders(scanResults), Collections.emptyMap(), - TAG + "#getMatchingOsuProviders"); + () -> mPasspointManager.getMatchingOsuProviders(scanResults.getList()), + Collections.emptyMap(), TAG + "#getMatchingOsuProviders"); } /** @@ -3728,7 +3813,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { + ParceledListSlice<OsuProvider> osuProviders) { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } @@ -3736,13 +3821,14 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getMatchingPasspointConfigsForOsuProviders uid=%").c( Binder.getCallingUid()).flush(); } - if (osuProviders == null) { + if (osuProviders == null || osuProviders.getList() == null) { Log.e(TAG, "Attempt to retrieve Passpoint configuration with null osuProviders"); return new HashMap<>(); } return mWifiThreadRunner.call( - () -> mPasspointManager.getMatchingPasspointConfigsForOsuProviders(osuProviders), - Collections.emptyMap(), TAG + "#getMatchingPasspointConfigsForOsuProviders"); + () -> mPasspointManager.getMatchingPasspointConfigsForOsuProviders( + osuProviders.getList()), Collections.emptyMap(), + TAG + "#getMatchingPasspointConfigsForOsuProviders"); } /** @@ -3755,7 +3841,8 @@ public class WifiServiceImpl extends BaseWifiService { * @return List of {@link WifiConfiguration} converted from {@link PasspointProvider} */ @Override - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { + public ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles( + StringParceledListSlice fqdnList) { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } @@ -3763,13 +3850,13 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getWifiConfigsForPasspointProfiles uid=%").c( Binder.getCallingUid()).flush(); } - if (fqdnList == null) { + if (fqdnList == null || fqdnList.getList() == null || fqdnList.getList().isEmpty()) { Log.e(TAG, "Attempt to retrieve WifiConfiguration with null fqdn List"); - return new ArrayList<>(); + return new ParceledListSlice<>(Collections.emptyList()); } - return mWifiThreadRunner.call( - () -> mPasspointManager.getWifiConfigsForPasspointProfiles(fqdnList), - Collections.emptyList(), TAG + "#getWifiConfigsForPasspointProfiles"); + return new ParceledListSlice<>(mWifiThreadRunner.call( + () -> mPasspointManager.getWifiConfigsForPasspointProfiles(fqdnList.getList()), + Collections.emptyList(), TAG + "#getWifiConfigsForPasspointProfiles")); } /** @@ -3783,8 +3870,9 @@ public class WifiServiceImpl extends BaseWifiService { * @return a list of {@link WifiConfiguration} from matched {@link WifiNetworkSuggestion}. */ @Override - public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { + public ParceledListSlice<WifiConfiguration> + getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + ParceledListSlice<ScanResult> scanResults) { if (!isSettingsOrSuw(Binder.getCallingPid(), Binder.getCallingUid())) { throw new SecurityException(TAG + ": Permission denied"); } @@ -3792,15 +3880,16 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getWifiConfigsForMatchedNetworkSuggestions uid=%").c( Binder.getCallingUid()).flush(); } - if (!ScanResultUtil.validateScanResultList(scanResults)) { + if (scanResults == null || !ScanResultUtil.validateScanResultList(scanResults.getList())) { Log.w(TAG, "Attempt to retrieve WifiConfiguration with invalid scanResult List"); - return new ArrayList<>(); + return new ParceledListSlice<>(Collections.emptyList()); } - return mWifiThreadRunner.call( + return new ParceledListSlice<>(WifiConfigurationUtil.convertMultiTypeConfigsToLegacyConfigs( + mWifiThreadRunner.call( () -> mWifiNetworkSuggestionsManager - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(scanResults), - Collections.emptyList(), - TAG + "#getWifiConfigForMatchedNetworkSuggestionsSharedWithUser"); + .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + scanResults.getList()), Collections.emptyList(), + TAG + "#getWifiConfigForMatchedNetworkSuggestionsSharedWithUser"), true)); } /** @@ -3891,6 +3980,11 @@ public class WifiServiceImpl extends BaseWifiService { boolean isCamera = mWifiPermissionsUtil.checkCameraPermission(callingUid); boolean isSystem = mWifiPermissionsUtil.isSystem(packageName, callingUid); boolean isPrivileged = isPrivileged(callingPid, callingUid); + if (!isPrivileged && !isSystem && !isAdmin && config.getBssidAllowlistInternal() != null) { + mLog.info("addOrUpdateNetwork with allow bssid list is not allowed for uid=%") + .c(callingUid).flush(); + return -1; + } if (!isTargetSdkLessThanQOrPrivileged(packageName, callingPid, callingUid)) { mLog.info("addOrUpdateNetwork not allowed for uid=%").c(callingUid).flush(); @@ -4370,7 +4464,7 @@ public class WifiServiceImpl extends BaseWifiService { @Override public void getBssidBlocklist(@NonNull ParceledListSlice<WifiSsid> ssids, @NonNull IMacAddressListListener listener) { - if (ssids == null) { + if (ssids == null || ssids.getList() == null) { throw new IllegalArgumentException("Null ssids"); } if (listener == null) { @@ -4663,24 +4757,29 @@ public class WifiServiceImpl extends BaseWifiService { @Override @NonNull public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - @NonNull List<WifiNetworkSuggestion> networkSuggestions, - @Nullable List<ScanResult> scanResults, + @NonNull ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, + @Nullable ParceledListSlice<ScanResult> scanResults, String callingPackage, String callingFeatureId) { enforceAccessPermission(); int uid = Binder.getCallingUid(); long ident = Binder.clearCallingIdentity(); + if (networkSuggestions == null || networkSuggestions.getList() == null) { + throw new IllegalArgumentException("networkSuggestions must not be null."); + } try { mWifiPermissionsUtil.enforceCanAccessScanResults(callingPackage, callingFeatureId, uid, null); return mWifiThreadRunner.call( () -> { - if (!ScanResultUtil.validateScanResultList(scanResults)) { + if (scanResults == null + || !ScanResultUtil.validateScanResultList(scanResults.getList())) { return mWifiNetworkSuggestionsManager.getMatchingScanResults( - networkSuggestions, mScanRequestProxy.getScanResults()); + networkSuggestions.getList(), + mScanRequestProxy.getScanResults()); } else { return mWifiNetworkSuggestionsManager.getMatchingScanResults( - networkSuggestions, scanResults); + networkSuggestions.getList(), scanResults.getList()); } }, Collections.emptyMap(), TAG + "#getMatchingScanResults"); @@ -4788,7 +4887,8 @@ public class WifiServiceImpl extends BaseWifiService { * @return A list of {@link PasspointConfiguration}. */ @Override - public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { + public ParceledListSlice<PasspointConfiguration> getPasspointConfigurations( + String packageName) { final int uid = Binder.getCallingUid(); mWifiPermissionsUtil.checkPackage(uid, packageName); boolean privileged = false; @@ -4800,9 +4900,9 @@ public class WifiServiceImpl extends BaseWifiService { mLog.info("getPasspointConfigurations uid=%").c(Binder.getCallingUid()).flush(); } final boolean privilegedFinal = privileged; - return mWifiThreadRunner.call( + return new ParceledListSlice<>(mWifiThreadRunner.call( () -> mPasspointManager.getProviderConfigs(uid, privilegedFinal), - Collections.emptyList(), TAG + "#getPasspointConfigurations"); + Collections.emptyList(), TAG + "#getPasspointConfigurations")); } /** @@ -5022,7 +5122,7 @@ public class WifiServiceImpl extends BaseWifiService { } private boolean is24GhzBandSupportedInternal() { - if (mContext.getResources().getBoolean(R.bool.config_wifi24ghzSupport)) { + if (mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)) { return true; } return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); @@ -5039,7 +5139,7 @@ public class WifiServiceImpl extends BaseWifiService { } private boolean is5GhzBandSupportedInternal() { - if (mContext.getResources().getBoolean(R.bool.config_wifi5ghzSupport)) { + if (mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)) { return true; } return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); @@ -5055,7 +5155,7 @@ public class WifiServiceImpl extends BaseWifiService { } private boolean is6GhzBandSupportedInternal() { - if (mContext.getResources().getBoolean(R.bool.config_wifi6ghzSupport)) { + if (mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)) { return true; } return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ); @@ -5075,7 +5175,7 @@ public class WifiServiceImpl extends BaseWifiService { } private boolean is60GhzBandSupportedInternal() { - if (mContext.getResources().getBoolean(R.bool.config_wifi60ghzSupport)) { + if (mResourceCache.getBoolean(R.bool.config_wifi60ghzSupport)) { return true; } return mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_60_GHZ); @@ -5532,7 +5632,7 @@ public class WifiServiceImpl extends BaseWifiService { mContext, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); pw.println("mInIdleMode " + mInIdleMode); pw.println("mScanPending " + mScanPending); - pw.println("SupportedFeatures:" + Long.toHexString(getSupportedFeaturesInternal())); + pw.println("SupportedFeatures: " + getSupportedFeaturesInternal()); pw.println("SettingsStore:"); mSettingsStore.dump(fd, pw, args); mActiveModeWarden.dump(fd, pw, args); @@ -5604,7 +5704,7 @@ public class WifiServiceImpl extends BaseWifiService { mWifiInjector.getWifiVoipDetector().dump(fd, pw, args); } pw.println(); - mWifiResourceCache.dump(pw); + mResourceCache.dump(pw); } }, TAG + "#dump"); } @@ -5672,21 +5772,23 @@ public class WifiServiceImpl extends BaseWifiService { public void initializeMulticastFiltering() { enforceMulticastChangePermission(); mLog.info("initializeMulticastFiltering uid=%").c(Binder.getCallingUid()).flush(); - mWifiMulticastLockManager.initializeFiltering(); + mWifiMulticastLockManager.startFilteringMulticastPackets(); } @Override public void acquireMulticastLock(IBinder binder, String tag) { enforceMulticastChangePermission(); - mLog.info("acquireMulticastLock uid=% tag=%").c(Binder.getCallingUid()).c(tag).flush(); - mWifiMulticastLockManager.acquireLock(binder, tag); + int uid = Binder.getCallingUid(); + mLog.info("acquireMulticastLock uid=% tag=%").c(uid).c(tag).flush(); + mWifiMulticastLockManager.acquireLock(uid, binder, tag); } @Override - public void releaseMulticastLock(String tag) { + public void releaseMulticastLock(IBinder binder, String tag) { enforceMulticastChangePermission(); - mLog.info("releaseMulticastLock uid=% tag=%").c(Binder.getCallingUid()).c(tag).flush(); - mWifiMulticastLockManager.releaseLock(tag); + int uid = Binder.getCallingUid(); + mLog.info("releaseMulticastLock uid=% tag=%").c(uid).c(tag).flush(); + mWifiMulticastLockManager.releaseLock(uid, binder, tag); } @Override @@ -5739,7 +5841,7 @@ public class WifiServiceImpl extends BaseWifiService { } private void updateVerboseLoggingEnabled() { - final int verboseAlwaysOnLevel = mContext.getResources().getInteger( + final int verboseAlwaysOnLevel = mResourceCache.getInteger( R.integer.config_wifiVerboseLoggingAlwaysOnLevel); mVerboseLoggingEnabled = WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED == mVerboseLoggingLevel || WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY == mVerboseLoggingLevel @@ -6163,7 +6265,7 @@ public class WifiServiceImpl extends BaseWifiService { TAG + "#unregisterTrafficStateCallback"); } - private long getSupportedFeaturesInternal() { + private BitSet getSupportedFeaturesInternal() { return mActiveModeWarden.getSupportedFeatureSet(); } @@ -6227,7 +6329,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public int addNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, + ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, String callingFeatureId) { if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; @@ -6260,12 +6362,15 @@ public class WifiServiceImpl extends BaseWifiService { if (mVerboseLoggingEnabled) { mLog.info("addNetworkSuggestions uid=%").c(callingUid).flush(); } + if (networkSuggestions == null) { + return STATUS_NETWORK_SUGGESTIONS_SUCCESS; + } int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.add( - networkSuggestions, callingUid, callingPackageName, callingFeatureId), + networkSuggestions.getList(), callingUid, callingPackageName, callingFeatureId), WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, TAG + "#addNetworkSuggestions"); - if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { + if (success != STATUS_NETWORK_SUGGESTIONS_SUCCESS) { Log.e(TAG, "Failed to add network suggestions"); } return success; @@ -6281,7 +6386,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public int removeNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, + ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, @WifiManager.ActionAfterRemovingSuggestion int action) { if (enforceChangePermission(callingPackageName) != MODE_ALLOWED) { return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; @@ -6295,11 +6400,14 @@ public class WifiServiceImpl extends BaseWifiService { } int callingUid = Binder.getCallingUid(); + if (networkSuggestions == null) { + return STATUS_NETWORK_SUGGESTIONS_SUCCESS; + } int success = mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.remove( - networkSuggestions, callingUid, callingPackageName, + networkSuggestions.getList(), callingUid, callingPackageName, action), WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, TAG + "#removeNetworkSuggestions"); - if (success != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { + if (success != STATUS_NETWORK_SUGGESTIONS_SUCCESS) { Log.e(TAG, "Failed to remove network suggestions"); } return success; @@ -6311,16 +6419,17 @@ public class WifiServiceImpl extends BaseWifiService { * @return a list of network suggestions suggested by this app */ @Override - public List<WifiNetworkSuggestion> getNetworkSuggestions(String callingPackageName) { + public ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions( + String callingPackageName) { int callingUid = Binder.getCallingUid(); mAppOps.checkPackage(callingUid, callingPackageName); enforceAccessPermission(); if (mVerboseLoggingEnabled) { mLog.info("getNetworkSuggestionList uid=%").c(Binder.getCallingUid()).flush(); } - return mWifiThreadRunner.call(() -> + return new ParceledListSlice<>(mWifiThreadRunner.call(() -> mWifiNetworkSuggestionsManager.get(callingPackageName, callingUid), - Collections.emptyList(), TAG + "#getNetworkSuggestions"); + Collections.emptyList(), TAG + "#getNetworkSuggestions")); } /** @@ -6952,6 +7061,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#registerScanResultsCallback(WifiManager.ScanResultsCallback)} */ + @Override public void registerScanResultsCallback(@NonNull IScanResultsCallback callback) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); @@ -7555,7 +7665,8 @@ public class WifiServiceImpl extends BaseWifiService { true, TAG + " getUsableChannels"); } if (mVerboseLoggingEnabled) { - mLog.info("getUsableChannels uid=%").c(Binder.getCallingUid()).flush(); + mLog.info("getUsableChannels uid=% band=% mode=% filter=%").c(Binder.getCallingUid()).c( + band).c(mode).c(filter).flush(); } if (!isValidBandForGetUsableChannels(band)) { throw new IllegalArgumentException("Unsupported band: " + band); @@ -7650,21 +7761,20 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public boolean isPnoSupported() { + boolean featureSetSupportsPno = isFeatureSupported(WifiManager.WIFI_FEATURE_PNO); return mWifiGlobals.isSwPnoEnabled() - || (mWifiGlobals.isBackgroundScanSupported() - && (getSupportedFeatures() & WifiManager.WIFI_FEATURE_PNO) != 0); + || (mWifiGlobals.isBackgroundScanSupported() && featureSetSupportsPno); } private boolean isAggressiveRoamingModeSupported() { - return (getSupportedFeatures() & WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT) - != 0; + return isFeatureSupported(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); } /** * @return true if this device supports Trust On First Use */ private boolean isTrustOnFirstUseSupported() { - return (getSupportedFeatures() & WIFI_FEATURE_TRUST_ON_FIRST_USE) != 0; + return isFeatureSupported(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); } /** @@ -7761,11 +7871,11 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override @RequiresApi(Build.VERSION_CODES.TIRAMISU) - public void notifyWifiSsidPolicyChanged(int policyType, List<WifiSsid> ssids) { + public void notifyWifiSsidPolicyChanged(int policyType, ParceledListSlice<WifiSsid> ssids) { if (!SdkLevel.isAtLeastT()) { throw new UnsupportedOperationException(); } - if (ssids == null) { + if (ssids == null || ssids.getList() == null) { throw new IllegalArgumentException("SSID list may not be null"); } if (!checkManageDeviceAdminsPermission(Binder.getCallingPid(), Binder.getCallingUid())) { @@ -7782,13 +7892,13 @@ public class WifiServiceImpl extends BaseWifiService { WifiSsid ssid = wifiInfo.getWifiSsid(); if (policyType == WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST - && !ssids.contains(ssid)) { + && !ssids.getList().contains(ssid)) { cmm.disconnect(); mLog.info("disconnect admin restricted network").flush(); continue; } if (policyType == WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST - && ssids.contains(ssid)) { + && ssids.getList().contains(ssid)) { cmm.disconnect(); mLog.info("disconnect admin restricted network").flush(); continue; @@ -7839,14 +7949,16 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public void addCustomDhcpOptions(@NonNull WifiSsid ssid, @NonNull byte[] oui, - @NonNull List<DhcpOption> options) { + @NonNull ParceledListSlice<DhcpOption> options) { enforceAnyPermissionOf(android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.OVERRIDE_WIFI_CONFIG); if (mVerboseLoggingEnabled) { Log.v(TAG, "addCustomDhcpOptions: ssid=" + ssid + ", oui=" + Arrays.toString(oui) + ", options=" + options); } - mWifiThreadRunner.post(() -> mWifiConfigManager.addCustomDhcpOptions(ssid, oui, options), + List<DhcpOption> dhcpOptionList = options == null ? null : options.getList(); + mWifiThreadRunner.post(() -> mWifiConfigManager.addCustomDhcpOptions(ssid, oui, + dhcpOptionList), TAG + "#addCustomDhcpOptions"); } @@ -7869,7 +7981,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public String[] getOemPrivilegedWifiAdminPackages() { - return mContext.getResources() + return mResourceCache .getStringArray(R.array.config_oemPrivilegedWifiAdminPackages); } @@ -7951,7 +8063,7 @@ public class WifiServiceImpl extends BaseWifiService { } @Override public int getMaxNumberOfChannelsPerRequest() { - return mContext.getResources() + return mResourceCache .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels); } @@ -7999,7 +8111,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) - public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, + public void addQosPolicies(@NonNull ParceledListSlice<QosPolicyParams> policyParamsList, @NonNull IBinder binder, @NonNull String packageName, @NonNull IListListener listener) { if (!SdkLevel.isAtLeastU()) { @@ -8014,33 +8126,39 @@ public class WifiServiceImpl extends BaseWifiService { } Objects.requireNonNull(policyParamsList, "policyParamsList cannot be null"); + Objects.requireNonNull(policyParamsList.getList(), + "policyParamsList contents cannot be null"); Objects.requireNonNull(binder, "binder cannot be null"); Objects.requireNonNull(listener, "listener cannot be null"); + if (policyParamsList.getList().size() == 0 + || policyParamsList.getList().size() + > WifiManager.getMaxNumberOfPoliciesPerQosRequest() + || !policyIdsAreUnique(policyParamsList.getList()) + || !policiesHaveSameDirection(policyParamsList.getList())) { + throw new IllegalArgumentException("policyParamsList is invalid"); + } + if (!mApplicationQosPolicyRequestHandler.isFeatureEnabled()) { Log.i(TAG, "addQosPolicies is disabled on this device"); - rejectAllQosPolicies(policyParamsList, listener); + rejectAllQosPolicies(policyParamsList.getList(), listener); return; } - if (policyParamsList.size() == 0 - || policyParamsList.size() > WifiManager.getMaxNumberOfPoliciesPerQosRequest() - || !policyIdsAreUnique(policyParamsList) - || !policiesHaveSameDirection(policyParamsList)) { - throw new IllegalArgumentException("policyParamsList is invalid"); - } + if (!(SdkLevel.isAtLeastV() && isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX)) - && policyParamsList.get(0).getDirection() == QosPolicyParams.DIRECTION_UPLINK) { + && policyParamsList.getList().get(0).getDirection() + == QosPolicyParams.DIRECTION_UPLINK) { Log.e(TAG, "Uplink QoS policies are only supported on devices with SDK >= V" + " and 11ax support"); - rejectAllQosPolicies(policyParamsList, listener); + rejectAllQosPolicies(policyParamsList.getList(), listener); return; } mWifiThreadRunner.post(() -> { mApplicationQosPolicyRequestHandler.queueAddRequest( - policyParamsList, listener, binder, uid); + policyParamsList.getList(), listener, binder, uid); }, TAG + "#addQosPolicies"); } @@ -8220,6 +8338,7 @@ public class WifiServiceImpl extends BaseWifiService { * See {@link WifiManager#removeWifiLowLatencyLockListener( * WifiManager.WifiLowLatencyLockListener)} */ + @Override public void removeWifiLowLatencyLockListener(IWifiLowLatencyLockListener listener) { if (listener == null) { throw new IllegalArgumentException(); @@ -8249,6 +8368,7 @@ public class WifiServiceImpl extends BaseWifiService { * See {@link WifiManager#getMaxMloAssociationLinkCount(Executor, Consumer)} */ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) + @Override public void getMaxMloAssociationLinkCount(@NonNull IIntegerListener listener, Bundle extras) { // SDK check. if (!SdkLevel.isAtLeastU()) { @@ -8280,6 +8400,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#getMaxMloStrLinkCount(Executor, Consumer)} */ + @Override @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public void getMaxMloStrLinkCount(@NonNull IIntegerListener listener, Bundle extras) { // SDK check. @@ -8312,6 +8433,7 @@ public class WifiServiceImpl extends BaseWifiService { /** * See {@link WifiManager#getSupportedSimultaneousBandCombinations(Executor, Consumer)}. */ + @Override public void getSupportedSimultaneousBandCombinations(@NonNull IWifiBandsListener listener, Bundle extras) { // SDK check. @@ -8538,7 +8660,7 @@ public class WifiServiceImpl extends BaseWifiService { if (!SdkLevel.isAtLeastV()) { throw new UnsupportedOperationException("SDK level too old"); } - if (!isAggressiveRoamingModeSupported()) { + if (!isAggressiveRoamingModeSupported() && roamingMode == ROAMING_MODE_AGGRESSIVE) { throw new UnsupportedOperationException("Aggressive roaming mode not supported"); } Objects.requireNonNull(ssid, "ssid cannot be null"); @@ -8573,9 +8695,6 @@ public class WifiServiceImpl extends BaseWifiService { if (!SdkLevel.isAtLeastV()) { throw new UnsupportedOperationException("SDK level too old"); } - if (!isAggressiveRoamingModeSupported()) { - throw new UnsupportedOperationException("Aggressive roaming mode not supported"); - } Objects.requireNonNull(ssid, "ssid cannot be null"); Objects.requireNonNull(packageName, "packageName cannot be null"); @@ -8605,9 +8724,6 @@ public class WifiServiceImpl extends BaseWifiService { if (!SdkLevel.isAtLeastV()) { throw new UnsupportedOperationException("SDK level too old"); } - if (!isAggressiveRoamingModeSupported()) { - throw new UnsupportedOperationException("Aggressive roaming mode not supported"); - } Objects.requireNonNull(packageName, "packageName cannot be null"); Objects.requireNonNull(listener, "listener cannot be null"); @@ -8768,4 +8884,90 @@ public class WifiServiceImpl extends BaseWifiService { } }, TAG + "#queryD2dAllowedWhenInfraStaDisabled"); } + + /** + * See {@link WifiManager#setAutojoinDisallowedSecurityTypes(int)} + * @param restrictions The autojoin restriction security types to be set. + * @throws SecurityException if the caller does not have permission. + * @throws IllegalArgumentException if the arguments are null or invalid + */ + @Override + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + public void setAutojoinDisallowedSecurityTypes(int restrictions, @NonNull Bundle extras) { + // SDK check. + if (!SdkLevel.isAtLeastT()) { + throw new UnsupportedOperationException("SDK level too old"); + } + // Check null argument + if (extras == null) { + throw new IllegalArgumentException("extras cannot be null"); + } + // Check invalid argument + if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OPEN)) == 0 + && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_OWE)) != 0) { + throw new IllegalArgumentException("Restricting OWE but not OPEN is not allowed"); + } + if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_PSK)) == 0 + && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_SAE)) != 0) { + throw new IllegalArgumentException("Restricting SAE but not PSK is not allowed"); + } + if ((restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP)) == 0 + && (restrictions & (0x1 << WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE)) != 0) { + throw new IllegalArgumentException( + "Restricting EAP_WPA3_ENTERPRISE but not EAP is not allowed"); + } + // Permission check. + int uid = Binder.getCallingUid(); + if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) + && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { + throw new SecurityException( + "Uid=" + uid + " is not allowed to set AutoJoinRestrictionSecurityTypes"); + } + if (mVerboseLoggingEnabled) { + mLog.info("setAutojoinDisallowedSecurityTypes uid=% Package Name=% restrictions=%") + .c(uid).c(getPackageName(extras)).c(restrictions).flush(); + } + mWifiThreadRunner.post(() -> { + mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(restrictions); + }, TAG + "#setAutojoinDisallowedSecurityTypes"); + } + + /** + * See {@link WifiManager#getAutojoinDisallowedSecurityTypes(Executor, Consumer)} + */ + @Override + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + public void getAutojoinDisallowedSecurityTypes(@NonNull IIntegerListener listener, + @NonNull Bundle extras) { + // SDK check. + if (!SdkLevel.isAtLeastT()) { + throw new UnsupportedOperationException("SDK level too old"); + } + // Argument check + if (listener == null) { + throw new IllegalArgumentException("listener cannot be null"); + } + if (extras == null) { + throw new IllegalArgumentException("extras cannot be null"); + } + // Permission check. + int uid = Binder.getCallingUid(); + if (!mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(uid) + && !mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) { + throw new SecurityException( + "Uid=" + uid + " is not allowed to get AutoJoinRestrictionSecurityTypes"); + } + if (mVerboseLoggingEnabled) { + mLog.info("getAutojoinDisallowedSecurityTypes: Uid=% Package Name=%").c( + Binder.getCallingUid()).c(getPackageName(extras)).flush(); + } + + mWifiThreadRunner.post(() -> { + try { + listener.onResult(mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes()); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } + }, TAG + "#getAutojoinDisallowedSecurityTypes"); + } } diff --git a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java index 17af39fdd8..a5ba58dd13 100644 --- a/service/java/com/android/server/wifi/WifiSettingsConfigStore.java +++ b/service/java/com/android/server/wifi/WifiSettingsConfigStore.java @@ -136,12 +136,19 @@ public class WifiSettingsConfigStore { new Key<>("wifi_default_country_code", WifiCountryCode.getOemDefaultCountryCode()); /** - * Store the supported features retrieved from WiFi HAL and Supplicant HAL + * Store the supported features retrieved from WiFi HAL and Supplicant HAL. Note that this + * value is deprecated and is replaced by {@link #WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES} */ public static final Key<Long> WIFI_NATIVE_SUPPORTED_FEATURES = new Key<>("wifi_native_supported_features", 0L); /** + * Store the extended supported features retrieved from WiFi HAL and Supplicant HAL + */ + public static final Key<long[]> WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES = + new Key<>("wifi_native_extended_supported_features", new long[0]); + + /** * Store the supported features retrieved from WiFi HAL and Supplicant HAL */ public static final Key<Integer> WIFI_NATIVE_SUPPORTED_STA_BANDS = diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java index 8b68e3a2a2..0481cb1fcc 100644 --- a/service/java/com/android/server/wifi/WifiShellCommand.java +++ b/service/java/com/android/server/wifi/WifiShellCommand.java @@ -25,6 +25,9 @@ import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED; import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT; import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_LINGER; import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED; +import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE; +import static android.net.wifi.WifiManager.ROAMING_MODE_NONE; +import static android.net.wifi.WifiManager.ROAMING_MODE_NORMAL; import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_DISABLED; import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY; import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; @@ -517,28 +520,70 @@ public class WifiShellCommand extends BasicShellCommandHandler { + mWifiGlobals.getIpReachabilityDisconnectEnabled()); return 0; case "set-poll-rssi-interval-msecs": - int newPollIntervalMsecs; - try { - newPollIntervalMsecs = Integer.parseInt(getNextArgRequired()); - } catch (NumberFormatException e) { - pw.println( + List<Integer> newPollIntervals = new ArrayList<>(); + while (getRemainingArgsCount() > 0) { + int newPollIntervalMsecs; + try { + newPollIntervalMsecs = Integer.parseInt(getNextArgRequired()); + } catch (NumberFormatException e) { + pw.println( "Invalid argument to 'set-poll-rssi-interval-msecs' " - + "- must be a positive integer"); - return -1; - } + + "- must be a positive integer"); + return -1; + } - if (newPollIntervalMsecs < 1) { - pw.println( + if (newPollIntervalMsecs < 1) { + pw.println( "Invalid argument to 'set-poll-rssi-interval-msecs' " - + "- must be a positive integer"); - return -1; + + "- must be a positive integer"); + return -1; + } + + newPollIntervals.add(newPollIntervalMsecs); } - mWifiGlobals.setPollRssiIntervalMillis(newPollIntervalMsecs); + switch (newPollIntervals.size()) { + case 0: + throw new IllegalArgumentException( + "Need at least one valid rssi polling interval"); + case 1: + mActiveModeWarden.getPrimaryClientModeManager() + .setLinkLayerStatsPollingInterval(newPollIntervals.get(0)); + break; + case 2: + int newShortIntervalMsecs = newPollIntervals.get(0); + int newLongIntervalMsecs = newPollIntervals.get(1); + if (newShortIntervalMsecs >= newLongIntervalMsecs) { + pw.println( + "Invalid argument to 'set-poll-rssi-interval-msecs' " + + "- the long polling interval must be greater " + + "than the short polling interval"); + return -1; + } + mWifiGlobals.setPollRssiShortIntervalMillis(newShortIntervalMsecs); + mWifiGlobals.setPollRssiLongIntervalMillis(newLongIntervalMsecs); + mWifiGlobals.setPollRssiIntervalMillis(newShortIntervalMsecs); + mActiveModeWarden.getPrimaryClientModeManager() + .setLinkLayerStatsPollingInterval(0); + break; + default: + pw.println("Too many arguments, need at most two valid rssi polling " + + "intervals"); + return -1; + } return 0; case "get-poll-rssi-interval-msecs": - pw.println("WifiGlobals.getPollRssiIntervalMillis() = " + pw.println("Current interval between RSSI polls (milliseconds) = " + mWifiGlobals.getPollRssiIntervalMillis()); + if (mWifiGlobals.isAdjustPollRssiIntervalEnabled() + && mDeviceConfig.isAdjustPollRssiIntervalEnabled() + && !mWifiGlobals.isPollRssiIntervalOverridden()) { + pw.println("Auto adjustment of poll rssi is enabled"); + pw.println("Regular (short) interval between RSSI polls (milliseconds) = " + + mWifiGlobals.getPollRssiShortIntervalMillis()); + pw.println("Long interval between RSSI polls (milliseconds) = " + + mWifiGlobals.getPollRssiLongIntervalMillis()); + } return 0; case "force-hi-perf-mode": { boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); @@ -819,6 +864,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { mWifiService.clearExternalPnoScanRequest(); return 0; } + case "set-pno-scan": { + boolean enabled = getNextArgRequiredTrueOrFalse("enabled", "disabled"); + mWifiService.setPnoScanEnabled(enabled, true /*enablePnoScanAfterWifiToggle*/, + mContext.getOpPackageName()); + return 0; + } case "start-lohs": { CountDownLatch countDownLatch = new CountDownLatch(2); SoftApConfiguration config = buildSoftApConfiguration(pw); @@ -951,14 +1002,10 @@ public class WifiShellCommand extends BasicShellCommandHandler { if (ApConfigUtil.isWpa3SaeSupported(mContext)) { pw.println("wifi_softap_wpa3_sae_supported"); } - if ((mWifiService.getSupportedFeatures() - & WifiManager.WIFI_FEATURE_BRIDGED_AP) - == WifiManager.WIFI_FEATURE_BRIDGED_AP) { + if (mWifiService.isFeatureSupported(WifiManager.WIFI_FEATURE_BRIDGED_AP)) { pw.println("wifi_softap_bridged_ap_supported"); } - if ((mWifiService.getSupportedFeatures() - & WifiManager.WIFI_FEATURE_STA_BRIDGED_AP) - == WifiManager.WIFI_FEATURE_STA_BRIDGED_AP) { + if (mWifiService.isFeatureSupported(WifiManager.WIFI_FEATURE_STA_BRIDGED_AP)) { pw.println("wifi_softap_bridged_ap_with_sta_supported"); } return 0; @@ -1123,7 +1170,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { return -1; } int errorCode = mWifiService.addNetworkSuggestions( - Arrays.asList(suggestion), SHELL_PACKAGE_NAME, null); + new ParceledListSlice(List.of(suggestion)), SHELL_PACKAGE_NAME, null); if (errorCode != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { pw.println("Add network suggestion failed with error code: " + errorCode); return -1; @@ -1164,7 +1211,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { actionCode = ACTION_REMOVE_SUGGESTION_LINGER; } List<WifiNetworkSuggestion> suggestions = - mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); + mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME).getList(); WifiNetworkSuggestion suggestion = suggestions.stream() .filter(s -> s.getSsid().equals(ssid)) .findAny() @@ -1174,7 +1221,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { return -1; } mWifiService.removeNetworkSuggestions( - Arrays.asList(suggestion), SHELL_PACKAGE_NAME, actionCode); + new ParceledListSlice<>(List.of(suggestion)), + SHELL_PACKAGE_NAME, actionCode); // untrusted/oem-paid networks need a corresponding NetworkRequest. if (suggestion.isUntrusted() || (SdkLevel.isAtLeastS() @@ -1192,12 +1240,12 @@ public class WifiShellCommand extends BasicShellCommandHandler { } case "remove-all-suggestions": mWifiService.removeNetworkSuggestions( - Collections.emptyList(), SHELL_PACKAGE_NAME, + new ParceledListSlice<>(Collections.emptyList()), SHELL_PACKAGE_NAME, WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT); return 0; case "list-suggestions": { List<WifiNetworkSuggestion> suggestions = - mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME); + mWifiService.getNetworkSuggestions(SHELL_PACKAGE_NAME).getList(); printWifiNetworkSuggestions(pw, suggestions); return 0; } @@ -1210,7 +1258,7 @@ public class WifiShellCommand extends BasicShellCommandHandler { case "list-suggestions-from-app": { String packageName = getNextArgRequired(); List<WifiNetworkSuggestion> suggestions = - mWifiService.getNetworkSuggestions(packageName); + mWifiService.getNetworkSuggestions(packageName).getList(); printWifiNetworkSuggestions(pw, suggestions); return 0; } @@ -2194,6 +2242,38 @@ public class WifiShellCommand extends BasicShellCommandHandler { resourceCache.restoreIntegerValue(overlayName); } } + case "string" -> { + String value; + if (isEnabled) { + value = getNextArgRequired(); + resourceCache.overrideStringValue(overlayName, value); + } else { + resourceCache.restoreStringValue(overlayName); + } + } + case "string-array" -> { + String[] value; + if (isEnabled) { + value = peekRemainingArgs(); + resourceCache.overrideStringArrayValue(overlayName, value); + } else { + resourceCache.restoreStringArrayValue(overlayName); + } + } + case "integer-array" -> { + String[] input; + if (isEnabled) { + input = peekRemainingArgs(); + int[] value = new int[input.length]; + for (int i = 0; i < input.length; i++) { + value[i] = Integer.parseInt(input[i]); + } + + resourceCache.overrideIntArrayValue(overlayName, value); + } else { + resourceCache.restoreIntArrayValue(overlayName); + } + } default -> { pw.print("require a valid type of the overlay"); return -1; @@ -2204,6 +2284,32 @@ public class WifiShellCommand extends BasicShellCommandHandler { case "get-overlay-config-values": mContext.getResourceCache().dump(pw); return 0; + case "set-ssid-roaming-mode": + String ssid = getNextArgRequired(); + String roamingMode = getNextArgRequired(); + String option = getNextOption(); + + WifiSsid wifiSsid; + if (option != null && option.equals("-x")) { + wifiSsid = WifiSsid.fromString(ssid); + } else { + wifiSsid = WifiSsid.fromString("\"" + ssid + "\""); + } + + int mode; + if (roamingMode.equals("none")) { + mode = ROAMING_MODE_NONE; + } else if (roamingMode.equals("normal")) { + mode = ROAMING_MODE_NORMAL; + } else if (roamingMode.equals("aggressive")) { + mode = ROAMING_MODE_AGGRESSIVE; + } else { + pw.println("Unsupported roaming mode"); + return -1; + } + + mWifiService.setPerSsidRoamingMode(wifiSsid, mode, SHELL_PACKAGE_NAME); + return 0; default: return handleDefaultCommands(cmd); } @@ -2999,10 +3105,11 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" '31' - band 2.4, 5, 6 and 60 GHz with DFS channels"); pw.println(" get-cached-scan-data"); pw.println(" Gets scan data cached by the firmware"); - pw.println(" force-overlay-config-value bool|integer <overlayName> enabled|disabled" - + "<configValue>"); + pw.println(" force-overlay-config-value bool|integer|string|integer-array|string-array " + + "<overlayName> enabled|disabled <configValue>"); pw.println(" Force overlay to a specified value."); - pw.println(" bool|integer - specified the type of the overlay"); + pw.println(" bool|integer|string|integer-array|string-array - specified the type of the " + + "overlay"); pw.println(" <overlayName> - name of the overlay whose value is overridden."); pw.println(" enabled|disabled: enable the override or disable it and revert to using " + "the built-in value."); @@ -3019,8 +3126,15 @@ public class WifiShellCommand extends BasicShellCommandHandler { } private void onHelpPrivileged(PrintWriter pw) { - pw.println(" set-poll-rssi-interval-msecs <int>"); - pw.println(" Sets the interval between RSSI polls to <int> milliseconds."); + pw.println(" set-poll-rssi-interval-msecs <int> [<int>]"); + pw.println(" Sets the interval between RSSI polls to the specified value(s), in " + + "milliseconds."); + pw.println(" When only one value is specified, set the interval to that value. " + + "When two values are specified, set the regular (short) interval to the first " + + "value, and set the long interval to the second value. Note that the " + + "enabling/disabling of auto adjustment between the two intervals is handled by " + + "the respective flags. If the auto adjustment is disabled, it is equivalent to " + + "only specifying the first value, and then setting the interval to that value"); pw.println(" get-poll-rssi-interval-msecs"); pw.println(" Gets current interval between RSSI polls, in milliseconds."); pw.println(" force-hi-perf-mode enabled|disabled"); @@ -3236,6 +3350,8 @@ public class WifiShellCommand extends BasicShellCommandHandler { pw.println(" Requests to include a non-quoted UTF-8 SSID in PNO scans"); pw.println(" clear-pno-request"); pw.println(" Clear the PNO scan request."); + pw.println(" set-pno-scan enabled|disabled"); + pw.println(" Set the PNO scan enabled or disabled."); pw.println(" start-dpp-enrollee-responder [-i <info>] [-c <curve>]"); pw.println(" Start DPP Enrollee responder mode."); pw.println(" -i - Device Info to be used in DPP Bootstrapping URI"); @@ -3285,6 +3401,10 @@ public class WifiShellCommand extends BasicShellCommandHandler { + "option provided or no arguments provided after the -r option, then set the " + "request properties to none in the request."); pw.println(" Example: configure-afc-server https://testURL -r key1 value1 key2 value2"); + pw.println(" set-ssid-roaming-mode <ssid> none|normal|aggressive [-x]"); + pw.println(" Sets the roaming mode for the given SSID."); + pw.println(" -x - Specifies the SSID as hex digits instead of plain text."); + pw.println(" Example: set-ssid-roaming-mode test_ssid aggressive"); } @Override diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index d8714ff6e3..13b659f36a 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -56,6 +56,7 @@ import com.google.errorprone.annotations.CompileTimeConstant; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -378,10 +379,10 @@ public class WifiVendorHal { } } - private long getNecessaryCapabilitiesForSoftApMode(@SoftApConfiguration.BandType int band) { - long caps = HalDeviceManager.CHIP_CAPABILITY_ANY; + private BitSet getNecessaryCapabilitiesForSoftApMode(@SoftApConfiguration.BandType int band) { + BitSet caps = new BitSet(); if ((band & SoftApConfiguration.BAND_60GHZ) != 0) { - caps |= WifiManager.WIFI_FEATURE_INFRA_60G; + caps.set(WifiManager.WIFI_FEATURE_INFRA_60G); } return caps; } @@ -788,15 +789,15 @@ public class WifiVendorHal { * * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ - private long getSupportedFeatureSetFromPackageManager() { - long featureSet = 0; + private BitSet getSupportedFeatureSetFromPackageManager() { + BitSet featureSet = new BitSet(); final PackageManager pm = sContext.getPackageManager(); for (Pair pair: sSystemFeatureCapabilityTranslation) { if (pm.hasSystemFeature((String) pair.second)) { - featureSet |= (long) pair.first; + featureSet.set((int) pair.first); } } - enter("System feature set: %").c(featureSet).flush(); + enter("System feature set: %").c(featureSet.toString()).flush(); return featureSet; } @@ -873,50 +874,50 @@ public class WifiVendorHal { * The result may differ depending on the mode (STA or AP) * * @param ifaceName Name of the interface. - * @return bitmask defined by WifiManager.WIFI_FEATURE_* + * @return BitSet defined by WifiManager.WIFI_FEATURE_* */ - public long getSupportedFeatureSet(@NonNull String ifaceName) { - long featureSet = 0L; + public BitSet getSupportedFeatureSet(@NonNull String ifaceName) { + BitSet featureSet = new BitSet(); if (!mHalDeviceManager.isStarted() || !mHalDeviceManager.isSupported()) { return getSupportedFeatureSetFromPackageManager(); } synchronized (sLock) { if (mWifiChip != null) { - WifiChip.Response<Long> capsResp = mWifiChip.getCapabilitiesAfterIfacesExist(); + WifiChip.Response<BitSet> capsResp = mWifiChip.getCapabilitiesAfterIfacesExist(); if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS) { featureSet = capsResp.getValue(); } else if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION) { - return 0; + return new BitSet(); } } WifiStaIface iface = getStaIface(ifaceName); if (iface != null) { - featureSet |= iface.getCapabilities(); + featureSet.or(iface.getCapabilities()); if (mHalDeviceManager.is24g5gDbsSupported(iface) || mHalDeviceManager.is5g6gDbsSupported(iface)) { - featureSet |= WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS; + featureSet.set(WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); } } } if (mWifiGlobals.isWpa3SaeH2eSupported()) { - featureSet |= WifiManager.WIFI_FEATURE_SAE_H2E; + featureSet.set(WifiManager.WIFI_FEATURE_SAE_H2E); } Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_STA)) { - featureSet |= WifiManager.WIFI_FEATURE_INFRA; + featureSet.set(WifiManager.WIFI_FEATURE_INFRA); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_AP)) { - featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; + featureSet.set(WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_P2P)) { - featureSet |= WifiManager.WIFI_FEATURE_P2P; + featureSet.set(WifiManager.WIFI_FEATURE_P2P); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_NAN)) { - featureSet |= WifiManager.WIFI_FEATURE_AWARE; + featureSet.set(WifiManager.WIFI_FEATURE_AWARE); } return featureSet; diff --git a/service/java/com/android/server/wifi/WifiVoipDetector.java b/service/java/com/android/server/wifi/WifiVoipDetector.java index 5754bc3ef8..e8c274b410 100644 --- a/service/java/com/android/server/wifi/WifiVoipDetector.java +++ b/service/java/com/android/server/wifi/WifiVoipDetector.java @@ -181,6 +181,7 @@ public class WifiVoipDetector { log = "Failed to set Voip Mode to " + newMode + " (maybe not supported?)"; } else { mCurrentMode = newMode; + mWifiInjector.getWifiMetrics().setVoipMode(mCurrentMode); } mLocalLog.log(log); if (mVerboseLoggingEnabled) { diff --git a/service/java/com/android/server/wifi/aware/PairingConfigManager.java b/service/java/com/android/server/wifi/aware/PairingConfigManager.java index c0ce760b6a..59061d2439 100644 --- a/service/java/com/android/server/wifi/aware/PairingConfigManager.java +++ b/service/java/com/android/server/wifi/aware/PairingConfigManager.java @@ -42,8 +42,12 @@ public class PairingConfigManager { private static final String TAG = "AwarePairingManager"; - private static final int NIK_SIZE_IN_BYTE = 16; - private static final int TAG_SIZE_IN_BYTE = 8; + // NIK size + public static final int NIK_SIZE_IN_BYTE = 16; + // TAG size + public static final int TAG_SIZE_IN_BYTE = 8; + // NIR byte array + public static final byte[] NIR = {'N', 'I', 'R'}; /** * Store the NPKSA from the NAN Pairing confirmation @@ -76,7 +80,6 @@ public class PairingConfigManager { private byte[] createRandomNik() { long first, second; - Random mRandom = new SecureRandom(); first = mRandom.nextLong(); second = mRandom.nextLong(); @@ -119,14 +122,13 @@ public class PairingConfigManager { private boolean checkMatchAlias(String alias, byte[] nonce, byte[] tag, byte[] mac) { byte[] nik = mAliasToNikMap.get(alias); - byte[] nir = {'N', 'I', 'R'}; if (nik == null) return false; SecretKeySpec spec = new SecretKeySpec(nik, "HmacSHA256"); try { Mac hash = Mac.getInstance("HmacSHA256"); hash.init(spec); - hash.update(nir); + hash.update(NIR); hash.update(mac); hash.update(nonce); byte[] message = Arrays.copyOf(hash.doFinal(), TAG_SIZE_IN_BYTE); @@ -155,11 +157,8 @@ public class PairingConfigManager { if (info == null) { return; } - Set<String> pairedDevices = mPerAppPairedAliasMap.get(packageName); - if (pairedDevices == null) { - pairedDevices = new HashSet<>(); - mPerAppPairedAliasMap.put(packageName, pairedDevices); - } + Set<String> pairedDevices = mPerAppPairedAliasMap.computeIfAbsent(packageName, + k -> new HashSet<>()); pairedDevices.add(alias); mAliasToNikMap.put(alias, info.mPeerNik); mAliasToSecurityInfoMap.put(alias, info); diff --git a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java index 468b8b84b8..a44d90a76e 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareServiceImpl.java @@ -43,7 +43,6 @@ import android.net.wifi.aware.SubscribeConfig; import android.os.Binder; import android.os.Build; import android.os.Bundle; -import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -89,7 +88,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { private WifiAwareNativeApi mWifiAwareNativeApi; private WifiAwareNativeCallback mWifiAwareNativeCallback; private WifiAwareShellCommand mShellCommand; - private Handler mHandler; + private RunnerHandler mHandler; private final Object mLock = new Object(); private final SparseArray<IBinder.DeathRecipient> mDeathRecipientsByClientId = @@ -160,6 +159,7 @@ public class WifiAwareServiceImpl extends IWifiAwareManager.Stub { mWifiAwareNativeManager.enableVerboseLogging(mVerboseLoggingEnabled, mVerboseLoggingEnabled); mWifiAwareNativeApi.enableVerboseLogging(mVerboseLoggingEnabled, vDbg); + mHandler.enableVerboseLogging(mVerboseLoggingEnabled); } /** diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java index a4fd8ad693..971e1e82db 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java @@ -154,6 +154,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe private static final String TAG = "WifiAwareStateManager"; private boolean mVdbg = false; // STOPSHIP if true - for detailed state machine private boolean mVerboseLoggingEnabled = false; + private static final short NUM_LOG_RECS = 256; + private static final short NUM_LOG_RECS_VERBOSE = 1024; @VisibleForTesting public static final String HAL_COMMAND_TIMEOUT_TAG = TAG + " HAL Command Timeout"; @@ -320,6 +322,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe private static final String MESSAGE_RANGING_INDICATION = "ranging_indication"; private static final String MESSAGE_RANGE_MM = "range_mm"; private static final String MESSAGE_BUNDLE_KEY_NDP_IDS = "ndp_ids"; + private static final String MESSAGE_BUNDLE_KEY_NDP_ID = "ndp_id"; private static final String MESSAGE_BUNDLE_KEY_APP_INFO = "app_info"; private static final String MESSAGE_BUNDLE_KEY_ACCEPT_STATE = "accept_state"; private static final String MESSAGE_BUNDLE_KEY_NONCE = "nonce"; @@ -457,8 +460,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean vDbg) { mVerboseLoggingEnabled = verboseEnabled; mDataPathMgr.enableVerboseLogging(verboseEnabled, vDbg); - mSm.setDbg(halVerboseLogging); mVdbg = vDbg; + mSm.setLogRecSize(verboseEnabled ? NUM_LOG_RECS_VERBOSE : NUM_LOG_RECS); } /** @@ -718,16 +721,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } if (action.equals(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)) { - if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0) { - if (mPowerManager.isDeviceIdleMode() - && !isAnyCallerIgnoringBatteryOptimizations()) { - disableUsage(false); - } else { - enableUsage(); - } - } else { - reconfigure(); - } + reconfigure(); } } }, @@ -737,7 +731,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe intentFilter = new IntentFilter(); intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION); - mContext.registerReceiver( + mContext.registerReceiverForAllUsers( new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1450,13 +1444,6 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe * only happens when a connection is created. */ public void enableUsage() { - if (mSettableParameters.get(PARAM_ON_IDLE_DISABLE_AWARE) != 0 - && mPowerManager.isDeviceIdleMode()) { - if (mVerboseLoggingEnabled) { - Log.d(TAG, "enableUsage(): while device is in IDLE mode - ignoring"); - } - return; - } if (!SdkLevel.isAtLeastT() && !mWifiPermissionsUtil.isLocationModeEnabled()) { if (mVerboseLoggingEnabled) { Log.d(TAG, "enableUsage(): while location is disabled - ignoring"); @@ -1545,6 +1532,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe boolean isOutOfBand, byte[] appInfo) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); msg.arg1 = COMMAND_TYPE_INITIATE_DATA_PATH_SETUP; + msg.arg2 = networkSpecifier.clientId; msg.obj = networkSpecifier; msg.getData().putInt(MESSAGE_BUNDLE_KEY_PEER_ID, peerId); msg.getData().putInt(MESSAGE_BUNDLE_KEY_CHANNEL_REQ_TYPE, channelRequestType); @@ -1564,8 +1552,11 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe WifiAwareNetworkSpecifier networkSpecifier) { Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND); msg.arg1 = COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST; - msg.arg2 = ndpId; + if (networkSpecifier != null) { + msg.arg2 = networkSpecifier.clientId; + } msg.obj = networkSpecifier; + msg.getData().putInt(MESSAGE_BUNDLE_KEY_NDP_ID, ndpId); msg.getData().putBoolean(MESSAGE_BUNDLE_KEY_ACCEPT_STATE, accept); msg.getData().putString(MESSAGE_BUNDLE_KEY_INTERFACE_NAME, interfaceName); msg.getData().putByteArray(MESSAGE_BUNDLE_KEY_APP_INFO, appInfo); @@ -2248,6 +2239,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe /* --> */ addState(mWaitForResponseState, mDefaultState); setInitialState(mWaitState); + setLogRecSize(NUM_LOG_RECS); } @Override @@ -2372,36 +2364,11 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe case MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT -> "MESSAGE_TYPE_BOOTSTRAPPING_TIMEOUT"; default -> { Log.e(TAG, "unknown message what: " + what); - yield "what:" + what; + yield "<unknown>"; } }; } - private String messageToString(Message msg) { - StringBuilder sb = new StringBuilder(); - - String s = getWhatToString(msg.what); - if (s == null) { - s = "<unknown>"; - } - sb.append(s).append("/"); - - if (msg.what == MESSAGE_TYPE_NOTIFICATION || msg.what == MESSAGE_TYPE_COMMAND - || msg.what == MESSAGE_TYPE_RESPONSE) { - s = getWhatToString(msg.arg1); - if (s == null) { - s = "<unknown>"; - } - sb.append(s); - } - - if (msg.what == MESSAGE_TYPE_RESPONSE || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { - sb.append(" (Transaction ID=").append(msg.arg2).append(")"); - } - - return sb.toString(); - } - public void onAwareDownCleanupSendQueueState() { mSendQueueBlocked = false; mHostQueuedSendMessages.clear(); @@ -2493,6 +2460,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe @Override public void enterImpl() { + mCurrentCommand = null; + mCurrentTransactionId = TRANSACTION_ID_IGNORE; } @Override @@ -2681,6 +2650,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe if (reason != NanStatusCode.SUCCESS) { sendAwareStateChangedBroadcast(false); } + releaseAwareInterface(); break; } case NOTIFICATION_TYPE_ON_MESSAGE_SEND_SUCCESS: { @@ -3182,7 +3152,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe case COMMAND_TYPE_RESPOND_TO_DATA_PATH_SETUP_REQUEST: { Bundle data = msg.getData(); - int ndpId = msg.arg2; + int ndpId = data.getInt(MESSAGE_BUNDLE_KEY_NDP_ID); WifiAwareNetworkSpecifier specifier = (WifiAwareNetworkSpecifier) msg.obj; boolean accept = data.getBoolean(MESSAGE_BUNDLE_KEY_ACCEPT_STATE); @@ -3384,7 +3354,7 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe msg.getData().getBoolean(MESSAGE_BUNDLE_KEY_SUCCESS_FLAG), reason); if (success) { - int ndpId = mCurrentCommand.arg2; + int ndpId = mCurrentCommand.getData().getInt(MESSAGE_BUNDLE_KEY_NDP_ID); WakeupMessage timeout = new WakeupMessage(mContext, getHandler(), HAL_DATA_PATH_CONFIRM_TIMEOUT_TAG, MESSAGE_TYPE_DATA_PATH_TIMEOUT, ndpId); @@ -3491,8 +3461,6 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe } default: Log.wtf(TAG, "processResponse: this isn't a RESPONSE -- msg=" + msg); - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; return; } if (msg.arg1 != RESPONSE_TYPE_ON_CONFIG_SUCCESS @@ -3500,9 +3468,6 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe // Config response handle separately to identify it's connect or reconfigure recordHalApiCall(mCurrentCommand.arg1, reason, mStartTime); } - - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; } private void processTimeout(Message msg) { @@ -3634,9 +3599,6 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe Log.wtf(TAG, "processTimeout: this isn't a COMMAND -- msg=" + msg); /* fall-through */ } - - mCurrentCommand = null; - mCurrentTransactionId = TRANSACTION_ID_IGNORE; } private void updateSendMessageTimeout() { @@ -3722,11 +3684,44 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe @Override protected String getLogRecString(Message msg) { - StringBuilder sb = new StringBuilder(messageToString(msg)); + StringBuilder sb = new StringBuilder(); + if (msg.what == MESSAGE_TYPE_NOTIFICATION || msg.what == MESSAGE_TYPE_COMMAND + || msg.what == MESSAGE_TYPE_RESPONSE + || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { + sb.append(getWhatToString(msg.arg1)); + } + Message message = msg; + if ((msg.what == MESSAGE_TYPE_RESPONSE || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) + && mCurrentCommand != null) { + message = mCurrentCommand; + } + if (msg.what == MESSAGE_TYPE_COMMAND + || msg.what == MESSAGE_TYPE_RESPONSE + || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { + if (message.arg1 == COMMAND_TYPE_CONNECT) { + sb.append(" caller=") + .append(message.getData().getString(MESSAGE_BUNDLE_KEY_CALLING_PACKAGE)) + .append("(") + .append(message.getData().getInt(MESSAGE_BUNDLE_KEY_UID)) + .append(")"); + } else { + WifiAwareClientState client = mClients.get(message.arg2); + if (client != null) { + sb.append(" caller=") + .append(client.getCallingPackage()) + .append("(") + .append(client.getUid()) + .append(")"); + } + } + } if (msg.what == MESSAGE_TYPE_COMMAND && mCurrentTransactionId != TRANSACTION_ID_IGNORE) { sb.append(" (Transaction ID=").append(mCurrentTransactionId).append(")"); + } else if (msg.what == MESSAGE_TYPE_RESPONSE + || msg.what == MESSAGE_TYPE_RESPONSE_TIMEOUT) { + sb.append(" (Transaction ID=").append(msg.arg2).append(")"); } return sb.toString(); @@ -5096,7 +5091,8 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe + ", success=" + success + ", reasonOnFailure=" + reasonOnFailure); } - return mDataPathMgr.onRespondToDataPathRequest(command.arg2, success, reasonOnFailure); + return mDataPathMgr.onRespondToDataPathRequest( + command.getData().getInt(MESSAGE_BUNDLE_KEY_NDP_ID), success, reasonOnFailure); } private void onEndPathEndResponseLocal(Message command, boolean success, int reasonOnFailure) { diff --git a/service/java/com/android/server/wifi/coex/CoexUtils.java b/service/java/com/android/server/wifi/coex/CoexUtils.java index 786fe785b3..35d988bb5b 100644 --- a/service/java/com/android/server/wifi/coex/CoexUtils.java +++ b/service/java/com/android/server/wifi/coex/CoexUtils.java @@ -650,8 +650,9 @@ public class CoexUtils { public CoexCellChannel(@Annotation.NetworkType int rat, int band, int downlinkFreqKhz, int downlinkBandwidthKhz, int uplinkFreqKhz, int uplinkBandwidthKhz, int subId) { - if (band < 1 || band > 261) { - Log.wtf(TAG, "Band is " + band + " but should be a value from 1 to 261"); + if ((band < 1 || band > 261) && band != PhysicalChannelConfig.BAND_UNKNOWN) { + Log.wtf(TAG, "Band is " + band + " but should be a value from 1 to 261" + + " or PhysicalChannelConfig.BAND_UNKNOWN"); } if (downlinkFreqKhz < 0 && downlinkFreqKhz != PhysicalChannelConfig.FREQUENCY_UNKNOWN) { Log.wtf(TAG, "Downlink frequency is " + downlinkFreqKhz + " but should be >= 0" diff --git a/service/java/com/android/server/wifi/hal/IWifiChip.java b/service/java/com/android/server/wifi/hal/IWifiChip.java index 7e3e7dbfcb..7c8235c1db 100644 --- a/service/java/com/android/server/wifi/hal/IWifiChip.java +++ b/service/java/com/android/server/wifi/hal/IWifiChip.java @@ -29,6 +29,7 @@ import com.android.server.wifi.SarInfo; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WlanWakeReasonAndCounts; +import java.util.BitSet; import java.util.List; /** Abstraction of WifiChip */ @@ -153,19 +154,19 @@ public interface IWifiChip { * but it is recommended to use {@link #getCapabilitiesAfterIfacesExist()} once * any ifaces are up. * - * @return {@link WifiChip.Response} where the value is a bitset of + * @return {@link WifiChip.Response} where the value is a BitSet of * WifiManager.WIFI_FEATURE_* values. */ - WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist(); + WifiChip.Response<BitSet> getCapabilitiesBeforeIfacesExist(); /** * Get the capabilities supported by this chip. * Call if interfaces have been created on this chip. * - * @return {@link WifiChip.Response} where the value is a bitset of + * @return {@link WifiChip.Response} where the value is a BitSet of * WifiManager.WIFI_FEATURE_* values. */ - WifiChip.Response<Long> getCapabilitiesAfterIfacesExist(); + WifiChip.Response<BitSet> getCapabilitiesAfterIfacesExist(); /** * Retrieve the Wi-Fi wakeup reason stats for debugging. diff --git a/service/java/com/android/server/wifi/hal/IWifiStaIface.java b/service/java/com/android/server/wifi/hal/IWifiStaIface.java index 3e4078531a..2358d2bcd6 100644 --- a/service/java/com/android/server/wifi/hal/IWifiStaIface.java +++ b/service/java/com/android/server/wifi/hal/IWifiStaIface.java @@ -29,6 +29,7 @@ import com.android.server.wifi.WifiLinkLayerStats; import com.android.server.wifi.WifiLoggerHal; import com.android.server.wifi.WifiNative; +import java.util.BitSet; import java.util.List; /** Abstraction of WifiStaIface */ @@ -97,9 +98,9 @@ public interface IWifiStaIface { /** * Get the capabilities supported by this STA iface. * - * @return Bitset of WifiManager.WIFI_FEATURE_* values. + * @return BitSet of WifiManager.WIFI_FEATURE_* values. */ - long getCapabilities(); + BitSet getCapabilities(); /** * Retrieve the fates of inbound packets. diff --git a/service/java/com/android/server/wifi/hal/WifiChip.java b/service/java/com/android/server/wifi/hal/WifiChip.java index 19d52b8518..557573f207 100644 --- a/service/java/com/android/server/wifi/hal/WifiChip.java +++ b/service/java/com/android/server/wifi/hal/WifiChip.java @@ -37,6 +37,7 @@ import com.android.server.wifi.util.NativeUtil; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.BitSet; import java.util.List; import java.util.function.Supplier; @@ -657,16 +658,16 @@ public class WifiChip { /** * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} */ - public Response<Long> getCapabilitiesBeforeIfacesExist() { - return validateAndCall("getCapabilitiesBeforeIfacesExist", new Response<>(0L), + public Response<BitSet> getCapabilitiesBeforeIfacesExist() { + return validateAndCall("getCapabilitiesBeforeIfacesExist", new Response<>(new BitSet()), () -> mWifiChip.getCapabilitiesBeforeIfacesExist()); } /** * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} */ - public Response<Long> getCapabilitiesAfterIfacesExist() { - return validateAndCall("getCapabilitiesAfterIfacesExist", new Response<>(0L), + public Response<BitSet> getCapabilitiesAfterIfacesExist() { + return validateAndCall("getCapabilitiesAfterIfacesExist", new Response<>(new BitSet()), () -> mWifiChip.getCapabilitiesAfterIfacesExist()); } diff --git a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java index f9e4ce2232..9c41ddbdd8 100644 --- a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java @@ -78,6 +78,7 @@ import com.android.server.wifi.util.HalAidlUtil; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; /** @@ -389,7 +390,7 @@ public class WifiChipAidlImpl implements IWifiChip { * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} */ @Override - public WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist() { + public WifiChip.Response<BitSet> getCapabilitiesBeforeIfacesExist() { final String methodStr = "getCapabilitiesBeforeIfacesExist"; return getCapabilitiesInternal(methodStr); } @@ -398,15 +399,15 @@ public class WifiChipAidlImpl implements IWifiChip { * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} */ @Override - public WifiChip.Response<Long> getCapabilitiesAfterIfacesExist() { + public WifiChip.Response<BitSet> getCapabilitiesAfterIfacesExist() { final String methodStr = "getCapabilitiesAfterIfacesExist"; return getCapabilitiesInternal(methodStr); } - private WifiChip.Response<Long> getCapabilitiesInternal(String methodStr) { + private WifiChip.Response<BitSet> getCapabilitiesInternal(String methodStr) { // getCapabilities uses the same logic in AIDL, regardless of whether the call // happens before or after any interfaces have been created. - WifiChip.Response<Long> featuresResp = new WifiChip.Response<>(0L); + WifiChip.Response<BitSet> featuresResp = new WifiChip.Response<>(new BitSet()); synchronized (mLock) { try { if (!checkIfaceAndLogFailure(methodStr)) return featuresResp; @@ -1590,28 +1591,28 @@ public class WifiChipAidlImpl implements IWifiChip { } @VisibleForTesting - protected static long halToFrameworkChipFeatureSet(long halFeatureSet) { - long features = 0; + protected static BitSet halToFrameworkChipFeatureSet(long halFeatureSet) { + BitSet features = new BitSet(); if (bitmapContains(halFeatureSet, FeatureSetMask.SET_TX_POWER_LIMIT)) { - features |= WifiManager.WIFI_FEATURE_TX_POWER_LIMIT; + features.set(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT); } if (bitmapContains(halFeatureSet, FeatureSetMask.D2D_RTT)) { - features |= WifiManager.WIFI_FEATURE_D2D_RTT; + features.set(WifiManager.WIFI_FEATURE_D2D_RTT); } if (bitmapContains(halFeatureSet, FeatureSetMask.D2AP_RTT)) { - features |= WifiManager.WIFI_FEATURE_D2AP_RTT; + features.set(WifiManager.WIFI_FEATURE_D2AP_RTT); } if (bitmapContains(halFeatureSet, FeatureSetMask.SET_LATENCY_MODE)) { - features |= WifiManager.WIFI_FEATURE_LOW_LATENCY; + features.set(WifiManager.WIFI_FEATURE_LOW_LATENCY); } if (bitmapContains(halFeatureSet, FeatureSetMask.P2P_RAND_MAC)) { - features |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC; + features.set(WifiManager.WIFI_FEATURE_P2P_RAND_MAC); } if (bitmapContains(halFeatureSet, FeatureSetMask.WIGIG)) { - features |= WifiManager.WIFI_FEATURE_INFRA_60G; + features.set(WifiManager.WIFI_FEATURE_INFRA_60G); } if (bitmapContains(halFeatureSet, FeatureSetMask.T2LM_NEGOTIATION)) { - features |= WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION; + features.set(WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION); } return features; } diff --git a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java index 31101ac116..e366295e33 100644 --- a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java @@ -64,6 +64,7 @@ import com.android.wifi.resources.R; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; import java.util.function.Supplier; @@ -236,9 +237,9 @@ public class WifiChipHidlImpl implements IWifiChip { * See comments for {@link IWifiChip#getCapabilitiesBeforeIfacesExist()} */ @Override - public WifiChip.Response<Long> getCapabilitiesBeforeIfacesExist() { + public WifiChip.Response<BitSet> getCapabilitiesBeforeIfacesExist() { String methodStr = "getCapabilitiesBeforeIfacesExist"; - return validateAndCall(methodStr, new WifiChip.Response<>(0L), + return validateAndCall(methodStr, new WifiChip.Response<>(new BitSet()), () -> getCapabilitiesBeforeIfacesExistInternal(methodStr)); } @@ -246,9 +247,9 @@ public class WifiChipHidlImpl implements IWifiChip { * See comments for {@link IWifiChip#getCapabilitiesAfterIfacesExist()} */ @Override - public WifiChip.Response<Long> getCapabilitiesAfterIfacesExist() { + public WifiChip.Response<BitSet> getCapabilitiesAfterIfacesExist() { String methodStr = "getCapabilitiesAfterIfacesExist"; - return validateAndCall(methodStr, new WifiChip.Response<>(0L), + return validateAndCall(methodStr, new WifiChip.Response<>(new BitSet()), () -> getCapabilitiesAfterIfacesExistInternal(methodStr)); } @@ -800,8 +801,8 @@ public class WifiChipHidlImpl implements IWifiChip { return modeResp.value; } - private WifiChip.Response<Long> getCapabilitiesBeforeIfacesExistInternal(String methodStr) { - WifiChip.Response<Long> capsResp = new WifiChip.Response<>(0L); + private WifiChip.Response<BitSet> getCapabilitiesBeforeIfacesExistInternal(String methodStr) { + WifiChip.Response<BitSet> capsResp = new WifiChip.Response<>(new BitSet()); try { // HAL newer than v1.5 supports getting capabilities before creating an interface. android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); @@ -823,8 +824,8 @@ public class WifiChipHidlImpl implements IWifiChip { return capsResp; } - private WifiChip.Response<Long> getCapabilitiesAfterIfacesExistInternal(String methodStr) { - WifiChip.Response<Long> capsResp = new WifiChip.Response<>(0L); + private WifiChip.Response<BitSet> getCapabilitiesAfterIfacesExistInternal(String methodStr) { + WifiChip.Response<BitSet> capsResp = new WifiChip.Response<>(new BitSet()); try { android.hardware.wifi.V1_5.IWifiChip chip15 = getWifiChipV1_5Mockable(); android.hardware.wifi.V1_3.IWifiChip chip13 = getWifiChipV1_3Mockable(); @@ -851,7 +852,7 @@ public class WifiChipHidlImpl implements IWifiChip { } else { mWifiChip.getCapabilities((status, caps) -> { if (isOk(status, methodStr)) { - capsResp.setValue((long) wifiFeatureMaskFromChipCapabilities(caps)); + capsResp.setValue(wifiFeatureMaskFromChipCapabilities(caps)); capsResp.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); } else { capsResp.setStatusCode( @@ -1747,7 +1748,7 @@ public class WifiChipHidlImpl implements IWifiChip { } } - private static final long[][] sChipFeatureCapabilityTranslation = { + private static final int[][] sChipFeatureCapabilityTranslation = { {WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT }, @@ -1763,7 +1764,7 @@ public class WifiChipHidlImpl implements IWifiChip { * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for * additional capabilities introduced in V1.5 */ - private static final long[][] sChipFeatureCapabilityTranslation15 = { + private static final int[][] sChipFeatureCapabilityTranslation15 = { {WifiManager.WIFI_FEATURE_INFRA_60G, android.hardware.wifi.V1_5.IWifiChip.ChipCapabilityMask.WIGIG } @@ -1773,7 +1774,7 @@ public class WifiChipHidlImpl implements IWifiChip { * Translation table used by getSupportedFeatureSet for translating IWifiChip caps for * additional capabilities introduced in V1.3 */ - private static final long[][] sChipFeatureCapabilityTranslation13 = { + private static final int[][] sChipFeatureCapabilityTranslation13 = { {WifiManager.WIFI_FEATURE_LOW_LATENCY, android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE }, @@ -1790,11 +1791,11 @@ public class WifiChipHidlImpl implements IWifiChip { * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ @VisibleForTesting - int wifiFeatureMaskFromChipCapabilities(int capabilities) { - int features = 0; + BitSet wifiFeatureMaskFromChipCapabilities(int capabilities) { + BitSet features = new BitSet(); for (int i = 0; i < sChipFeatureCapabilityTranslation.length; i++) { if ((capabilities & sChipFeatureCapabilityTranslation[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation[i][0]; + features.set(sChipFeatureCapabilityTranslation[i][0]); } } return features; @@ -1807,14 +1808,14 @@ public class WifiChipHidlImpl implements IWifiChip { * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ @VisibleForTesting - long wifiFeatureMaskFromChipCapabilities_1_5(int capabilities) { + BitSet wifiFeatureMaskFromChipCapabilities_1_5(int capabilities) { // First collect features from previous versions - long features = wifiFeatureMaskFromChipCapabilities_1_3(capabilities); + BitSet features = wifiFeatureMaskFromChipCapabilities_1_3(capabilities); // Next collect features for V1_5 version for (int i = 0; i < sChipFeatureCapabilityTranslation15.length; i++) { if ((capabilities & sChipFeatureCapabilityTranslation15[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation15[i][0]; + features.set(sChipFeatureCapabilityTranslation15[i][0]); } } return features; @@ -1827,14 +1828,14 @@ public class WifiChipHidlImpl implements IWifiChip { * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ @VisibleForTesting - long wifiFeatureMaskFromChipCapabilities_1_3(int capabilities) { + BitSet wifiFeatureMaskFromChipCapabilities_1_3(int capabilities) { // First collect features from previous versions - long features = wifiFeatureMaskFromChipCapabilities(capabilities); + BitSet features = wifiFeatureMaskFromChipCapabilities(capabilities); // Next collect features for V1_3 version for (int i = 0; i < sChipFeatureCapabilityTranslation13.length; i++) { if ((capabilities & sChipFeatureCapabilityTranslation13[i][1]) != 0) { - features |= sChipFeatureCapabilityTranslation13[i][0]; + features.set(sChipFeatureCapabilityTranslation13[i][0]); } } return features; diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java index 2b5a7da08a..ecefe9bf33 100644 --- a/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceAidlImpl.java @@ -18,6 +18,8 @@ package com.android.server.wifi.hal; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_128; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_256; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; @@ -455,9 +457,9 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite) { String methodStr = "respondToPairingRequest"; - NanRespondToPairingIndicationRequest request = createNanPairingResponse(pairingId, accept, - pairingIdentityKey, enablePairingCache, requestType, pmk, password, akm, - cipherSuite); + NanRespondToPairingIndicationRequest request = createRespondToPairingIndicationRequest( + pairingId, accept, pairingIdentityKey, enablePairingCache, requestType, pmk, + password, akm, cipherSuite); synchronized (mLock) { try { if (!checkIfaceAndLogFailure(methodStr)) return false; @@ -844,7 +846,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.OPEN; WifiAwareDataPathSecurityConfig securityConfig = publishConfig.getSecurityConfig(); if (securityConfig != null) { - req.baseConfigs.securityConfig.cipherType = getHalCipherSuiteType( + req.baseConfigs.securityConfig.cipherType = getHalCipherSuites( securityConfig.getCipherSuite()); if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { req.baseConfigs.securityConfig.securityType = NanDataPathSecurityType.PMK; @@ -867,6 +869,10 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { req.publishType = publishConfig.mPublishType; req.txType = NanTxType.BROADCAST; req.pairingConfig = createAidlPairingConfig(publishConfig.getPairingConfig()); + if (publishConfig.getPairingConfig() != null) { + req.baseConfigs.securityConfig.cipherType |= getHalCipherSuites( + publishConfig.getPairingConfig().getSupportedCipherSuites()); + } req.identityKey = copyArray(nik, 16); if (SdkLevel.isAtLeastV() && !publishConfig.getVendorData().isEmpty()) { @@ -935,6 +941,10 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { req.subscribeType = subscribeConfig.mSubscribeType; req.pairingConfig = createAidlPairingConfig(subscribeConfig.getPairingConfig()); + if (subscribeConfig.getPairingConfig() != null) { + req.baseConfigs.securityConfig.cipherType |= getHalCipherSuites( + subscribeConfig.getPairingConfig().getSupportedCipherSuites()); + } req.identityKey = copyArray(nik, 16); req.intfAddr = new android.hardware.wifi.MacAddress[0]; @@ -995,7 +1005,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { req.securityConfig.scid = new byte[16]; req.securityConfig.securityType = NanDataPathSecurityType.OPEN; if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite()); + req.securityConfig.cipherType = getHalCipherSuites(securityConfig.getCipherSuite()); if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { req.securityConfig.securityType = NanDataPathSecurityType.PMK; req.securityConfig.pmk = copyArray(securityConfig.getPmk()); @@ -1032,7 +1042,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { : NanPairingRequestType.NAN_PAIRING_VERIFICATION; request.securityConfig = new NanPairingSecurityConfig(); request.securityConfig.pmk = new byte[32]; - request.securityConfig.cipherType = cipherSuite; + request.securityConfig.cipherType = getHalCipherSuites(cipherSuite); request.securityConfig.passphrase = new byte[0]; if (pmk != null && pmk.length != 0) { request.securityConfig.securityType = NanPairingSecurityType.PMK; @@ -1050,7 +1060,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { return request; } - private static NanRespondToPairingIndicationRequest createNanPairingResponse( + private static NanRespondToPairingIndicationRequest createRespondToPairingIndicationRequest( int pairingInstanceId, boolean accept, byte[] pairingIdentityKey, boolean enablePairingCache, int requestType, byte[] pmk, String password, int akm, int cipherSuite) { @@ -1065,7 +1075,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { request.securityConfig = new NanPairingSecurityConfig(); request.securityConfig.pmk = new byte[32]; request.securityConfig.passphrase = new byte[0]; - request.securityConfig.cipherType = cipherSuite; + request.securityConfig.cipherType = getHalCipherSuites(cipherSuite); if (pmk != null && pmk.length != 0) { request.securityConfig.securityType = NanPairingSecurityType.PMK; request.securityConfig.pmk = copyArray(pmk); @@ -1097,7 +1107,7 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { req.securityConfig.scid = new byte[16]; req.securityConfig.securityType = NanDataPathSecurityType.OPEN; if (securityConfig != null) { - req.securityConfig.cipherType = getHalCipherSuiteType(securityConfig.getCipherSuite()); + req.securityConfig.cipherType = getHalCipherSuites(securityConfig.getCipherSuite()); if (securityConfig.getPmk() != null && securityConfig.getPmk().length != 0) { req.securityConfig.securityType = NanDataPathSecurityType.PMK; req.securityConfig.pmk = copyArray(securityConfig.getPmk()); @@ -1119,18 +1129,27 @@ public class WifiNanIfaceAidlImpl implements IWifiNanIface { return req; } - private static int getHalCipherSuiteType(int frameworkCipherSuites) { - switch (frameworkCipherSuites) { - case WIFI_AWARE_CIPHER_SUITE_NCS_SK_128: - return NanCipherSuiteType.SHARED_KEY_128_MASK; - case WIFI_AWARE_CIPHER_SUITE_NCS_SK_256: - return NanCipherSuiteType.SHARED_KEY_256_MASK; - case WIFI_AWARE_CIPHER_SUITE_NCS_PK_128: - return NanCipherSuiteType.PUBLIC_KEY_2WDH_256_MASK; - case WIFI_AWARE_CIPHER_SUITE_NCS_PK_256: - return NanCipherSuiteType.PUBLIC_KEY_2WDH_256_MASK; + private static int getHalCipherSuites(int frameworkCipherSuites) { + int cipherSuites = NanCipherSuiteType.NONE; + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_SK_128) != 0) { + cipherSuites |= NanCipherSuiteType.SHARED_KEY_128_MASK; + } + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_SK_256) != 0) { + cipherSuites |= NanCipherSuiteType.SHARED_KEY_256_MASK; + } + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_PK_128) != 0) { + cipherSuites |= NanCipherSuiteType.PUBLIC_KEY_2WDH_128_MASK; + } + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_PK_256) != 0) { + cipherSuites |= NanCipherSuiteType.PUBLIC_KEY_2WDH_256_MASK; + } + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128) != 0) { + cipherSuites |= NanCipherSuiteType.PUBLIC_KEY_PASN_128_MASK; + } + if ((frameworkCipherSuites & WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256) != 0) { + cipherSuites |= NanCipherSuiteType.PUBLIC_KEY_PASN_256_MASK; } - return NanCipherSuiteType.NONE; + return cipherSuites; } private static byte[] copyArray(byte[] source) { diff --git a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java index bb1a2e1bf2..f3c410badf 100644 --- a/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiNanIfaceCallbackAidlImpl.java @@ -440,18 +440,21 @@ public class WifiNanIfaceCallbackAidlImpl extends IWifiNanIfaceEventCallback.Stu NanRangingIndication.fromAidl(event.rangingIndicationType), event.rangingMeasurementInMm, event.scid, - toPublicDataPathCipherSuites(event.peerCipherType), + toPublicDataPathCipherSuites(event.peerCipherType) + | toPublicPairingCipherSuites(event.peerCipherType), event.peerNira.nonce, event.peerNira.tag, - createPublicPairingConfig(event.peerPairingConfig), + createPublicPairingConfig(event.peerPairingConfig, event.peerCipherType), vendorData); } - private AwarePairingConfig createPublicPairingConfig(NanPairingConfig nativePairingConfig) { + private AwarePairingConfig createPublicPairingConfig(NanPairingConfig nativePairingConfig, + int cipherSuites) { return new AwarePairingConfig(nativePairingConfig.enablePairingSetup, nativePairingConfig.enablePairingCache, nativePairingConfig.enablePairingVerification, - toBootStrappingMethods(nativePairingConfig.supportedBootstrappingMethods)); + toBootStrappingMethods(nativePairingConfig.supportedBootstrappingMethods), + toPublicPairingCipherSuites(cipherSuites)); } private int toBootStrappingMethods(int nativeMethods) { @@ -642,7 +645,7 @@ public class WifiNanIfaceCallbackAidlImpl extends IWifiNanIfaceEventCallback.Stu NpkSecurityAssociation npksa) { return new PairingSecurityAssociationInfo(npksa.peerNanIdentityKey, npksa.localNanIdentityKey, npksa.npk, - createPublicPairingAkm(npksa.akm), toPublicDataPathCipherSuites(npksa.cipherType)); + createPublicPairingAkm(npksa.akm), toPublicPairingCipherSuites(npksa.cipherType)); } private static int createPublicPairingAkm(int aidlAkm) { diff --git a/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java index 9c10ee0937..ba32e3f93b 100644 --- a/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiRttControllerAidlImpl.java @@ -56,6 +56,8 @@ import java.util.Set; public class WifiRttControllerAidlImpl implements IWifiRttController { private static final String TAG = "WifiRttControllerAidl"; private boolean mVerboseLoggingEnabled = false; + private static final int CONVERSION_MICROS_TO_10_MILLIS = 10000; + private static final int CONVERSION_MICROS_TO_100_MICROS = 100; private android.hardware.wifi.IWifiRttController mWifiRttController; private WifiRttController.Capabilities mRttCapabilities; @@ -292,8 +294,10 @@ public class WifiRttControllerAidlImpl implements IWifiRttController { .setMeasurementChannelFrequencyMHz(rttResult.channelFreqMHz) .setMeasurementBandwidth(halToFrameworkChannelBandwidth(rttResult.packetBw)) .set80211azNtbMeasurement(rttResult.type == RttType.TWO_SIDED_11AZ_NTB) - .setMinTimeBetweenNtbMeasurementsMicros(rttResult.ntbMinMeasurementTime) - .setMaxTimeBetweenNtbMeasurementsMicros(rttResult.ntbMaxMeasurementTime) + .setMinTimeBetweenNtbMeasurementsMicros(rttResult.ntbMinMeasurementTime + * CONVERSION_MICROS_TO_100_MICROS) + .setMaxTimeBetweenNtbMeasurementsMicros(rttResult.ntbMaxMeasurementTime + * CONVERSION_MICROS_TO_10_MILLIS) .set80211azInitiatorTxLtfRepetitionsCount(rttResult.i2rTxLtfRepetitionCount) .set80211azResponderTxLtfRepetitionsCount(rttResult.r2iTxLtfRepetitionCount) .set80211azNumberOfTxSpatialStreams(rttResult.numTxSpatialStreams) @@ -486,11 +490,11 @@ public class WifiRttControllerAidlImpl implements IWifiRttController { } validateBwAndPreambleCombination(config.bw, config.preamble); // ResponderConfig#ntbMaxMeasurementTime is in units of 10 milliseconds - config.ntbMaxMeasurementTime = - responder.getNtbMaxTimeBetweenMeasurementsMicros() / 10000; + config.ntbMaxMeasurementTime = responder.getNtbMaxTimeBetweenMeasurementsMicros() + / CONVERSION_MICROS_TO_10_MILLIS; // ResponderConfig#ntbMinMeasurementTime is in units of 100 microseconds - config.ntbMinMeasurementTime = - responder.getNtbMinTimeBetweenMeasurementsMicros() / 100; + config.ntbMinMeasurementTime = responder.getNtbMinTimeBetweenMeasurementsMicros() + / CONVERSION_MICROS_TO_100_MICROS; if (config.peer == RttPeerType.NAN_TYPE) { config.mustRequestLci = false; diff --git a/service/java/com/android/server/wifi/hal/WifiStaIface.java b/service/java/com/android/server/wifi/hal/WifiStaIface.java index ca4cd785d1..b0caeca366 100644 --- a/service/java/com/android/server/wifi/hal/WifiStaIface.java +++ b/service/java/com/android/server/wifi/hal/WifiStaIface.java @@ -37,6 +37,7 @@ import com.android.server.wifi.WifiLinkLayerStats; import com.android.server.wifi.WifiNative; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.function.Supplier; @@ -253,8 +254,8 @@ public class WifiStaIface implements WifiHal.WifiInterface { /** * See comments for {@link IWifiStaIface#getCapabilities()} */ - public long getCapabilities() { - return validateAndCall("getCapabilities", 0L, + public BitSet getCapabilities() { + return validateAndCall("getCapabilities", new BitSet(), () -> mWifiStaIface.getCapabilities()); } diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java index 8cb199a0f4..580069317b 100644 --- a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java @@ -80,6 +80,7 @@ import com.android.server.wifi.util.NativeUtil; import com.android.wifi.resources.R; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; /** @@ -281,11 +282,11 @@ public class WifiStaIfaceAidlImpl implements IWifiStaIface { * See comments for {@link IWifiStaIface#getCapabilities()} */ @Override - public long getCapabilities() { + public BitSet getCapabilities() { final String methodStr = "getCapabilities"; synchronized (mLock) { try { - if (!checkIfaceAndLogFailure(methodStr)) return 0L; + if (!checkIfaceAndLogFailure(methodStr)) return new BitSet(); long halFeatureSet = mWifiStaIface.getFeatureSet(); return halToFrameworkStaFeatureSet(halFeatureSet); } catch (RemoteException e) { @@ -293,7 +294,7 @@ public class WifiStaIfaceAidlImpl implements IWifiStaIface { } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } - return 0L; + return new BitSet(); } } @@ -1265,59 +1266,59 @@ public class WifiStaIfaceAidlImpl implements IWifiStaIface { } @VisibleForTesting - protected static long halToFrameworkStaFeatureSet(long halFeatureSet) { - long features = 0; + protected static BitSet halToFrameworkStaFeatureSet(long halFeatureSet) { + BitSet features = new BitSet(); if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.HOTSPOT)) { - features |= WifiManager.WIFI_FEATURE_PASSPOINT; + features.set(WifiManager.WIFI_FEATURE_PASSPOINT); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN)) { - features |= WifiManager.WIFI_FEATURE_SCANNER; + features.set(WifiManager.WIFI_FEATURE_SCANNER); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.PNO)) { - features |= WifiManager.WIFI_FEATURE_PNO; + features.set(WifiManager.WIFI_FEATURE_PNO); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS)) { - features |= WifiManager.WIFI_FEATURE_TDLS; + features.set(WifiManager.WIFI_FEATURE_TDLS); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS_OFFCHANNEL)) { - features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; + features.set(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.LINK_LAYER_STATS)) { - features |= WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; + features.set(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.RSSI_MONITOR)) { - features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; + features.set(WifiManager.WIFI_FEATURE_RSSI_MONITOR); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.KEEP_ALIVE)) { - features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; + features.set(WifiManager.WIFI_FEATURE_MKEEP_ALIVE); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.ND_OFFLOAD)) { - features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; + features.set(WifiManager.WIFI_FEATURE_CONFIG_NDO); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.CONTROL_ROAMING)) { - features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; + features.set(WifiManager.WIFI_FEATURE_CONTROL_ROAMING); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.PROBE_IE_ALLOWLIST)) { - features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; + features.set(WifiManager.WIFI_FEATURE_IE_WHITELIST); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.SCAN_RAND)) { - features |= WifiManager.WIFI_FEATURE_SCAN_RAND; + features.set(WifiManager.WIFI_FEATURE_SCAN_RAND); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.ROAMING_MODE_CONTROL)) { - features |= WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT; + features.set(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); } return features; } @@ -1476,11 +1477,21 @@ public class WifiStaIfaceAidlImpl implements IWifiStaIface { radio.on_time_roam_scan = aidlRadioStats.onTimeInMsForRoamScan; radio.on_time_pno_scan = aidlRadioStats.onTimeInMsForPnoScan; radio.on_time_hs20_scan = aidlRadioStats.onTimeInMsForHs20Scan; + if (aidlRadioStats.txTimeInMsPerLevel != null + && aidlRadioStats.txTimeInMsPerLevel.length > 0) { + radio.tx_time_in_ms_per_level = new int[aidlRadioStats.txTimeInMsPerLevel.length]; + for (int i = 0; i < aidlRadioStats.txTimeInMsPerLevel.length; ++i) { + radio.tx_time_in_ms_per_level[i] = aidlRadioStats.txTimeInMsPerLevel[i]; + } + } /* Copy list of channel stats */ for (WifiChannelStats channelStats : aidlRadioStats.channelStats) { WifiLinkLayerStats.ChannelStats channelStatsEntry = new WifiLinkLayerStats.ChannelStats(); channelStatsEntry.frequency = channelStats.channel.centerFreq; + channelStatsEntry.frequencyFirstSegment = channelStats.channel.centerFreq0; + channelStatsEntry.frequencySecondSegment = channelStats.channel.centerFreq1; + channelStatsEntry.channelWidth = channelStats.channel.width; channelStatsEntry.radioOnTimeMs = channelStats.onTimeInMs; channelStatsEntry.ccaBusyTimeMs = channelStats.ccaBusyTimeInMs; radio.channelStatsMap.put(channelStats.channel.centerFreq, channelStatsEntry); diff --git a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java index 399fd2c377..a5deeaeef2 100644 --- a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java @@ -61,6 +61,7 @@ import com.android.server.wifi.util.NativeUtil; import com.android.wifi.resources.R; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.function.Supplier; @@ -159,9 +160,9 @@ public class WifiStaIfaceHidlImpl implements IWifiStaIface { /** * See comments for {@link IWifiStaIface#getCapabilities()} */ - public long getCapabilities() { + public BitSet getCapabilities() { final String methodStr = "getCapabilities"; - return validateAndCall(methodStr, 0L, + return validateAndCall(methodStr, new BitSet(), () -> getCapabilitiesInternal(methodStr)); } @@ -467,8 +468,8 @@ public class WifiStaIfaceHidlImpl implements IWifiStaIface { return scanResp.value; } - private long getCapabilitiesInternal(String methodStr) { - GeneralUtil.Mutable<Long> capsResp = new GeneralUtil.Mutable<>(0L); + private BitSet getCapabilitiesInternal(String methodStr) { + GeneralUtil.Mutable<BitSet> capsResp = new GeneralUtil.Mutable<>(new BitSet()); try { mWifiStaIface.getCapabilities((status, caps) -> { if (isOk(status, methodStr)) { @@ -889,56 +890,56 @@ public class WifiStaIfaceHidlImpl implements IWifiStaIface { } @VisibleForTesting - long halToFrameworkStaIfaceCapability(int caps) { - long features = 0; + BitSet halToFrameworkStaIfaceCapability(int caps) { + BitSet features = new BitSet(); if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.HOTSPOT)) { - features |= WifiManager.WIFI_FEATURE_PASSPOINT; + features.set(WifiManager.WIFI_FEATURE_PASSPOINT); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) { - features |= WifiManager.WIFI_FEATURE_SCANNER; + features.set(WifiManager.WIFI_FEATURE_SCANNER); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) { - features |= WifiManager.WIFI_FEATURE_PNO; + features.set(WifiManager.WIFI_FEATURE_PNO); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) { - features |= WifiManager.WIFI_FEATURE_TDLS; + features.set(WifiManager.WIFI_FEATURE_TDLS); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) { - features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; + features.set(WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS)) { - features |= WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; + features.set(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.RSSI_MONITOR)) { - features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; + features.set(WifiManager.WIFI_FEATURE_RSSI_MONITOR); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.KEEP_ALIVE)) { - features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; + features.set(WifiManager.WIFI_FEATURE_MKEEP_ALIVE); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.ND_OFFLOAD)) { - features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; + features.set(WifiManager.WIFI_FEATURE_CONFIG_NDO); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.CONTROL_ROAMING)) { - features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; + features.set(WifiManager.WIFI_FEATURE_CONTROL_ROAMING); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask .PROBE_IE_WHITELIST)) { - features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; + features.set(WifiManager.WIFI_FEATURE_IE_WHITELIST); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.SCAN_RAND)) { - features |= WifiManager.WIFI_FEATURE_SCAN_RAND; + features.set(WifiManager.WIFI_FEATURE_SCAN_RAND); } return features; } diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java index 44db1f3c0d..afb6b8ff6e 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelper.java @@ -342,8 +342,6 @@ public class PasspointNetworkNominateHelper { return existingNetwork; } mWifiConfigManager.enableNetwork(result.getNetworkId(), false, config.creatorUid, null); - mWifiConfigManager.setNetworkCandidateScanResult(result.getNetworkId(), - candidate.mScanDetail.getScanResult(), 0, null); mWifiConfigManager.updateScanDetailForNetwork( result.getNetworkId(), candidate.mScanDetail); return mWifiConfigManager.getConfiguredNetwork(result.getNetworkId()); diff --git a/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java b/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java new file mode 100644 index 0000000000..828d694431 --- /dev/null +++ b/service/java/com/android/server/wifi/mainline_supplicant/ServiceManagerWrapper.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2024 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 com.android.server.wifi.mainline_supplicant; + +import android.annotation.Nullable; +import android.os.IBinder; + +import com.android.modules.utils.build.SdkLevel; + +/** + * Wrapper around ServiceManager APIs that are not directly available to the mainline module. + */ +public final class ServiceManagerWrapper { + static { + System.loadLibrary("service-wifi-jni"); + } + + /** + * Returns the specified service from the service manager. + * + * If the service is not running, service manager will attempt to start it, and this function + * will wait for it to be ready. + * + * @return {@code null} only if there are permission problems or fatal errors + */ + public static @Nullable IBinder waitForService(String serviceName) { + // Underlying implementation requires SDK 31+ + if (!SdkLevel.isAtLeastS()) { + return null; + } + return nativeWaitForService(serviceName); + } + + private static native IBinder nativeWaitForService(String serviceName); +} diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java index e3eabad46c..60dc936057 100644 --- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java +++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceCallbackAidlImpl.java @@ -31,6 +31,7 @@ import android.hardware.wifi.supplicant.P2pPeerClientJoinedEventParams; import android.hardware.wifi.supplicant.P2pProvDiscStatusCode; import android.hardware.wifi.supplicant.P2pProvisionDiscoveryCompletedEventParams; import android.hardware.wifi.supplicant.P2pStatusCode; +import android.hardware.wifi.supplicant.P2pUsdBasedServiceDiscoveryResultParams; import android.hardware.wifi.supplicant.WpsConfigMethods; import android.hardware.wifi.supplicant.WpsDevPasswordId; import android.net.MacAddress; @@ -627,6 +628,41 @@ public class SupplicantP2pIfaceCallbackAidlImpl extends ISupplicantP2pIfaceCallb mMonitor.broadcastP2pServiceDiscoveryResponse(mInterface, response); } + /** + * Used to indicate the reception of a USD based service discovery response. + * + * @param params Parameters associated with the USD based service discovery result. + */ + @Override + public void onUsdBasedServiceDiscoveryResult(P2pUsdBasedServiceDiscoveryResultParams params) { + logd("Usd based service discovery result received on " + mInterface); + // TODO implementation + } + + /** + * Used to indicate the termination of USD based service discovery. + * + * @param sessionId Identifier to identify the instance of a service discovery. + * @param reasonCode The reason for termination of service discovery. + */ + @Override + public void onUsdBasedServiceDiscoveryTerminated(int sessionId, int reasonCode) { + logd("Usd based service discovery terminated on " + mInterface); + // TODO implementation + } + + /** + * Used to indicate the termination of USD based service Advertisement + * + * @param sessionId Identifier to identify the instance of a service advertisement. + * @param reasonCode The reason for termination of service advertisement. + */ + @Override + public void onUsdBasedServiceAdvertisementTerminated(int sessionId, int reasonCode) { + logd("Usd based service advertisement terminated on " + mInterface); + // TODO implementation + } + private WifiP2pDevice createStaEventDevice(byte[] interfaceAddress, byte[] p2pDeviceAddress, InetAddress ipAddress) { WifiP2pDevice device = new WifiP2pDevice(); diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java index edbf956ace..3be642d651 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pNative.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pNative.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.WorkSource; import android.text.TextUtils; import android.util.Log; +import android.util.SparseArray; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.PropertyService; @@ -996,6 +997,18 @@ public class WifiP2pNative { } /** + * Returns whether P2P + P2P concurrency is supported or not. + */ + public boolean isP2pP2pConcurrencySupported() { + synchronized (mLock) { + return mWifiVendorHal.canDeviceSupportCreateTypeCombo( + new SparseArray<Integer>() {{ + put(HDM_CREATE_IFACE_P2P, 2); + }}); + } + } + + /** * Configure the IP addresses in supplicant for P2P GO to provide the IP address to * client in EAPOL handshake. Refer Wi-Fi P2P Technical Specification v1.7 - Section 4.2.8 * IP Address Allocation in EAPOL-Key Frames (4-Way Handshake) for more details. diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java index e004bc4660..6365a609cf 100644 --- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java +++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java @@ -169,6 +169,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -342,7 +343,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // Messages for interaction with IpClient. private static final int IPC_PRE_DHCP_ACTION = BASE + 30; private static final int IPC_POST_DHCP_ACTION = BASE + 31; - private static final int IPC_DHCP_RESULTS = BASE + 32; + @VisibleForTesting + static final int IPC_DHCP_RESULTS = BASE + 32; private static final int IPC_PROVISIONING_SUCCESS = BASE + 33; private static final int IPC_PROVISIONING_FAILURE = BASE + 34; @VisibleForTesting @@ -429,6 +431,16 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private final Map<String, HashSet<ScanResult.InformationElement>> mVendorElements = new HashMap<>(); + // client(application) P2P group info list, key = package name + private final Map<String, WifiP2pGroupInfo> mOwnershipMap = new HashMap<>(); + + // Max number of P2P groups supported + private static final int MAX_NUM_GROUP = 1; + // Package name used to represent all shared connections + private static final String SHARED_PKG_NAME = "__SHARED_PACKAGE_NAME"; + // Ongoing connection request package name with the default value set for shared connection + private String mConnectionPkgName = SHARED_PKG_NAME; + // peer authorizing timestamp which is indexed by the peer MAC address. private final Map<String, Long> mPeerAuthorizingTimestamp = new HashMap<>(); @@ -463,6 +475,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private final RemoteCallbackList<IWifiP2pListener> mWifiP2pListeners = new RemoteCallbackList<>(); + // clients(application) P2P listener map, key = package name + private final Map<String, IWifiP2pListener> mP2pListenerMap = new HashMap<>(); /** * Error code definition. @@ -581,6 +595,18 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } /** + * Stores P2P group information + */ + private static class WifiP2pGroupInfo { + public WifiP2pGroup p2pGroup; + public WifiP2pInfo p2pInfo; + WifiP2pGroupInfo(WifiP2pGroup group, WifiP2pInfo info) { + p2pGroup = group; + p2pInfo = info; + } + } + + /** * Handles client connections */ private class ClientHandler extends Handler { @@ -1052,6 +1078,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { AttributionSource source = mClientAttributionSource.remove(binder); if (null != source) { mVendorElements.remove(source.getPackageName()); + mOwnershipMap.remove(source.getPackageName()); + mP2pListenerMap.remove(source.getPackageName()); } } @@ -1070,6 +1098,24 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } } + /** + * Get WifiP2pGroupInfo owned by the provided package name + */ + private WifiP2pGroupInfo getP2pGroupInfo(String packageName) { + if (mOwnershipMap.containsKey(packageName)) { + return mOwnershipMap.get(packageName); + } else if (mOwnershipMap.containsKey(SHARED_PKG_NAME)) { + return mOwnershipMap.get(SHARED_PKG_NAME); + } + return null; + } + + private boolean checkIfPackageIsGroupOwner(String packageName) { + return !mFeatureFlags.p2pOwnership() + || mOwnershipMap.containsKey(packageName) + || mOwnershipMap.containsKey(SHARED_PKG_NAME); + } + /** This is used to provide information to drivers to optimize performance depending * on the current mode of operation. * 0 - disabled @@ -1120,6 +1166,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { TAG + " registerWifiP2pListener"); Log.i(TAG, "registerWifiP2pListener uid=" + Binder.getCallingUid()); mWifiP2pListeners.register(listener); + mP2pListenerMap.put(packageName, listener); } /** @@ -1133,6 +1180,15 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } Log.i(TAG, "unregisterWifiP2pListener uid=" + Binder.getCallingUid()); mWifiP2pListeners.unregister(listener); + Iterator<Map.Entry<String, IWifiP2pListener>> iterator = + mP2pListenerMap.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry<String, IWifiP2pListener> entry = iterator.next(); + if (entry.getValue() == listener) { + iterator.remove(); + break; + } + } } private void onP2pStateChanged(@WifiP2pManager.WifiP2pState int state) { @@ -1243,53 +1299,57 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mWifiP2pListeners.finishBroadcast(); } - private void onGroupCreated(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) { - int numCallbacks = mWifiP2pListeners.beginBroadcast(); + private void onGroupCreated(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup, + RemoteCallbackList<IWifiP2pListener> callbackList) { + int numCallbacks = callbackList.beginBroadcast(); for (int i = 0; i < numCallbacks; i++) { try { - mWifiP2pListeners.getBroadcastItem(i).onGroupCreated(p2pInfo, p2pGroup); + callbackList.getBroadcastItem(i).onGroupCreated(p2pInfo, p2pGroup); } catch (RemoteException e) { Log.e(TAG, "Failure calling onGroupCreated" + e); } } - mWifiP2pListeners.finishBroadcast(); + callbackList.finishBroadcast(); } - private void onPeerClientJoined(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) { - int numCallbacks = mWifiP2pListeners.beginBroadcast(); + private void onPeerClientJoined(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup, + RemoteCallbackList<IWifiP2pListener> callbackList) { + int numCallbacks = callbackList.beginBroadcast(); for (int i = 0; i < numCallbacks; i++) { try { - mWifiP2pListeners.getBroadcastItem(i).onPeerClientJoined(p2pInfo, p2pGroup); + callbackList.getBroadcastItem(i).onPeerClientJoined(p2pInfo, p2pGroup); } catch (RemoteException e) { Log.e(TAG, "Failure calling onPeerClientJoined" + e); } } - mWifiP2pListeners.finishBroadcast(); + callbackList.finishBroadcast(); } - private void onPeerClientDisconnected(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) { - int numCallbacks = mWifiP2pListeners.beginBroadcast(); + private void onPeerClientDisconnected(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup, + RemoteCallbackList<IWifiP2pListener> callbackList) { + int numCallbacks = callbackList.beginBroadcast(); for (int i = 0; i < numCallbacks; i++) { try { - mWifiP2pListeners.getBroadcastItem(i).onPeerClientDisconnected(p2pInfo, + callbackList.getBroadcastItem(i).onPeerClientDisconnected(p2pInfo, p2pGroup); } catch (RemoteException e) { Log.e(TAG, "Failure calling onPeerClientDisconnected" + e); } } - mWifiP2pListeners.finishBroadcast(); + callbackList.finishBroadcast(); } - private void onFrequencyChanged(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup) { - int numCallbacks = mWifiP2pListeners.beginBroadcast(); + private void onFrequencyChanged(WifiP2pInfo p2pInfo, WifiP2pGroup p2pGroup, + RemoteCallbackList<IWifiP2pListener> callbackList) { + int numCallbacks = callbackList.beginBroadcast(); for (int i = 0; i < numCallbacks; i++) { try { - mWifiP2pListeners.getBroadcastItem(i).onFrequencyChanged(p2pInfo, p2pGroup); + callbackList.getBroadcastItem(i).onFrequencyChanged(p2pInfo, p2pGroup); } catch (RemoteException e) { Log.e(TAG, "Failure calling onFrequencyChanged" + e); } } - mWifiP2pListeners.finishBroadcast(); + callbackList.finishBroadcast(); } private void onGroupRemoved() { @@ -1311,6 +1371,12 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { != PackageManager.PERMISSION_DENIED; } + private boolean isDualP2pSupported() { + return mFeatureFlags.p2pDual() + && mFeatureFlags.p2pOwnership() + && mWifiNative.isP2pP2pConcurrencySupported(); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -1333,6 +1399,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { pw.println("mClientInfoList " + mClientInfoList.size()); pw.println("mActiveClients " + mActiveClients); pw.println("mPeerAuthorizingTimestamp" + mPeerAuthorizingTimestamp); + pw.println("isDualP2pSupported" + isDualP2pSupported()); pw.println(); final IIpClient ipClient = mIpClient; @@ -1376,6 +1443,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { new P2pEnabledState(mThreshold, mThreadLocalLog); // Inactive is when p2p is enabled with no connectivity private final InactiveState mInactiveState = new InactiveState(mThreshold, mThreadLocalLog); + // Idle is when p2p is enabled and there's no ongoing connection attempt + private final IdleState mIdleState = new IdleState(mThreshold, mThreadLocalLog); private final GroupCreatingState mGroupCreatingState = new GroupCreatingState(mThreshold, mThreadLocalLog); private final UserAuthorizingInviteRequestState mUserAuthorizingInviteRequestState = @@ -1469,6 +1538,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { addState(mWaitingState, mP2pDisabledContainerState); addState(mP2pEnabledState, mDefaultState); addState(mInactiveState, mP2pEnabledState); + addState(mIdleState, mP2pEnabledState); addState(mGroupCreatingState, mP2pEnabledState); addState(mUserAuthorizingInviteRequestState, mGroupCreatingState); addState(mUserAuthorizingNegotiationRequestState, mGroupCreatingState); @@ -1526,7 +1596,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mSettingsConfigStore.registerChangeListener(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED, new D2DAllowWhenInfraStaDisabledValueListener(), this.getHandler()); // Register for location mode on/off broadcasts - mContext.registerReceiver(new BroadcastReceiver() { + mContext.registerReceiverForAllUsers(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { /* if location mode is off, ongoing discovery should be stopped. @@ -1540,7 +1610,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendMessage(WifiP2pManager.STOP_DISCOVERY); } } - }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); + }, new IntentFilter(LocationManager.MODE_CHANGED_ACTION), null, getHandler()); // Register for tethering state if (!SdkLevel.isAtLeastS()) { mContext.registerReceiver(new BroadcastReceiver() { @@ -1595,6 +1665,25 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } } + private RemoteCallbackList<IWifiP2pListener> generateCallbackList(WifiP2pGroup group) { + if (!mFeatureFlags.p2pOwnership() || mOwnershipMap.containsKey(SHARED_PKG_NAME)) { + return mWifiP2pListeners; + } + + for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) { + if (entry.getValue().p2pGroup.getInterface().equals(group.getInterface())) { + IWifiP2pListener p2pListener = mP2pListenerMap.get(entry.getKey()); + RemoteCallbackList<IWifiP2pListener> listener = new RemoteCallbackList<>(); + if (p2pListener != null) { + listener.register(p2pListener); + logd("WifiP2pListener callback generated for " + entry.getKey()); + } + return listener; + } + } + return mWifiP2pListeners; + } + @Override protected String getLogRecString(Message msg) { StringBuilder sb = new StringBuilder(); @@ -2220,8 +2309,22 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { message.obj)); break; case WifiP2pManager.REQUEST_CONNECTION_INFO: - replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, - new WifiP2pInfo(mWifiP2pInfo)); + if (mFeatureFlags.p2pOwnership()) { + String packageName = getCallingPkgName( + message.sendingUid, message.replyTo); + WifiP2pGroupInfo groupInfo = getP2pGroupInfo(packageName); + if (groupInfo != null) { + replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, + new WifiP2pInfo(groupInfo.p2pInfo)); + } else { + logd("No group owned by caller - returning empty info"); + replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, + new WifiP2pInfo()); + } + } else { + replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, + new WifiP2pInfo(mWifiP2pInfo)); + } break; case WifiP2pManager.REQUEST_GROUP_INFO: { String packageName = getCallingPkgName(message.sendingUid, message.replyTo); @@ -2247,8 +2350,19 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // remain at this state. break; } - replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, - maybeEraseOwnDeviceAddress(mGroup, message.sendingUid)); + if (mFeatureFlags.p2pOwnership()) { + WifiP2pGroupInfo groupInfo = getP2pGroupInfo(packageName); + if (groupInfo != null) { + replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, + maybeEraseOwnDeviceAddress(groupInfo.p2pGroup, uid)); + } else { + logd("No group owned by caller - returning null group"); + replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, null); + } + } else { + replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, + maybeEraseOwnDeviceAddress(mGroup, message.sendingUid)); + } break; } case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO: { @@ -2839,6 +2953,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } resetWifiP2pInfo(); mGroup = null; + mOwnershipMap.clear(); } @Override @@ -2963,7 +3078,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } else if (proceedWithOperation == InterfaceConflictManager.ICM_EXECUTE_COMMAND) { if (setupInterface()) { - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } } // else InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER: nop break; @@ -3041,7 +3160,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { == InterfaceConflictManager.ICM_EXECUTE_COMMAND) { if (!setupInterface()) return NOT_HANDLED; deferMessage(message); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } // else InterfaceConflictManager.ICM_SKIP_COMMAND_WAIT_FOR_USER: nop break; } @@ -3762,7 +3885,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { break; } mSavedPeerConfig = new WifiP2pConfig(); - mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; + mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; mSavedPeerConfig.deviceAddress = device.deviceAddress; mSavedPeerConfig.wps.pin = provDisc.pin; if (SdkLevel.isAtLeastV() && provDisc.getVendorData() != null) { @@ -4019,6 +4142,486 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } } + class IdleState extends RunnerState { + + /** + * The Runner state Constructor + * + * @param threshold the running time threshold in milliseconds + */ + IdleState(int threshold, @NonNull LocalLog localLog) { + super(threshold, localLog); + } + + @Override + public void enterImpl() { + logSmStateName(this.getName(), + getCurrentState() != null ? getCurrentState().getName() : ""); + mPeerAuthorizingTimestamp.clear(); + mSavedPeerConfig.invalidate(); + mDetailedState = NetworkInfo.DetailedState.IDLE; + mConnectionPkgName = SHARED_PKG_NAME; + scheduleIdleShutdown(); + } + + @Override + public void exitImpl() { + cancelIdleShutdown(); + } + + @Override + public boolean processMessageImpl(Message message) { + logSmMessage(getName(), message); + // Re-schedule the shutdown timer since we got the new operation. + // only handle commands from clients. + if (message.what > Protocol.BASE_WIFI_P2P_MANAGER + && message.what < Protocol.BASE_WIFI_P2P_SERVICE) { + scheduleIdleShutdown(); + } + switch (message.what) { + case WifiP2pManager.CONNECT: { + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (packageName == null) { + replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + break; + } + int uid = message.sendingUid; + String attributionTag = getCallingFeatureId(uid, message.replyTo); + Bundle extras = message.getData() + .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); + boolean hasPermission = false; + if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { + hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( + packageName, + attributionTag, + uid, false); + } else { + hasPermission = checkNearbyDevicesPermission(uid, packageName, + extras, "CONNECT", message.obj); + } + if (!hasPermission) { + replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + // remain at this state. + break; + } + mLastCallerInfoManager.put(WifiManager.API_P2P_CONNECT, + Process.myTid(), uid, 0, packageName, true); + if (mVerboseLoggingEnabled) logd(getName() + " sending connect"); + WifiP2pConfig config = (WifiP2pConfig) + extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); + + boolean isConnectFailed = false; + if (isConfigValidAsGroup(config)) { + mAutonomousGroup = false; + mWifiNative.p2pStopFind(); + if (mVerboseLoggingEnabled) { + logd("FAST_CONNECTION GC band freq: " + getGroupOwnerBandToString( + config.groupOwnerBand)); + } + if (mWifiNative.p2pGroupAdd(config, true)) { + reportConnectionEventTakeBugReportIfOverlapped( + P2pConnectionEvent.CONNECTION_FAST, + config, WifiMetricsProto.GroupEvent.GROUP_CLIENT, uid, + attributionTag); + mConnectionPkgName = packageName; + smTransition(this, mGroupNegotiationState); + } else { + loge("Cannot join a group with config."); + isConnectFailed = true; + replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + } + } else { + if (isConfigInvalid(config)) { + loge("Dropping connect request " + config); + isConnectFailed = true; + replyToMessage(message, WifiP2pManager.CONNECT_FAILED); + } else { + mAutonomousGroup = false; + mWifiNative.p2pStopFind(); + if (reinvokePersistentGroup(config, false)) { + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_REINVOKE, + config, GroupEvent.GROUP_UNKNOWN, uid, attributionTag); + smTransition(this, mGroupNegotiationState); + } else { + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_FRESH, + config, GroupEvent.GROUP_UNKNOWN, uid, attributionTag); + smTransition(this, mProvisionDiscoveryState); + } + } + } + + if (!isConnectFailed) { + mSavedPeerConfig = config; + mPeers.updateStatus(mSavedPeerConfig.deviceAddress, + WifiP2pDevice.INVITED); + sendPeersChangedBroadcast(); + replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); + } + break; + } + case WifiP2pManager.STOP_DISCOVERY: + mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_PEER_DISCOVERY, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); + if (mWifiNative.p2pStopFind()) { + // When discovery stops in inactive state, flush to clear + // state peer data + mWifiNative.p2pFlush(); + mServiceDiscReqId = null; + replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_SUCCEEDED); + } else { + replyToMessage(message, WifiP2pManager.STOP_DISCOVERY_FAILED, + WifiP2pManager.ERROR); + } + break; + case CMD_P2P_IDLE_SHUTDOWN: + Log.d(TAG, "IdleShutDown message received"); + sendMessage(DISABLE_P2P); + break; + case WifiP2pMonitor.P2P_GO_NEGOTIATION_REQUEST_EVENT: + WifiP2pConfig config = (WifiP2pConfig) message.obj; + if (isConfigInvalid(config)) { + loge("Dropping GO neg request " + config); + break; + } + mSavedPeerConfig = config; + mAutonomousGroup = false; + mJoinExistingGroup = false; + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_FRESH, + config, GroupEvent.GROUP_UNKNOWN, Process.SYSTEM_UID, null); + smTransition(this, mUserAuthorizingNegotiationRequestState); + break; + case WifiP2pMonitor.P2P_INVITATION_RECEIVED_EVENT: + if (message.obj == null) { + Log.e(TAG, "Invalid argument(s)"); + break; + } + WifiP2pGroup group = (WifiP2pGroup) message.obj; + WifiP2pDevice owner = group.getOwner(); + if (owner == null) { + int id = group.getNetworkId(); + if (id < 0) { + loge("Ignored invitation from null owner"); + break; + } + + String addr = mGroups.getOwnerAddr(id); + if (addr != null) { + group.setOwner(new WifiP2pDevice(addr)); + owner = group.getOwner(); + } else { + loge("Ignored invitation from null owner"); + break; + } + } + config = new WifiP2pConfig(); + config.deviceAddress = group.getOwner().deviceAddress; + if (isConfigInvalid(config)) { + loge("Dropping invitation request " + config); + break; + } + mSavedPeerConfig = config; + + // Check if we have the owner in peer list and use appropriate + // wps method. Default is to use PBC. + if (owner != null && ((owner = mPeers.get(owner.deviceAddress)) != null)) { + if (owner.wpsPbcSupported()) { + mSavedPeerConfig.wps.setup = WpsInfo.PBC; + } else if (owner.wpsKeypadSupported()) { + mSavedPeerConfig.wps.setup = WpsInfo.KEYPAD; + } else if (owner.wpsDisplaySupported()) { + mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; + } + } + + mAutonomousGroup = false; + mJoinExistingGroup = true; + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_FRESH, + config, GroupEvent.GROUP_UNKNOWN, Process.SYSTEM_UID, null); + smTransition(this, mUserAuthorizingInviteRequestState); + break; + case WifiP2pMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: + case WifiP2pMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: + // We let the supplicant handle the provision discovery response + // and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. + // Handling provision discovery and issuing a p2p_connect before + // group negotiation comes through causes issues + break; + case WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: + if (message.obj == null) { + Log.e(TAG, "Illegal argument(s)"); + break; + } + WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; + WifiP2pDevice device = provDisc.device; + if (device == null) { + loge("Device entry is null"); + break; + } + mSavedPeerConfig = new WifiP2pConfig(); + mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; + mSavedPeerConfig.deviceAddress = device.deviceAddress; + mSavedPeerConfig.wps.pin = provDisc.pin; + if (SdkLevel.isAtLeastV() && provDisc.getVendorData() != null) { + mSavedPeerConfig.setVendorData(provDisc.getVendorData()); + } + + notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress); + mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED); + sendPeersChangedBroadcast(); + smTransition(this, mUserAuthorizingNegotiationRequestState); + break; + case WifiP2pManager.CREATE_GROUP: { + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (packageName == null) { + replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, + WifiP2pManager.ERROR); + break; + } + int uid = message.sendingUid; + String attributionTag = getCallingFeatureId(uid, message.replyTo); + Bundle extras = message.getData() + .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); + boolean hasPermission; + if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { + hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( + packageName, + attributionTag, + uid, false); + } else { + hasPermission = checkNearbyDevicesPermission(uid, packageName, + extras, "CREATE_GROUP", message.obj); + } + if (!hasPermission) { + replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, + WifiP2pManager.ERROR); + // remain at this state. + break; + } + mAutonomousGroup = true; + int netId = message.arg1; + config = extras.getParcelable(WifiP2pManager.EXTRA_PARAM_KEY_CONFIG); + mLastCallerInfoManager.put(config == null + ? WifiManager.API_P2P_CREATE_GROUP + : WifiManager.API_P2P_CREATE_GROUP_P2P_CONFIG, + Process.myTid(), uid, 0, packageName, true); + boolean ret = false; + if (config != null) { + if (isConfigValidAsGroup(config)) { + mConnectionPkgName = packageName; + if (mVerboseLoggingEnabled) { + logd("FAST_CONNECTION GO band freq: " + + getGroupOwnerBandToString(config.groupOwnerBand)); + } + reportConnectionEventTakeBugReportIfOverlapped( + P2pConnectionEvent.CONNECTION_FAST, + config, GroupEvent.GROUP_OWNER, uid, attributionTag); + ret = mWifiNative.p2pGroupAdd(config, false); + } + } else if (netId == WifiP2pGroup.NETWORK_ID_PERSISTENT) { + // check if the go persistent group is present. + netId = mGroups.getNetworkId(mThisDevice.deviceAddress); + if (netId != -1) { + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_REINVOKE, + null, GroupEvent.GROUP_OWNER, uid, attributionTag); + ret = mWifiNative.p2pGroupAdd(netId); + } else { + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_LOCAL, + null, GroupEvent.GROUP_OWNER, uid, attributionTag); + ret = mWifiNative.p2pGroupAdd(true); + } + } else { + mWifiP2pMetrics.startConnectionEvent( + P2pConnectionEvent.CONNECTION_LOCAL, + null, GroupEvent.GROUP_OWNER, uid, attributionTag); + ret = mWifiNative.p2pGroupAdd(false); + } + + if (ret) { + replyToMessage(message, WifiP2pManager.CREATE_GROUP_SUCCEEDED); + smTransition(this, mGroupNegotiationState); + } else { + mConnectionPkgName = SHARED_PKG_NAME; + replyToMessage(message, WifiP2pManager.CREATE_GROUP_FAILED, + WifiP2pManager.ERROR); + // remain at this state. + String errorMsg = "P2P group creating failed"; + if (mVerboseLoggingEnabled) logd(getName() + errorMsg); + if (mWifiP2pMetrics.isP2pFastConnectionType()) { + takeBugReportP2pFailureIfNeeded("Wi-Fi BugReport (P2P " + + mWifiP2pMetrics.getP2pGroupRoleString() + + " creation failure)", errorMsg); + } + mWifiP2pMetrics.endConnectionEvent( + P2pConnectionEvent.CLF_CREATE_GROUP_FAILED); + } + break; + } + case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: + if (message.obj == null) { + Log.e(TAG, "Invalid argument(s)"); + break; + } + mGroup = (WifiP2pGroup) message.obj; + if (mVerboseLoggingEnabled) logd(getName() + " group started"); + if (mGroup.isGroupOwner() + && EMPTY_DEVICE_ADDRESS.equals(mGroup.getOwner().deviceAddress)) { + // wpa_supplicant doesn't set own device address to go_dev_addr. + mGroup.getOwner().deviceAddress = mThisDevice.deviceAddress; + } + // We hit this scenario when a persistent group is reinvoked + if (mGroup.getNetworkId() == WifiP2pGroup.NETWORK_ID_PERSISTENT) { + mAutonomousGroup = false; + deferMessage(message); + smTransition(this, mGroupNegotiationState); + } else { + loge("Unexpected group creation, remove " + mGroup); + mWifiNative.p2pGroupRemove(mGroup.getInterface()); + mGroup = null; + } + break; + case WifiP2pManager.START_LISTEN: + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (packageName == null) { + replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); + break; + } + int uid = message.sendingUid; + int listenType = message.arg1; + if (listenType == WifiP2pManager.WIFI_P2P_EXT_LISTEN_WITH_PARAMS + && !SdkLevel.isAtLeastV()) { + replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); + break; + } + Bundle extras = message.getData() + .getBundle(WifiP2pManager.EXTRA_PARAM_KEY_BUNDLE); + WifiP2pExtListenParams extListenParams = SdkLevel.isAtLeastV() + && (listenType == WifiP2pManager.WIFI_P2P_EXT_LISTEN_WITH_PARAMS) + ? extras.getParcelable( + WifiP2pManager.EXTRA_PARAM_KEY_EXT_LISTEN_PARAMS, + WifiP2pExtListenParams.class) + : null; + boolean hasPermission; + if (isPlatformOrTargetSdkLessThanT(packageName, uid)) { + hasPermission = mWifiPermissionsUtil.checkCanAccessWifiDirect( + packageName, + getCallingFeatureId(message.sendingUid, message.replyTo), + uid, true); + } else { + hasPermission = checkNearbyDevicesPermission(uid, packageName, + extras, "START_LISTEN", message.obj); + } + if (!hasPermission) { + replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); + break; + } + mLastCallerInfoManager.put(WifiManager.API_P2P_START_LISTENING, + Process.myTid(), uid, 0, packageName, true); + if (mVerboseLoggingEnabled) logd(getName() + " start listen mode"); + mWifiNative.p2pStopFind(); + if (mWifiNative.p2pExtListen(true, + mContext.getResources().getInteger( + R.integer.config_wifiP2pExtListenPeriodMs), + mContext.getResources().getInteger( + R.integer.config_wifiP2pExtListenIntervalMs), + extListenParams)) { + replyToMessage(message, WifiP2pManager.START_LISTEN_SUCCEEDED); + sendP2pListenChangedBroadcast(true); + } else { + replyToMessage(message, WifiP2pManager.START_LISTEN_FAILED); + } + break; + case WifiP2pManager.STOP_LISTEN: + mLastCallerInfoManager.put(WifiManager.API_P2P_STOP_LISTENING, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); + if (mVerboseLoggingEnabled) logd(getName() + " stop listen mode"); + if (mWifiNative.p2pExtListen(false, 0, 0, null)) { + replyToMessage(message, WifiP2pManager.STOP_LISTEN_SUCCEEDED); + sendP2pListenChangedBroadcast(false); + } else { + replyToMessage(message, WifiP2pManager.STOP_LISTEN_FAILED); + } + mWifiNative.p2pStopFind(); + break; + case WifiP2pManager.SET_CHANNEL: + if (!checkNetworkSettingsOrNetworkStackOrOverrideWifiConfigPermission( + message.sendingUid)) { + loge("Permission violation - none of NETWORK_SETTING, NETWORK_STACK," + + " or OVERRIDE_WIFI_CONFIG permission, uid = " + + message.sendingUid); + replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED, + WifiP2pManager.ERROR); + break; + } + if (message.obj == null) { + Log.e(TAG, "Illegal arguments(s)"); + break; + } + mLastCallerInfoManager.put(WifiManager.API_P2P_SET_CHANNELS, + Process.myTid(), message.sendingUid, 0, + getCallingPkgName(message.sendingUid, message.replyTo), true); + Bundle p2pChannels = (Bundle) message.obj; + mUserListenChannel = p2pChannels.getInt("lc", 0); + mUserOperatingChannel = p2pChannels.getInt("oc", 0); + if (updateP2pChannels()) { + replyToMessage(message, WifiP2pManager.SET_CHANNEL_SUCCEEDED); + } else { + replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED); + } + break; + case WifiP2pManager.INITIATOR_REPORT_NFC_HANDOVER: + String handoverSelect = null; + + if (message.obj != null) { + handoverSelect = ((Bundle) message.obj) + .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); + } + + if (handoverSelect != null + && mWifiNative.initiatorReportNfcHandover(handoverSelect)) { + replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); + smTransition(this, mGroupCreatingState); + } else { + replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); + } + break; + case WifiP2pManager.RESPONDER_REPORT_NFC_HANDOVER: + String handoverRequest = null; + + if (message.obj != null) { + handoverRequest = ((Bundle) message.obj) + .getString(WifiP2pManager.EXTRA_HANDOVER_MESSAGE); + } + + if (handoverRequest != null + && mWifiNative.responderReportNfcHandover(handoverRequest)) { + replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_SUCCEEDED); + smTransition(this, mGroupCreatingState); + } else { + replyToMessage(message, WifiP2pManager.REPORT_NFC_HANDOVER_FAILED); + } + break; + default: + return NOT_HANDLED; + } + return HANDLED; + } + + @Override + public String getMessageLogRec(int what) { + return P2pStateMachine.class.getSimpleName() + "." + + this.getClass().getSimpleName() + + "." + getWhatToString(what); + } + } + class P2pRejectWaitState extends RunnerState { /** @@ -4058,7 +4661,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); } } - transitionTo(mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } else { loge( "Stale P2p rejection resume after delay - cached index: " @@ -4128,7 +4735,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_TIMEOUT); handleGroupCreationFailure( WifiP2pManager.GROUP_CREATION_FAILURE_REASON_TIMED_OUT); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } break; case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: @@ -4180,6 +4791,16 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // discovery or for a pending user action, but at the framework // level, we always treat cancel as succeeded and enter // an inactive state + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (mFeatureFlags.p2pOwnership() + && mConnectionPkgName != packageName + && mConnectionPkgName != SHARED_PKG_NAME) { + replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, + WifiP2pManager.BUSY); + logd("Cancel connect requested by " + packageName + + " when connection is initiated by " + mConnectionPkgName); + break; + } mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, Process.myTid(), message.sendingUid, 0, getCallingPkgName(message.sendingUid, message.replyTo), true); @@ -4290,7 +4911,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mWifiNative.p2pCancelConnect(); handleGroupCreationFailure( WifiP2pManager.GROUP_CREATION_FAILURE_REASON_USER_REJECTED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } break; case PEER_CONNECTION_USER_CONFIRM: @@ -4304,7 +4929,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { loge("provision discovery failed status: " + message.arg1); handleGroupCreationFailure(WifiP2pManager .GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: { if (!handleSetConnectionResult(message, @@ -4384,13 +5013,21 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (mVerboseLoggingEnabled) { logd("User rejected invitation " + mSavedPeerConfig); } - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: loge("provision discovery failed status: " + message.arg1); handleGroupCreationFailure(WifiP2pManager .GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: if (!handleSetConnectionResult(message, @@ -4547,7 +5184,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_PROV_DISC_FAIL); handleGroupCreationFailure(WifiP2pManager .GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; default: return NOT_HANDLED; @@ -4618,7 +5259,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mGroup.setNetworkId(mGroups.getNetworkId(devAddr, mGroup.getNetworkName())); } - if (mGroup.isGroupOwner()) { // Setting an idle time out on GO causes issues with certain scenarios // on clients where it can be off-channel for longer and with the power @@ -4648,7 +5288,12 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } break; } - + if (mOwnershipMap.size() >= MAX_NUM_GROUP) { + Log.wtf(TAG, "group size= " + mOwnershipMap.size() + + " exceeds max number of p2p group supported"); + } + mOwnershipMap.put( + mConnectionPkgName, new WifiP2pGroupInfo(mGroup, null)); mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S); Log.d(TAG, "start Ip client with provisioning mode: " + mSavedPeerConfig.getGroupClientIpProvisioningMode()); @@ -4687,6 +5332,15 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (!interfaces.contains(mGroup.getInterface())) break; Log.d(TAG, "tether " + mGroup.getInterface() + " ready"); + if (mOwnershipMap.size() > MAX_NUM_GROUP) { + Log.wtf(TAG, "group size= " + mOwnershipMap.size() + + " exceeds max number of p2p group supported"); + } + WifiP2pGroupInfo groupInfo = mOwnershipMap.putIfAbsent(mConnectionPkgName, + new WifiP2pGroupInfo(mGroup, null)); + if (groupInfo != null) { + groupInfo.p2pGroup = mGroup; + } smTransition(this, mGroupCreatedState); break; case WifiP2pMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT: @@ -4708,7 +5362,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_GROUP_REMOVED); handleGroupCreationFailure( WifiP2pManager.GROUP_CREATION_FAILURE_REASON_GROUP_REMOVED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT: // A group formation failure is always followed by @@ -4780,7 +5438,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_INVITATION_FAIL); handleGroupCreationFailure( WifiP2pManager.GROUP_CREATION_FAILURE_REASON_INVITATION_FAILED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } } break; case WifiP2pMonitor.P2P_PROV_DISC_FAILURE_EVENT: @@ -4789,7 +5451,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_GROUP_REMOVED); handleGroupCreationFailure(WifiP2pManager .GROUP_CREATION_FAILURE_REASON_PROVISION_DISCOVERY_FAILED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pMonitor.AP_STA_CONNECTED_EVENT: case WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT: @@ -4940,7 +5606,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { P2pConnectionEvent.CLF_USER_REJECT); handleGroupCreationFailure( WifiP2pManager.GROUP_CREATION_FAILURE_REASON_USER_REJECTED); - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case DROP_WIFI_USER_ACCEPT: mFrequencyConflictDialog = null; @@ -4953,7 +5623,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (mVerboseLoggingEnabled) { logd(getName() + "Wifi disconnected, retry p2p"); } - smTransition(this, mInactiveState); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } p2pReconnect(); break; default: @@ -5015,7 +5689,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // In case of a negotiation group, connection changed is sent // after a client joins. For autonomous, send now if (mAutonomousGroup) { - onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), eraseOwnDeviceAddress(mGroup)); + onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); } @@ -5060,8 +5735,14 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { } else { loge("Connect on null device address, ignore"); } + if (!mAutonomousGroup && mGroup.getClientList().size() == 1) { + onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); + } onPeerClientJoined(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); break; } @@ -5085,7 +5766,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // when this happens at exit() } else { onPeerClientDisconnected(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); // Notify when a client disconnects from group sendP2pConnectionChangedBroadcast(); } @@ -5176,7 +5858,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { loge("Failed to add iface to local network " + e); } onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); break; case IPC_PROVISIONING_SUCCESS: @@ -5202,7 +5885,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (goInterfaceMacAddress == null) { setWifiP2pInfoOnGroupFormationWithInetAddress(null); onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); break; } @@ -5214,7 +5898,8 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { NetworkInterface.getByName(mGroup.getInterface())); setWifiP2pInfoOnGroupFormationWithInetAddress(goIp); onGroupCreated(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); } catch (UnknownHostException | SocketException e) { loge("Unable to retrieve link-local IPv6 address of group owner " @@ -5226,21 +5911,32 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { loge("IP provisioning failed"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); break; - case WifiP2pManager.REMOVE_GROUP: + case WifiP2pManager.REMOVE_GROUP: { + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (!checkIfPackageIsGroupOwner(packageName) + && message.sendingUid != Process.SYSTEM_UID) { + replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, + WifiP2pManager.BUSY); + break; + } mLastCallerInfoManager.put(WifiManager.API_P2P_REMOVE_GROUP, - Process.myTid(), message.sendingUid, 0, - getCallingPkgName(message.sendingUid, message.replyTo), true); + Process.myTid(), message.sendingUid, 0, packageName, true); if (mVerboseLoggingEnabled) logd(getName() + " remove group"); if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { smTransition(this, mOngoingGroupRemovalState); replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); } else { - handleGroupRemoved(); - smTransition(this, mInactiveState); + handleGroupRemoved(packageName); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } replyToMessage(message, WifiP2pManager.REMOVE_GROUP_FAILED, WifiP2pManager.ERROR); } break; + } case WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT: // We do not listen to NETWORK_DISCONNECTION_EVENT for group removal // handling since supplicant actually tries to reconnect after a temporary @@ -5253,8 +5949,26 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // Treating network disconnection as group removal causes race conditions // since supplicant would still maintain the group at that stage. if (mVerboseLoggingEnabled) logd(getName() + " group removed"); - handleGroupRemoved(); - smTransition(this, mInactiveState); + + if (message.obj == null) { + Log.e(TAG, "Illegal arguments"); + break; + } + String pkgName = SHARED_PKG_NAME; + WifiP2pGroup group = (WifiP2pGroup) message.obj; + for (Map.Entry<String, WifiP2pGroupInfo> entry : mOwnershipMap.entrySet()) { + if (entry.getValue().p2pGroup.getInterface().equals( + group.getInterface())) { + pkgName = entry.getKey(); + break; + } + } + handleGroupRemoved(pkgName); + if (mFeatureFlags.p2pOwnership()) { + smTransition(this, mIdleState); + } else { + smTransition(this, mInactiveState); + } break; case WifiP2pMonitor.P2P_DEVICE_LOST_EVENT: if (message.obj == null) { @@ -5328,6 +6042,12 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { // remain at this state. break; } + if (!checkIfPackageIsGroupOwner(packageName)) { + replyToMessage(message, WifiP2pManager.CONNECT_FAILED, + WifiP2pManager.BUSY); + logd("Cannot perform invitation connection due to lack of ownership"); + break; + } mLastCallerInfoManager.put(WifiManager.API_P2P_CONNECT, Process.myTid(), uid, 0, packageName, true); WifiP2pConfig config = (WifiP2pConfig) @@ -5343,6 +6063,9 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); + if (mOwnershipMap.containsKey(packageName)) { + mConnectionPkgName = packageName; + } } else { replyToMessage(message, WifiP2pManager.CONNECT_FAILED, WifiP2pManager.ERROR); @@ -5418,7 +6141,17 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { case WifiP2pMonitor.P2P_GROUP_STARTED_EVENT: loge("Duplicate group creation event notice, ignore"); break; - case WifiP2pManager.CANCEL_CONNECT: + case WifiP2pManager.CANCEL_CONNECT: { + String packageName = getCallingPkgName(message.sendingUid, message.replyTo); + if (mFeatureFlags.p2pOwnership() + && mConnectionPkgName != packageName + && mConnectionPkgName != SHARED_PKG_NAME) { + replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED, + WifiP2pManager.BUSY); + logd("Cancel invitation connect requested by " + packageName + + " when connection is initiated by " + mConnectionPkgName); + break; + } mLastCallerInfoManager.put(WifiManager.API_P2P_CANCEL_CONNECT, Process.myTid(), message.sendingUid, 0, getCallingPkgName(message.sendingUid, message.replyTo), true); @@ -5438,11 +6171,13 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED); break; + } case WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT: if (mGroup != null) { mGroup.setFrequency(message.arg1); onFrequencyChanged(new WifiP2pInfo(mWifiP2pInfo), - eraseOwnDeviceAddress(mGroup)); + eraseOwnDeviceAddress(mGroup), + generateCallbackList(mGroup)); sendP2pConnectionChangedBroadcast(); } break; @@ -5560,7 +6295,6 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { break; case PEER_CONNECTION_USER_REJECT: if (mVerboseLoggingEnabled) logd("User rejected incoming request"); - mSavedPeerConfig.invalidate(); smTransition(this, mGroupCreatedState); break; case WifiP2pManager.SET_CONNECTION_REQUEST_RESULT: @@ -5765,6 +6499,12 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { broadcastOptions.setRequireNoneOfPermissions(excludedPermissionsList.toArray( new String[0])); } + // remove package name from intent for ownership + if (mFeatureFlags.p2pOwnership() + && intent.getAction().equals( + WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { + intent = getP2pConnectionChangedIntent(true); + } context.sendBroadcast(intent, null, broadcastOptions.toBundle()); } } @@ -5789,18 +6529,25 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendBroadcastWithExcludedPermissions(intent, null); } - private Intent getP2pConnectionChangedIntent() { + private Intent getP2pConnectionChangedIntent(boolean tethering) { Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, new WifiP2pInfo(mWifiP2pInfo)); intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, makeNetworkInfo()); intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, eraseOwnDeviceAddress(mGroup)); + if (tethering || !mFeatureFlags.p2pOwnership()) return intent; + if (!mOwnershipMap.containsKey(SHARED_PKG_NAME)) { + for (String pkg : mOwnershipMap.keySet()) { + intent.setPackage(pkg); + logd("sending p2p connection changed broadcast to only " + pkg); + } + } return intent; } private void sendP2pConnectionChangedBroadcast() { if (mVerboseLoggingEnabled) logd("sending p2p connection changed broadcast"); - Intent intent = getP2pConnectionChangedIntent(); + Intent intent = getP2pConnectionChangedIntent(false); if (SdkLevel.isAtLeastU()) { // First send direct foreground broadcast to Tethering package and system service // with same android.permission.MAINLINE_NETWORK_STACK @@ -5907,7 +6654,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (TextUtils.isEmpty(tetheringServicePackage)) return false; Log.i(TAG, "sending p2p tether request broadcast to " + tetheringServicePackage + " with permission " + Arrays.toString(permissions)); - Intent intent = getP2pConnectionChangedIntent(); + Intent intent = getP2pConnectionChangedIntent(true); if (setAdditionalFlags) { intent.addFlags(flags); } @@ -5919,7 +6666,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { private void sendBroadcastWithMainlineNetworkStackPermissionPostU() { String[] receiverPermissions = RECEIVER_PERMISSIONS_MAINLINE_NETWORK_STACK; - Intent intent = getP2pConnectionChangedIntent(); + Intent intent = getP2pConnectionChangedIntent(true); // Adding the flag to allow recipient to run at foreground priority with a shorter // timeout interval. intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -6697,6 +7444,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mWifiP2pInfo.groupFormed = true; mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner(); mWifiP2pInfo.groupOwnerAddress = serverAddress; + WifiP2pGroupInfo groupInfo = mOwnershipMap.putIfAbsent( + mConnectionPkgName, new WifiP2pGroupInfo(null, mWifiP2pInfo)); + if (groupInfo != null) { + groupInfo.p2pInfo = mWifiP2pInfo; + } } private void resetWifiP2pInfo() { @@ -6893,7 +7645,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { mWifiNative.setDeviceName(mThisDevice.deviceName); // DIRECT-XY-DEVICENAME (XY is randomly generated) - mWifiNative.setP2pSsidPostfix("-" + mThisDevice.deviceName); + mWifiNative.setP2pSsidPostfix(generateP2pSsidPostfix(mThisDevice.deviceName)); mWifiNative.setP2pDeviceType(mThisDevice.primaryDeviceType); // Supplicant defaults to using virtual display with display // which refers to a remote display. Use physical_display @@ -6991,7 +7743,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendDisconnectWifiRequest(false); } - private void handleGroupRemoved() { + private void handleGroupRemoved(String packageName) { if (mGroup.isGroupOwner()) { // {@link com.android.server.connectivity.Tethering} listens to // {@link WifiP2pManager#WIFI_P2P_CONNECTION_CHANGED_ACTION} @@ -7029,6 +7781,12 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { sendPeersChangedBroadcast(); } + if (mOwnershipMap.containsKey(packageName)) { + mOwnershipMap.remove(packageName); + } else { + mOwnershipMap.remove(SHARED_PKG_NAME); + } + mGroup = null; mPeersLostDuringConnection.clear(); mServiceDiscReqId = null; @@ -7739,7 +8497,7 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub { if (WifiP2pManager.CONNECTION_REQUEST_ACCEPT == message.arg1) { if (WifiP2pManager.ExternalApproverRequestListener.REQUEST_TYPE_NEGOTIATION == requestType - && WpsInfo.KEYPAD == mSavedPeerConfig.wps.setup) { + && WpsInfo.DISPLAY == mSavedPeerConfig.wps.setup) { sendMessage(PEER_CONNECTION_USER_CONFIRM); } else { Bundle extras = message.getData().getBundle( diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java index 85e5e65c50..387d888af1 100644 --- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java +++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java @@ -346,7 +346,7 @@ public class RttServiceImpl extends IWifiRttManager.Stub { intentFilter = new IntentFilter(); intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION); - mContext.registerReceiver(new BroadcastReceiver() { + mContext.registerReceiverForAllUsers(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (mVerboseLoggingEnabled) { @@ -358,7 +358,7 @@ public class RttServiceImpl extends IWifiRttManager.Stub { disable(); } } - }, intentFilter); + }, intentFilter, null, mRttServiceSynchronized.mHandler); mHalDeviceManager.initialize(); mHalDeviceManager.registerStatusListener(() -> { diff --git a/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java b/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java index 862b4cbdab..713edd792e 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java +++ b/service/java/com/android/server/wifi/scanner/WifiScannerInternal.java @@ -93,6 +93,12 @@ public abstract class WifiScannerInternal { } @Override + public void onFullResults(List<ScanResult> fullScanResult) { + mWifiThreadRunner.post(() -> fullScanResult.forEach(mScanListener::onFullResult), + TAG + "#onFullResults"); + } + + @Override public void onSingleScanCompleted() { // Internal scan listener doesn't need to handle this. } diff --git a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java index 2c07b4cc5a..4dead3e34b 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java @@ -244,7 +244,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { return; } final ExternalClientInfo client = new ExternalClientInfo(uid, packageName, - listener); + listener, featureId); client.register(); localLog("register scan listener: " + client + " AttributionTag " + featureId); logScanRequest("registerScanListener", client, null, null, null); @@ -298,13 +298,13 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { mWifiThreadRunner.post(() -> { ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener); if (client == null) { - client = new ExternalClientInfo(uid, packageName, listener); + client = new ExternalClientInfo(uid, packageName, listener, featureId); client.register(); } localLog("start background scan: " + client + " package " + packageName); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_START_BACKGROUND_SCAN; - msg.obj = new ScanParams(listener, settings, workSource); + msg.obj = new ScanParams(listener, settings, workSource, featureId); msg.sendingUid = uid; mBackgroundScanStateMachine.sendMessage(msg); }, TAG + "#startBackgroundScan"); @@ -332,7 +332,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { localLog("stop background scan: " + client); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_STOP_BACKGROUND_SCAN; - msg.obj = new ScanParams(listener, null, null); + msg.obj = new ScanParams(listener, null, null, featureId); msg.sendingUid = uid; mBackgroundScanStateMachine.sendMessage(msg); } @@ -363,8 +363,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { public String featureId; ScanParams(IWifiScannerListener listener, WifiScanner.ScanSettings settings, - WorkSource workSource) { - this(listener, settings, null, workSource, null, null); + WorkSource workSource, String featureId) { + this(listener, settings, null, workSource, null, featureId); } ScanParams(IWifiScannerListener listener, WifiScanner.ScanSettings settings, @@ -399,14 +399,14 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { mWifiThreadRunner.post(() -> { ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener); if (client == null) { - client = new ExternalClientInfo(uid, packageName, listener); + client = new ExternalClientInfo(uid, packageName, listener, featureId); client.register(); } localLog("start scan: " + client + " package " + packageName + " AttributionTag " + featureId); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_START_SINGLE_SCAN; - msg.obj = new ScanParams(listener, settings, workSource); + msg.obj = new ScanParams(listener, settings, workSource, featureId); msg.sendingUid = uid; mSingleScanStateMachine.sendMessage(msg); }, TAG + "#startScan"); @@ -434,7 +434,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { localLog("stop scan: " + client + " AttributionTag " + featureId); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_STOP_SINGLE_SCAN; - msg.obj = new ScanParams(listener, null, null); + msg.obj = new ScanParams(listener, null, null, featureId); msg.sendingUid = uid; mSingleScanStateMachine.sendMessage(msg); }, TAG + "#stopScan"); @@ -504,7 +504,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { localLog("start pno scan: " + clientInfoLog + " AttributionTag " + featureId); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_START_PNO_SCAN; - msg.obj = new ScanParams(listener, scanSettings, pnoSettings, null, packageName, null); + msg.obj = new ScanParams(listener, scanSettings, pnoSettings, null, packageName, + featureId); msg.sendingUid = uid; mPnoScanStateMachine.sendMessage(msg); }, TAG + "#startPnoScan"); @@ -528,15 +529,10 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { return; } mWifiThreadRunner.post(() -> { - ExternalClientInfo client = (ExternalClientInfo) mClients.get(listener); - if (client == null) { - Log.e(TAG, "listener not found " + listener); - return; - } - localLog("stop pno scan: " + client + " AttributionTag " + featureId); + localLog("stop pno scan: " + packageName + " AttributionTag " + featureId); Message msg = Message.obtain(); msg.what = WifiScanner.CMD_STOP_PNO_SCAN; - msg.obj = new ScanParams(listener, null, null); + msg.obj = new ScanParams(listener, null, null, featureId); msg.sendingUid = uid; mPnoScanStateMachine.sendMessage(msg); }, TAG + "#stopPnoScan"); @@ -653,7 +649,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { private static final int BASE = Protocol.BASE_WIFI_SCANNER_SERVICE; private static final int CMD_SCAN_RESULTS_AVAILABLE = BASE + 0; - private static final int CMD_FULL_SCAN_RESULTS = BASE + 1; + private static final int CMD_FULL_SCAN_SINGLE_RESULT = BASE + 1; + private static final int CMD_FULL_SCAN_ALL_RESULTS = BASE + 2; private static final int CMD_SCAN_PAUSED = BASE + 8; private static final int CMD_SCAN_RESTARTED = BASE + 9; private static final int CMD_SCAN_FAILED = BASE + 10; @@ -893,6 +890,70 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } + private String getWhatToStringInternal(int what) { + switch (what) { + case WifiScanner.CMD_START_BACKGROUND_SCAN: + return "WifiScanner.CMD_START_BACKGROUND_SCAN"; + case WifiScanner.CMD_STOP_BACKGROUND_SCAN: + return "WifiScanner.CMD_STOP_BACKGROUND_SCAN"; + case WifiScanner.CMD_GET_SCAN_RESULTS: + return "WifiScanner.CMD_GET_SCAN_RESULTS"; + case WifiScanner.CMD_SCAN_RESULT: + return "WifiScanner.CMD_SCAN_RESULT"; + case WifiScanner.CMD_CACHED_SCAN_DATA: + return "WifiScanner.CMD_CACHED_SCAN_DATA"; + case WifiScanner.CMD_OP_SUCCEEDED: + return "WifiScanner.CMD_OP_SUCCEEDED"; + case WifiScanner.CMD_OP_FAILED: + return "WifiScanner.CMD_OP_FAILED"; + case WifiScanner.CMD_FULL_SCAN_RESULT: + return "WifiScanner.CMD_FULL_SCAN_RESULT"; + case WifiScanner.CMD_START_SINGLE_SCAN: + return "WifiScanner.CMD_START_SINGLE_SCAN"; + case WifiScanner.CMD_STOP_SINGLE_SCAN: + return "WifiScanner.CMD_STOP_SINGLE_SCAN"; + case WifiScanner.CMD_SINGLE_SCAN_COMPLETED: + return "WifiScanner.CMD_SINGLE_SCAN_COMPLETED"; + case WifiScanner.CMD_START_PNO_SCAN: + return "WifiScanner.CMD_START_PNO_SCAN"; + case WifiScanner.CMD_STOP_PNO_SCAN: + return "WifiScanner.CMD_STOP_PNO_SCAN"; + case WifiScanner.CMD_PNO_NETWORK_FOUND: + return "WifiScanner.CMD_PNO_NETWORK_FOUND"; + case WifiScanner.CMD_REGISTER_SCAN_LISTENER: + return "WifiScanner.CMD_REGISTER_SCAN_LISTENER"; + case WifiScanner.CMD_DEREGISTER_SCAN_LISTENER: + return "WifiScanner.CMD_DEREGISTER_SCAN_LISTENER"; + case WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS: + return "WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS"; + case WifiScanner.CMD_ENABLE: + return "WifiScanner.CMD_ENABLE"; + case WifiScanner.CMD_DISABLE: + return "WifiScanner.CMD_DISABLE"; + case CMD_SCAN_RESULTS_AVAILABLE: + return "CMD_SCAN_RESULTS_AVAILABLE"; + case CMD_FULL_SCAN_SINGLE_RESULT: + return "CMD_FULL_SCAN_SINGLE_RESULT"; + case CMD_FULL_SCAN_ALL_RESULTS: + return "CMD_FULL_SCAN_ALL_RESULTS"; + case CMD_SCAN_PAUSED: + return "CMD_SCAN_PAUSED"; + case CMD_SCAN_RESTARTED: + return "CMD_SCAN_RESTARTED"; + case CMD_SCAN_FAILED: + return "CMD_SCAN_FAILED"; + case CMD_PNO_NETWORK_FOUND: + return "CMD_PNO_NETWORK_FOUND"; + case CMD_PNO_SCAN_FAILED: + return "CMD_PNO_SCAN_FAILED"; + case CMD_SW_PNO_SCAN: + return "CMD_SW_PNO_SCAN"; + default: + return "what:" + what; + } + } + + /** * State machine that holds the state of single scans. Scans should only be active in the * ScanningState. The pending scans and active scans maps are swapped when entering @@ -958,6 +1019,30 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } /** + * @return the string for msg.what + */ + @Override + protected String getWhatToString(int what) { + return getWhatToStringInternal(what); + } + + /** + * Return the additional string to be logged by LogRec, default + * + * @param msg that was processed + * @return information to be logged as a String + */ + @Override + protected String getLogRecString(Message msg) { + StringBuilder sb = new StringBuilder(); + sb.append(" "); + sb.append(Integer.toString(msg.arg1)); + sb.append(" "); + sb.append(Integer.toString(msg.arg2)); + return sb.toString(); + } + + /** * Tracks a single scan request across all the available scanner impls. * * a) Initiates the scan using the same ScanSettings across all the available impls. @@ -1029,6 +1114,16 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { public void onScanRequestFailed(int errorCode) { reportScanStatusForImpl(mImplIfaceName, STATUS_FAILED, errorCode); } + + @Override + public void onFullScanResults(List<ScanResult> fullScanResults, + int bucketsScanned) { + if (DBG) localLog("onFullScanResults received on iface " + mImplIfaceName); + if (fullScanResults == null || fullScanResults.isEmpty()) { + return; + } + reportFullScanResultsForImpl(mImplIfaceName, fullScanResults, bucketsScanned); + } } private static final int STATUS_PENDING = 0; @@ -1086,7 +1181,15 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { ScanResult fullScanResult, int bucketsScanned) { Integer status = mStatusPerImpl.get(implIfaceName); if (status != null && status == STATUS_PENDING) { - sendMessage(CMD_FULL_SCAN_RESULTS, 0, bucketsScanned, fullScanResult); + sendMessage(CMD_FULL_SCAN_SINGLE_RESULT, 0, bucketsScanned, fullScanResult); + } + } + + private void reportFullScanResultsForImpl(@NonNull String implIfaceName, + List<ScanResult> fullScanResults, int bucketsScanned) { + Integer status = mStatusPerImpl.get(implIfaceName); + if (status != null && status == STATUS_PENDING) { + sendMessage(CMD_FULL_SCAN_ALL_RESULTS, 0, bucketsScanned, fullScanResults); } } @@ -1223,7 +1326,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { case CMD_SCAN_RESULTS_AVAILABLE: if (DBG) localLog("ignored scan results available event"); return HANDLED; - case CMD_FULL_SCAN_RESULTS: + case CMD_FULL_SCAN_SINGLE_RESULT: + case CMD_FULL_SCAN_ALL_RESULTS: if (DBG) localLog("ignored full scan result event"); return HANDLED; case WifiScanner.CMD_GET_SINGLE_SCAN_RESULTS: @@ -1324,8 +1428,13 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } transitionTo(mIdleState); return HANDLED; - case CMD_FULL_SCAN_RESULTS: - reportFullScanResult((ScanResult) msg.obj, /* bucketsScanned */ msg.arg2); + case CMD_FULL_SCAN_SINGLE_RESULT: + reportFullScanSingleResult((ScanResult) msg.obj, + /* bucketsScanned */ msg.arg2); + return HANDLED; + case CMD_FULL_SCAN_ALL_RESULTS: + reportFullScanAllResults((List<ScanResult>) msg.obj, + /* bucketsScanned */ msg.arg2); return HANDLED; case CMD_SCAN_FAILED: mWifiMetrics.incrementScanReturnEntry( @@ -1595,7 +1704,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { clientHandlers.clear(); } - void reportFullScanResult(@NonNull ScanResult result, int bucketsScanned) { + void reportFullScanSingleResult(@NonNull ScanResult result, int bucketsScanned) { for (RequestInfo<ScanSettings> entry : mActiveScans) { if (ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, result, bucketsScanned, entry.settings, -1)) { @@ -1620,6 +1729,36 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } + void reportFullScanAllResults(@NonNull List<ScanResult> results, int bucketsScanned) { + List<ScanResult> matchedScanResults = new ArrayList<>(results.size()); + for (RequestInfo<ScanSettings> entry : mActiveScans) { + for (ScanResult result : results) { + if (ScanScheduleUtil.shouldReportFullScanResultForSettings(mChannelHelper, + result, bucketsScanned, entry.settings, -1)) { + matchedScanResults.add(result); + } + } + entry.clientInfo.reportEvent((listener) -> { + try { + listener.onFullResults(new ArrayList<>(matchedScanResults)); + } catch (RemoteException e) { + loge("Failed to call onFullResult: " + entry.clientInfo); + } + }); + matchedScanResults.clear(); + } + + for (RequestInfo<Void> entry : mSingleScanListeners) { + entry.clientInfo.reportEvent((listener) -> { + try { + listener.onFullResults(results); + } catch (RemoteException e) { + loge("Failed to call onFullResult: " + entry.clientInfo); + } + }); + } + } + void reportScanResults(@NonNull ScanData results) { if (results != null && results.getResults() != null) { if (results.getResults().length > 0) { @@ -1646,7 +1785,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } for (RequestInfo<Void> entry : mSingleScanListeners) { - logCallback("singleScanResults", entry.clientInfo, + logCallback("singleScanResults listener", entry.clientInfo, describeForLog(allResults)); entry.clientInfo.reportEvent((listener) -> { try { @@ -1772,7 +1911,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { @Override public void onFullScanResult(ScanResult fullScanResult, int bucketsScanned) { if (DBG) localLog("onFullScanResult received"); - sendMessage(CMD_FULL_SCAN_RESULTS, 0, bucketsScanned, fullScanResult); + sendMessage(CMD_FULL_SCAN_SINGLE_RESULT, 0, bucketsScanned, fullScanResult); } @Override @@ -1794,6 +1933,16 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { public void onScanRequestFailed(int errorCode) { sendMessage(CMD_SCAN_FAILED, errorCode); } + + @Override + public void onFullScanResults(List<ScanResult> fullScanResults, int bucketsScanned) { + if (DBG) localLog("onFullScanResult received"); + if (fullScanResults == null || fullScanResults.isEmpty()) { + return; + } + sendMessage(CMD_FULL_SCAN_ALL_RESULTS, 0, bucketsScanned, fullScanResults); + + } } class DefaultState extends State { @@ -1858,8 +2007,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { case CMD_SCAN_RESULTS_AVAILABLE: if (DBG) localLog("ignored scan results available event"); break; - - case CMD_FULL_SCAN_RESULTS: + case CMD_FULL_SCAN_SINGLE_RESULT: + case CMD_FULL_SCAN_ALL_RESULTS: if (DBG) localLog("ignored full scan result event"); break; @@ -1935,8 +2084,13 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { results != null ? results.length : 0); reportScanResults(results); break; - case CMD_FULL_SCAN_RESULTS: - reportFullScanResult((ScanResult) msg.obj, /* bucketsScanned */ msg.arg2); + case CMD_FULL_SCAN_SINGLE_RESULT: + reportFullScanSingleResult((ScanResult) msg.obj, + /* bucketsScanned */ msg.arg2); + break; + case CMD_FULL_SCAN_ALL_RESULTS: + reportFullScanAllResults((List<ScanResult>) msg.obj, + /* bucketsScanned */ msg.arg2); break; case CMD_SCAN_PAUSED: reportScanResults((ScanData[]) msg.obj); @@ -2112,7 +2266,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } - private void reportFullScanResult(ScanResult result, int bucketsScanned) { + private void reportFullScanSingleResult(ScanResult result, int bucketsScanned) { for (RequestInfo<ScanSettings> entry : mActiveBackgroundScans) { ClientInfo ci = entry.clientInfo; ScanSettings settings = entry.settings; @@ -2136,6 +2290,40 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } + private void reportFullScanAllResults(List<ScanResult> results, int bucketsScanned) { + List<ScanResult> copyResults = new ArrayList<>(results.size()); + for (ScanResult result : results) { + ScanResult newResult = new ScanResult(result); + if (result.informationElements != null) { + newResult.informationElements = result.informationElements.clone(); + } else { + newResult.informationElements = null; + } + copyResults.add(newResult); + } + List<ScanResult> matchedResults = new ArrayList<>(copyResults.size()); + for (RequestInfo<ScanSettings> entry : mActiveBackgroundScans) { + ClientInfo ci = entry.clientInfo; + ScanSettings settings = entry.settings; + + for (ScanResult result : results) { + if (mBackgroundScheduler.shouldReportFullScanResultForSettings( + result, bucketsScanned, settings)) { + + matchedResults.add(result); + } + entry.clientInfo.reportEvent((listener) -> { + try { + listener.onFullResults(new ArrayList<>(matchedResults)); + } catch (RemoteException e) { + loge("Failed to call onFullResult: " + ci); + } + }); + } + matchedResults.clear(); + } + } + private void reportScanResults(ScanData[] results) { if (results == null) { Log.d(TAG,"The results is null, nothing to report."); @@ -2239,6 +2427,30 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { setInitialState(mDefaultState); } + /** + * @return the string for msg.what + */ + @Override + protected String getWhatToString(int what) { + return getWhatToStringInternal(what); + } + + /** + * Return the additional string to be logged by LogRec, default + * + * @param msg that was processed + * @return information to be logged as a String + */ + @Override + protected String getLogRecString(Message msg) { + StringBuilder sb = new StringBuilder(); + sb.append(" "); + sb.append(Integer.toString(msg.arg1)); + sb.append(" "); + sb.append(Integer.toString(msg.arg2)); + return sb.toString(); + } + public void removePnoSettings(ClientInfo ci) { mActivePnoScans.removeAllForClient(ci); } @@ -2444,7 +2656,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { ClientInfo ci = mClients.get(scanParams.listener); if (ci == null) { ci = new ExternalClientInfo(msg.sendingUid, scanParams.packageName, - scanParams.listener); + scanParams.listener, scanParams.featureId); ci.register(); } if (scanParams.pnoSettings == null || scanParams.settings == null) { @@ -2504,7 +2716,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { ClientInfo ci = mClients.get(scanParams.listener); if (ci == null) { ci = new ExternalClientInfo(msg.sendingUid, scanParams.packageName, - scanParams.listener); + scanParams.listener, scanParams.featureId); ci.register(); } if (scanParams.pnoSettings == null || scanParams.settings == null) { @@ -2818,7 +3030,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { ClientInfo clientInfo = mClients.get(scanParams.listener); if (clientInfo == null) { clientInfo = new ExternalClientInfo(msg.sendingUid, - scanParams.packageName, scanParams.listener); + scanParams.packageName, scanParams.listener, + scanParams.featureId); clientInfo.register(); } @@ -2957,7 +3170,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { private void addInternalClient(ClientInfo ci) { if (mInternalClientInfo == null) { mInternalClientInfo = new InternalClientInfo(ci.getUid(), "internal", - new InternalListener()); + new InternalListener(), ci.mAttributionTag); mInternalClientInfo.register(); } else { Log.w(TAG, "Internal client for PNO already exists"); @@ -3042,7 +3255,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { Message msg = Message.obtain(); msg.what = WifiScanner.CMD_START_SINGLE_SCAN; msg.obj = new ScanParams(mInternalClientInfo.mListener, settings, - ClientModeImpl.WIFI_WORK_SOURCE); + ClientModeImpl.WIFI_WORK_SOURCE, "WIFI_INTERNAL"); mSingleScanStateMachine.sendMessage(msg); } mWifiMetrics.getScanMetrics().setWorkSource(ClientModeImpl.WIFI_WORK_SOURCE); @@ -3071,6 +3284,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { private abstract class ClientInfo { private final int mUid; private final String mPackageName; + private final String mAttributionTag; private final WorkSource mWorkSource; private boolean mScanWorkReported = false; protected final IWifiScannerListener mListener; @@ -3087,11 +3301,13 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } }; - ClientInfo(int uid, String packageName, IWifiScannerListener listener) { + ClientInfo(int uid, String packageName, IWifiScannerListener listener, + String attributionTag) { mUid = uid; mPackageName = packageName; mListener = listener; mWorkSource = new WorkSource(uid); + mAttributionTag = attributionTag; } /** @@ -3213,8 +3429,8 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { @Override public String toString() { - return "ClientInfo[uid=" + mUid + ", package=" + mPackageName + ", " + mListener - + "]"; + return "ClientInfo[uid=" + mUid + ", package=" + mPackageName + ", attributionTag=" + + mAttributionTag + ", " + mListener + "]"; } } @@ -3228,8 +3444,9 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { */ private boolean mDisconnected = false; - ExternalClientInfo(int uid, String packageName, IWifiScannerListener listener) { - super(uid, packageName, listener); + ExternalClientInfo(int uid, String packageName, IWifiScannerListener listener, + String attributionTag) { + super(uid, packageName, listener, attributionTag); if (DBG) localLog("New client, listener: " + listener); try { listener.asBinder().linkToDeath(mDeathRecipient, 0); @@ -3262,8 +3479,9 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { /** * The UID here is used to proxy the original external requester UID. */ - InternalClientInfo(int requesterUid, String packageName, IWifiScannerListener listener) { - super(requesterUid, packageName, listener); + InternalClientInfo(int requesterUid, String packageName, IWifiScannerListener listener, + String attributionTag) { + super(requesterUid, packageName, listener, attributionTag); } @Override @@ -3277,33 +3495,7 @@ public class WifiScanningServiceImpl extends IWifiScanner.Stub { } } - private static class InternalListener extends IWifiScannerListener.Stub { - InternalListener() { - } - - @Override - public void onSuccess() { - } - - @Override - public void onFailure(int reason, String description) { - } - - @Override - public void onResults(WifiScanner.ScanData[] results) { - } - - @Override - public void onFullResult(ScanResult fullScanResult) { - } - - @Override - public void onSingleScanCompleted() { - } - - @Override - public void onPnoNetworkFound(ScanResult[] results) { - } + private static class InternalListener extends IWifiScannerListener.Default { } private class LocalService extends WifiScannerInternal { diff --git a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java index 1fec135396..5f87b76596 100644 --- a/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java +++ b/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java @@ -422,12 +422,10 @@ public class WificondScannerImpl extends WifiScannerImpl implements Handler.Call if (mLastScanSettings.singleScanEventHandler != null) { if (mLastScanSettings.reportSingleScanFullResults) { - for (ScanResult scanResult : singleScanResults) { - // ignore buckets scanned since there is only one bucket for a single scan - mLastScanSettings.singleScanEventHandler.onFullScanResult(scanResult, - /* bucketsScanned */ 0); - } + mLastScanSettings.singleScanEventHandler + .onFullScanResults(singleScanResults, 0); } + Collections.sort(singleScanResults, SCAN_RESULT_SORT_COMPARATOR); mLatestSingleScanResult = new WifiScanner.ScanData(0, 0, 0, getScannedBandsInternal(mLastScanSettings.singleScanFreqs), diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java index bbc8d4b5e3..1c47ca8f11 100644 --- a/service/java/com/android/server/wifi/util/ApConfigUtil.java +++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java @@ -28,14 +28,14 @@ import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTO import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_WPA3_OWE; import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_WPA3_OWE_TRANSITION; import static android.net.wifi.SoftApCapability.SOFTAP_FEATURE_WPA3_SAE; +import static android.net.wifi.SoftApConfiguration.BAND_2GHZ; +import static android.net.wifi.SoftApConfiguration.BAND_5GHZ; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.Context; -import android.content.res.Resources; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; import android.net.wifi.SoftApCapability; @@ -45,9 +45,11 @@ import android.net.wifi.SoftApInfo; import android.net.wifi.WifiAvailableChannel; import android.net.wifi.WifiClient; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.nl80211.DeviceWiphyCapabilities; +import android.net.wifi.util.WifiResourceCache; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -59,6 +61,7 @@ import com.android.server.wifi.SoftApManager; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiSettingsConfigStore; import com.android.server.wifi.coex.CoexManager; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import java.util.ArrayList; @@ -241,7 +244,7 @@ public class ApConfigUtil { * @return The band includes 2.4Ghz when 2.4G SoftAp supported. */ public static @BandType int append24GToBandIf24GSupported(@BandType int targetBand, - Context context) { + WifiContext context) { if (isBandSupported(SoftApConfiguration.BAND_2GHZ, context)) { return targetBand | SoftApConfiguration.BAND_2GHZ; } @@ -255,7 +258,7 @@ public class ApConfigUtil { * @return The band includes 5Ghz when 5G SoftAp supported. */ public static @BandType int append5GToBandIf5GSupported(@BandType int targetBand, - Context context) { + WifiContext context) { if (isBandSupported(SoftApConfiguration.BAND_5GHZ, context)) { return targetBand | SoftApConfiguration.BAND_5GHZ; } @@ -298,7 +301,7 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if band is supported, false otherwise */ - public static boolean isBandSupported(@BandType int apBand, Context context) { + public static boolean isBandSupported(@BandType int apBand, WifiContext context) { if (!isBandValid(apBand)) { Log.e(TAG, "Invalid SoftAp band " + apBand); return false; @@ -377,7 +380,8 @@ public class ApConfigUtil { return unsafeFreqs; } - private static List<Integer> getConfiguredChannelList(Resources resources, @BandType int band) { + private static List<Integer> getConfiguredChannelList(WifiResourceCache resources, + @BandType int band) { switch (band) { case SoftApConfiguration.BAND_2GHZ: return convertStringToChannelList(resources.getString( @@ -397,8 +401,8 @@ public class ApConfigUtil { } private static List<Integer> addDfsChannelsIfNeeded(List<Integer> regulatoryList, - @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, Resources resources, - boolean inFrequencyMHz) { + @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, + WifiResourceCache resources, boolean inFrequencyMHz) { // Add DFS channels to the supported channel list if the device supports SoftAp // operation in the DFS channel. if (resources.getBoolean(R.bool.config_wifiSoftapAcsIncludeDfs) @@ -417,8 +421,8 @@ public class ApConfigUtil { } private static List<Integer> getWifiCondAvailableChannelsForBand( - @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, Resources resources, - boolean inFrequencyMHz) { + @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, + WifiResourceCache resources, boolean inFrequencyMHz) { List<Integer> regulatoryList = new ArrayList<Integer>(); // Get the allowed list of channel frequencies in MHz from wificond int[] regulatoryArray = wifiNative.getChannelsForBand(scannerBand); @@ -431,7 +435,8 @@ public class ApConfigUtil { } private static List<Integer> getHalAvailableChannelsForBand( - @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, Resources resources, + @WifiScanner.WifiBand int scannerBand, WifiNative wifiNative, + WifiResourceCache resources, boolean inFrequencyMHz) { // Try vendor HAL API to get the usable channel list. List<WifiAvailableChannel> usableChannelList = wifiNative.getUsableChannels( @@ -465,7 +470,7 @@ public class ApConfigUtil { * @return A list of frequencies that are allowed, null on error. */ public static List<Integer> getAvailableChannelFreqsForBand( - @BandType int band, WifiNative wifiNative, Resources resources, + @BandType int band, WifiNative wifiNative, WifiResourceCache resources, boolean inFrequencyMHz) { if (!isBandValid(band) || isMultiband(band)) { return null; @@ -527,7 +532,7 @@ public class ApConfigUtil { * @return a valid channel frequency on success, -1 on failure. */ public static int chooseApChannel(int apBand, @NonNull CoexManager coexManager, - @NonNull Resources resources, SoftApCapability capability) { + @NonNull WifiResourceCache resources, SoftApCapability capability) { if (!isBandValid(apBand)) { Log.e(TAG, "Invalid band: " + apBand); return -1; @@ -645,7 +650,7 @@ public class ApConfigUtil { */ public static SoftApConfiguration removeUnavailableBandsFromConfig( SoftApConfiguration config, SoftApCapability capability, CoexManager coexManager, - @NonNull Context context) { + @NonNull WifiContext context) { SoftApConfiguration.Builder builder = new SoftApConfiguration.Builder(config); try { @@ -694,6 +699,58 @@ public class ApConfigUtil { } /** + * Upgrades a single band config to 2 + 5 GHz dual band if the overlay is configured and + * there are no non-2GHz/5GHz bands that are configured and available with the current + * capabilities. + * </p> + * This is intended for configurations that were previously set with single band in a different + * country code that didn't support 2 + 5 GHz dual band, but the current country code does + * support 2 + 5 GHz dual band. + */ + public static SoftApConfiguration upgradeTo2g5gBridgedIfAvailableBandsAreSubset( + SoftApConfiguration config, SoftApCapability capability, @NonNull WifiContext context) { + // DBS requires SdkLevel S or above. + if (!SdkLevel.isAtLeastS()) { + return config; + } + + // Skip if overlay isn't set. + if (!context.getResourceCache().getBoolean( + R.bool.config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset)) { + return config; + } + + // Skip if config is already multi-band. + if (config.getBands().length != 1) { + return config; + } + + // Skip if 2 or 5 GHz aren't supported. + if (capability.getSupportedChannelList(BAND_2GHZ).length == 0 + || capability.getSupportedChannelList(BAND_5GHZ).length == 0) { + return config; + } + + // Skip if any non-2GHz/5GHz band is specified and supported. + int configuredBand = config.getBand(); + for (int band : SoftApConfiguration.BAND_TYPES) { + if (band == BAND_2GHZ || band == BAND_5GHZ) { + continue; + } + if ((configuredBand & band) != 0 + && capability.getSupportedChannelList(band).length > 0) { + return config; + } + } + + Log.i(TAG, "Temporarily upgrading config with band " + config.getBands()[0] + + " to 2 + 5GHz bridged."); + return new SoftApConfiguration.Builder(config) + .setBands(new int[]{BAND_2GHZ, BAND_2GHZ | BAND_5GHZ}) + .build(); + } + + /** * Remove all unsupported bands from the input band and return the resulting * (remaining) support bands. Unsupported bands are those which don't have channels available. * @@ -703,7 +760,7 @@ public class ApConfigUtil { * @return the available band which removed the unsupported band. * 0 when all of the band is not supported. */ - public static @BandType int removeUnsupportedBands(Context context, + public static @BandType int removeUnsupportedBands(WifiContext context, @NonNull int band) { int availableBand = band; for (int b : SoftApConfiguration.BAND_TYPES) { @@ -747,8 +804,8 @@ public class ApConfigUtil { * @return true if HAL support to map WPA3 transition mode to WPA3 in 6GHz band, * false otherwise. */ - public static boolean canHALConvertRestrictedSecurityTypeFor6GHz(@NonNull Resources resources, - @SoftApConfiguration.SecurityType int type) { + public static boolean canHALConvertRestrictedSecurityTypeFor6GHz( + @NonNull WifiResourceCache resources, @SoftApConfiguration.SecurityType int type) { return type == SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION && resources.getBoolean(R.bool .config_wifiSofapHalMapWpa3TransitionModeToWpa3OnlyIn6GHzBand); @@ -765,7 +822,7 @@ public class ApConfigUtil { * @return the updated SoftApConfiguration. */ public static SoftApConfiguration remove6gBandForUnsupportedSecurity( - @NonNull Resources resources, + @NonNull WifiResourceCache resources, SoftApConfiguration config, boolean isBridgedMode) { SoftApConfiguration.Builder builder = new SoftApConfiguration.Builder(config); @@ -838,13 +895,17 @@ public class ApConfigUtil { * IEEE80211BE & single link MLO in bridged mode from the resource file. * @param config The current {@link SoftApConfiguration}. * @param isBridgedMode true if bridged mode is enabled, false otherwise. + * @param numberOf11beSoftApManager number of existing 11BE SoftApManager. + * @param isChipSupportMultiLinkOnMLD true if the chip reports supports multiple links + * on a single MLD AP. * * @return true if IEEE80211BE is allowed for the given configuration, false otherwise. */ public static boolean is11beAllowedForThisConfiguration(DeviceWiphyCapabilities capabilities, - @NonNull Context context, + @NonNull WifiContext context, SoftApConfiguration config, - boolean isBridgedMode) { + boolean isBridgedMode, int numberOf11beSoftApManager, + boolean isChipSupportMultiLinkOnMLD) { if (!ApConfigUtil.isIeee80211beSupported(context)) { return false; } @@ -852,10 +913,22 @@ public class ApConfigUtil { ScanResult.WIFI_STANDARD_11BE)) { return false; } - if (isBridgedMode - && !context.getResources().getBoolean( - R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) { - return false; + if (Flags.mloSap()) { + int numberOfMLDStillAllowed = + maximumNumberOfMLDForMLOAp(context) - numberOf11beSoftApManager; + if (numberOfMLDStillAllowed < 1) { + return false; + } + if (isBridgedMode && !isChipSupportMultiLinkOnMLD && numberOfMLDStillAllowed < 2) { + // For non multilink MLO bridged mode, it requires two 11be instances. + return false; + } + } else { + if (isBridgedMode + && !context.getResourceCache().getBoolean( + R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) { + return false; + } } if (is11beDisabledForSecurityType(config.getSecurityType())) { return false; @@ -863,6 +936,19 @@ public class ApConfigUtil { return true; } + private static int maximumNumberOfMLDForMLOAp(@NonNull WifiContext context) { + int numberOfMLDSupported = context.getResourceCache() + .getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported); + if (numberOfMLDSupported != 0) { + return numberOfMLDSupported; + } + if (context.getResourceCache().getBoolean( + R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) { + return 2; + } + return 1; + } + /** * Update AP band and channel based on the provided country code and band. * This will also set @@ -876,7 +962,7 @@ public class ApConfigUtil { */ public static @SoftApManager.StartResult int updateApChannelConfig(WifiNative wifiNative, @NonNull CoexManager coexManager, - Resources resources, + WifiResourceCache resources, String countryCode, SoftApConfiguration.Builder configBuilder, SoftApConfiguration config, @@ -988,7 +1074,7 @@ public class ApConfigUtil { * @return SoftApCapability which updated the feature support or not from resource. */ @NonNull - public static SoftApCapability updateCapabilityFromResource(@NonNull Context context) { + public static SoftApCapability updateCapabilityFromResource(@NonNull WifiContext context) { long features = 0; if (isAcsSupported(context)) { Log.d(TAG, "Update Softap capability, add acs feature support"); @@ -1051,7 +1137,7 @@ public class ApConfigUtil { } SoftApCapability capability = new SoftApCapability(features); - int hardwareSupportedMaxClient = context.getResources().getInteger( + int hardwareSupportedMaxClient = context.getResourceCache().getInteger( R.integer.config_wifiHardwareSoftapMaxClientCount); if (hardwareSupportedMaxClient > 0) { Log.d(TAG, "Update Softap capability, max client = " + hardwareSupportedMaxClient); @@ -1088,8 +1174,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isIeee80211axSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isIeee80211axSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftapIeee80211axSupported); } @@ -1099,8 +1185,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isIeee80211beSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isIeee80211beSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftapIeee80211beSupported); } @@ -1122,8 +1208,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isApMacRandomizationSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isApMacRandomizationSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifi_ap_mac_randomization_supported); } @@ -1135,8 +1221,8 @@ public class ApConfigUtil { * @return true if supported, false otherwise. */ public static boolean isBridgedModeSupported( - @NonNull Context context, @NonNull WifiNative wifiNative) { - return SdkLevel.isAtLeastS() && context.getResources().getBoolean( + @NonNull WifiContext context, @NonNull WifiNative wifiNative) { + return SdkLevel.isAtLeastS() && context.getResourceCache().getBoolean( R.bool.config_wifiBridgedSoftApSupported) && wifiNative.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ put(HDM_CREATE_IFACE_AP_BRIDGE, 1); @@ -1150,8 +1236,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isBridgedModeSupportedInConfig(@NonNull Context context) { - return SdkLevel.isAtLeastS() && context.getResources().getBoolean( + public static boolean isBridgedModeSupportedInConfig(@NonNull WifiContext context) { + return SdkLevel.isAtLeastS() && context.getResourceCache().getBoolean( R.bool.config_wifiBridgedSoftApSupported); } @@ -1164,8 +1250,8 @@ public class ApConfigUtil { * @return true if supported, false otherwise. */ public static boolean isStaWithBridgedModeSupported( - @NonNull Context context, @NonNull WifiNative wifiNative) { - return SdkLevel.isAtLeastS() && context.getResources().getBoolean( + @NonNull WifiContext context, @NonNull WifiNative wifiNative) { + return SdkLevel.isAtLeastS() && context.getResourceCache().getBoolean( R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported) && wifiNative.canDeviceSupportCreateTypeCombo(new SparseArray<Integer>() {{ put(HDM_CREATE_IFACE_AP_BRIDGE, 1); @@ -1179,8 +1265,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isClientForceDisconnectSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isClientForceDisconnectSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSofapClientForceDisconnectSupported); } @@ -1190,8 +1276,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isWpa3SaeSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isWpa3SaeSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifi_softap_sae_supported); } @@ -1201,8 +1287,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isAcsSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isAcsSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifi_softap_acs_supported); } @@ -1212,8 +1298,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isMacCustomizationSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isMacCustomizationSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftapMacAddressCustomizationSupported); } @@ -1224,23 +1310,25 @@ public class ApConfigUtil { * @param band the band soft AP to operate on. * @return true if supported, false otherwise. */ - public static boolean isSoftApBandSupported(@NonNull Context context, @BandType int band) { + public static boolean isSoftApBandSupported(@NonNull WifiContext context, + @BandType int band) { + switch (band) { case SoftApConfiguration.BAND_2GHZ: - return context.getResources().getBoolean(R.bool.config_wifi24ghzSupport) - && context.getResources().getBoolean( + return context.getResourceCache().getBoolean(R.bool.config_wifi24ghzSupport) + && context.getResourceCache().getBoolean( R.bool.config_wifiSoftap24ghzSupported); case SoftApConfiguration.BAND_5GHZ: - return context.getResources().getBoolean(R.bool.config_wifi5ghzSupport) - && context.getResources().getBoolean( + return context.getResourceCache().getBoolean(R.bool.config_wifi5ghzSupport) + && context.getResourceCache().getBoolean( R.bool.config_wifiSoftap5ghzSupported); case SoftApConfiguration.BAND_6GHZ: - return context.getResources().getBoolean(R.bool.config_wifi6ghzSupport) - && context.getResources().getBoolean( + return context.getResourceCache().getBoolean(R.bool.config_wifi6ghzSupport) + && context.getResourceCache().getBoolean( R.bool.config_wifiSoftap6ghzSupported); case SoftApConfiguration.BAND_60GHZ: - return context.getResources().getBoolean(R.bool.config_wifi60ghzSupport) - && context.getResources().getBoolean( + return context.getResourceCache().getBoolean(R.bool.config_wifi60ghzSupport) + && context.getResourceCache().getBoolean( R.bool.config_wifiSoftap60ghzSupported); default: return false; @@ -1254,8 +1342,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isSoftApDynamicCountryCodeSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isSoftApDynamicCountryCodeSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported); } @@ -1266,8 +1354,9 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isSoftApRestartRequiredWhenCountryCodeChanged(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isSoftApRestartRequiredWhenCountryCodeChanged( + @NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiForcedSoftApRestartWhenCountryCodeChanged); } @@ -1277,8 +1366,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isOweTransitionSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isOweTransitionSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftapOweTransitionSupported); } @@ -1288,8 +1377,8 @@ public class ApConfigUtil { * @param context the caller context used to get value from resource file. * @return true if supported, false otherwise. */ - public static boolean isOweSupported(@NonNull Context context) { - return context.getResources().getBoolean( + public static boolean isOweSupported(@NonNull WifiContext context) { + return context.getResourceCache().getBoolean( R.bool.config_wifiSoftapOweSupported); } @@ -1420,7 +1509,7 @@ public class ApConfigUtil { * * @return true when freq ranges is needed, otherwise false. */ - public static boolean isSendFreqRangesNeeded(@BandType int band, Context context, + public static boolean isSendFreqRangesNeeded(@BandType int band, WifiContext context, SoftApConfiguration config) { // Fist we check if one of the selected bands has restrictions in the overlay file or in the // provided SoftApConfiguration. @@ -1429,7 +1518,8 @@ public class ApConfigUtil { // - If there is no restrictions on channels, we store the full band for (int b : SoftApConfiguration.BAND_TYPES) { if ((band & b) != 0) { - List<Integer> configuredList = getConfiguredChannelList(context.getResources(), b); + List<Integer> configuredList = getConfiguredChannelList( + context.getResourceCache(), b); if (configuredList != null && !configuredList.isEmpty()) { // If any of the selected band has restriction in the overlay file return true. return true; @@ -1602,7 +1692,7 @@ public class ApConfigUtil { * @return updated soft AP capability */ public static SoftApCapability updateSoftApCapabilityWithAvailableChannelList( - @NonNull SoftApCapability softApCapability, @NonNull Context context, + @NonNull SoftApCapability softApCapability, @NonNull WifiContext context, @NonNull WifiNative wifiNative, @NonNull SparseArray<int[]> channelMap) { SoftApCapability newSoftApCapability = new SoftApCapability(softApCapability); if (channelMap != null) { @@ -1621,7 +1711,7 @@ public class ApConfigUtil { for (int band : SoftApConfiguration.BAND_TYPES) { if (isSoftApBandSupported(context, band)) { supportedChannelList = getAvailableChannelFreqsForBand( - band, wifiNative, context.getResources(), false); + band, wifiNative, context.getResourceCache(), false); if (supportedChannelList != null) { newSoftApCapability.setSupportedChannelList( band, diff --git a/service/java/com/android/server/wifi/util/GeneralUtil.java b/service/java/com/android/server/wifi/util/GeneralUtil.java index 80d745cc93..7040d814e3 100644 --- a/service/java/com/android/server/wifi/util/GeneralUtil.java +++ b/service/java/com/android/server/wifi/util/GeneralUtil.java @@ -16,6 +16,8 @@ package com.android.server.wifi.util; +import java.util.BitSet; + /** * Class for general helper methods and objects for Wifi Framework code. * @hide @@ -40,4 +42,37 @@ public class GeneralUtil { this.value = value; } } + + /** + * Convert a capability bitmask to its index in a BitSet. + * + * TODO: Remove this method once the WifiManager capabilities are + * represented as indexes rather than bitmasks. + */ + public static int getCapabilityIndex(long capability) { + // Index of the first enabled bit is the number of trailing zeroes + // in the binary representation + return Long.numberOfTrailingZeros(capability); + } + + /** + * Convert a long to a BitSet. + * + * See TODO in {@link #getCapabilityIndex(long)}. + */ + public static BitSet longToBitset(long longValue) { + return BitSet.valueOf(new long[]{longValue}); + } + + /** + * Convert a BitSet to a long. + * + * See TODO in {@link #getCapabilityIndex(long)}. + */ + public static long bitsetToLong(BitSet bitset) { + if (bitset == null || bitset.cardinality() == 0) { + return 0L; + } + return bitset.toLongArray()[0]; + } } diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java index 57643b9c01..ea499578df 100644 --- a/service/java/com/android/server/wifi/util/InformationElementUtil.java +++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java @@ -1859,6 +1859,8 @@ public class InformationElementUtil { private static final int WPS_VENDOR_OUI_TYPE = 0x04f25000; private static final short WPA_VENDOR_OUI_VERSION = 0x0001; private static final int OWE_VENDOR_OUI_TYPE = 0x1c9a6f50; + private static final int RSNE_OVERRIDE_VENDOR_OUI_TYPE = 0x299a6f50; + private static final int RSNE_OVERRIDE2_VENDOR_OUI_TYPE = 0x2A9a6f50; private static final short RSNE_VERSION = 0x0001; private static final int WPA_AKM_EAP = 0x01f25000; @@ -1910,10 +1912,25 @@ public class InformationElementUtil { public boolean isWPS; public boolean isManagementFrameProtectionRequired; public boolean isManagementFrameProtectionCapable; + private boolean mHasPmfRequiredBitSetToFalseOccurred; + public boolean isRSNEOverrideElementPresent; public Capabilities() { } + private static boolean isRsneOverrideElement(InformationElement ie) { + ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); + try { + int vendorOuiType = buf.getInt(); + // Wi-Fi Alliance specific OUI and OUI type identifying RSNE Override element. + return (vendorOuiType == RSNE_OVERRIDE_VENDOR_OUI_TYPE + || vendorOuiType == RSNE_OVERRIDE2_VENDOR_OUI_TYPE); + } catch (BufferUnderflowException e) { + Log.e("IE_Capabilities", "Couldn't parse VSA IE, buffer underflow"); + return false; + } + } + // RSNE format (size unit: byte) // // | Element ID | Length | Version | Group Data Cipher Suite | @@ -1927,8 +1944,7 @@ public class InformationElementUtil { // // Note: InformationElement.bytes has 'Element ID' and 'Length' // stripped off already - private void parseRsnElement(InformationElement ie, SparseIntArray unknownAkmMap) { - ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); + private void parseRsnElement(ByteBuffer buf, SparseIntArray unknownAkmMap) { try { // version @@ -2027,9 +2043,17 @@ public class InformationElementUtil { // see section 9.4.2.25 - RSNE - In IEEE Std 802.11-2016 if (buf.remaining() < 2) return; int rsnCaps = buf.getShort(); - isManagementFrameProtectionRequired = - 0 != (RSN_CAP_MANAGEMENT_FRAME_PROTECTION_REQUIRED & rsnCaps); - isManagementFrameProtectionCapable = + // This method gets called multiple times if the AP and STA supports RSN overriding. + // The PMF required bit should be set to false if one of the RSN fields PMF + // required bit is ever false. The PMF capable bit should be set to true if one of + // the RSN fields PMF capable bit is ever true. + if ((RSN_CAP_MANAGEMENT_FRAME_PROTECTION_REQUIRED & rsnCaps) == 0) { + mHasPmfRequiredBitSetToFalseOccurred = true; + isManagementFrameProtectionRequired = false; + } else if (!mHasPmfRequiredBitSetToFalseOccurred) { + isManagementFrameProtectionRequired = true; + } + isManagementFrameProtectionCapable |= 0 != (RSN_CAP_MANAGEMENT_FRAME_PROTECTION_CAPABLE & rsnCaps); if (buf.remaining() < 2) return; @@ -2218,6 +2242,8 @@ public class InformationElementUtil { * @param ies -- Information Element array * @param beaconCap -- 16-bit Beacon Capability Information field * @param isOweSupported -- Boolean flag to indicate if OWE is supported by the device + * @param isRsnOverridingSupported -- Boolean flag to indicate if RSN Overriding is + * supported by the device * @param freq -- Frequency on which frame/beacon was transmitted. Some parsing may be * affected such as DMG parameters in DMG (60GHz) beacon. * @param unknownAkmMap -- unknown AKM to known AKM mapping (Internally converted to @@ -2228,6 +2254,7 @@ public class InformationElementUtil { InformationElement[] ies, int beaconCap, boolean isOweSupported, + boolean isRsnOverridingSupported, int freq, SparseIntArray unknownAkmMap) { protocol = new ArrayList<>(); @@ -2265,10 +2292,22 @@ public class InformationElementUtil { } if (ie.id == InformationElement.EID_RSN) { - parseRsnElement(ie, unknownAkmMap); + parseRsnElement(ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN), + unknownAkmMap); } if (ie.id == InformationElement.EID_VSA) { + if (isRsnOverridingSupported && isRsneOverrideElement(ie)) { + ByteBuffer buf = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN); + // RSN Override and RSN Override 2 vendor specific element begins + // with 3 bytes of Wi-Fi Alliance specific OUI and 1 byte of OUI type. + // The Payload field of the RSNE Override element and the RSNE Override 2 + // element uses the same format as the Information field of the RSNE. + // So skip the 4 byte OUI field and proceed to parse the RSN element. + buf.getInt(); + parseRsnElement(buf, unknownAkmMap); + isRSNEOverrideElementPresent = true; + } if (isWpaOneElement(ie)) { parseWpaOneElement(ie, unknownAkmMap); } @@ -2474,6 +2513,9 @@ public class InformationElementUtil { if (isManagementFrameProtectionCapable) { capabilities.append("[MFPC]"); } + if (isRSNEOverrideElementPresent) { + capabilities.append("[RSNO]"); + } return capabilities.toString(); } diff --git a/service/java/com/android/server/wifi/util/NativeUtil.java b/service/java/com/android/server/wifi/util/NativeUtil.java index 0d422d0b9a..f98a2c17c7 100644 --- a/service/java/com/android/server/wifi/util/NativeUtil.java +++ b/service/java/com/android/server/wifi/util/NativeUtil.java @@ -23,6 +23,8 @@ import android.net.wifi.util.HexEncoding; import android.text.TextUtils; import com.android.server.wifi.ByteBufferReader; +import com.android.server.wifi.SupplicantStaIfaceHal.StaIfaceReasonCode; +import com.android.server.wifi.WifiConfigurationUtil; import com.android.server.wifi.WifiGlobals; import java.nio.BufferUnderflowException; @@ -433,6 +435,31 @@ public class NativeUtil { return ciphers; } + /** + * Check if the EAPOL 4-WAY H/S failure is due to wrong password + * + */ + public static boolean isEapol4WayHandshakeFailureDueToWrongPassword(WifiConfiguration config, + boolean locallyGenerated, int reasonCode) { + if (!(WifiConfigurationUtil.isConfigForPskNetwork(config) + || WifiConfigurationUtil.isConfigForWapiPskNetwork( + config))) { + return false; + } + // Filter out the disconnect triggered by the supplicant due to WPA/RSN IE mismatch in the + // received EAPOL message 3/4 with the Beacon/ProbeResp WPA/RSN IE. + if (locallyGenerated && reasonCode == StaIfaceReasonCode.IE_IN_4WAY_DIFFERS) { + return false; + } + // Some APs send de-authentication/disassociation with reason code 5 + // (NO_MORE_STAS - Disassociated because AP is unable to handle all currently associated + // STAs) in the middle of EAPOL H/S. Filter out this reason code. + if (!locallyGenerated && reasonCode == StaIfaceReasonCode.DISASSOC_AP_BUSY) { + return false; + } + return true; + } + private static boolean isPskSaeParamsMergeable( WifiConfiguration config, WifiGlobals wifiGlobals) { if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK) diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java index e0bb9e5f28..0f70340d84 100644 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ b/service/java/com/android/server/wifi/util/XmlUtil.java @@ -16,6 +16,8 @@ package com.android.server.wifi.util; +import static com.android.wifi.flags.Flags.softapConfigStoreMaxChannelWidth; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.compat.CompatChanges; @@ -1972,6 +1974,7 @@ public class XmlUtil { public static final String XML_TAG_VENDOR_ELEMENTS = "VendorElements"; public static final String XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS = "PersistentRandomizedMacAddress"; + public static final String XML_TAG_MAX_CHANNEL_WIDTH = "MaxChannelWidth"; /** @@ -2195,6 +2198,10 @@ public class XmlUtil { XmlUtil.writeNextValue(out, XML_TAG_PERSISTENT_RANDOMIZED_MAC_ADDRESS, softApConfig.getPersistentRandomizedMacAddress().toString()); } + if (softapConfigStoreMaxChannelWidth()) { + XmlUtil.writeNextValue(out, XML_TAG_MAX_CHANNEL_WIDTH, + softApConfig.getMaxChannelBandwidth()); + } } if (SdkLevel.isAtLeastV()) { writeVendorDataListToXml(out, softApConfig.getVendorData()); @@ -2348,6 +2355,12 @@ public class XmlUtil { MacAddress.fromString((String) value)); } break; + case XML_TAG_MAX_CHANNEL_WIDTH: + if (SdkLevel.isAtLeastT() + && softapConfigStoreMaxChannelWidth()) { + softApConfigBuilder.setMaxChannelBandwidth((int) value); + } + break; default: Log.w(TAG, "Ignoring unknown value name " + valueName[0]); break; diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto index a27864fb87..1637fb7d5c 100644 --- a/service/proto/src/metrics.proto +++ b/service/proto/src/metrics.proto @@ -1466,6 +1466,15 @@ message StaEvent { // Wi-Fi 7 support for this network has been enabled or disabled. DISCONNECT_NETWORK_WIFI7_TOGGLED = 17; + + // IP configuration is lost. Triggered by connectivity + DISCONNECT_IP_CONFIGURATION_LOST = 18; + + // IP reachability is lost. Triggered by connectivity + DISCONNECT_IP_REACHABILITY_LOST = 19; + + // No credentials + DISCONNECT_NO_CREDENTIALS = 20; } // Authentication Failure reasons as reported through the API. @@ -2709,6 +2718,59 @@ message WifiUsabilityStatsEntry { // Link layer radio stats for all the radios repeated RadioStats radio_stats = 44; + + // Number of WiFi links. + optional int32 wifi_link_count = 45; + + // Link layer radio stats for all WiFi links + repeated LinkStats link_stats = 46; + + // The MLO mode + // See details in @WifiManager.MloMode + optional int32 mlo_mode = 47; + + // The number of tx bytes transmitted on current interface + optional int64 tx_transmitted_bytes = 48; + + // The number of rx bytes transmitted on current interface + optional int64 rx_transmitted_bytes = 49; + + // The total number of LABEL_BAD event happens + optional int32 label_bad_event_count = 50; + + // Current WiFi state in framework + optional int32 wifi_framework_state = 51; + + // Downstream throughput estimation provided by Network Capabilities + optional int32 is_network_capabilities_downstream_sufficient = 52; + + // Upstream throughput estimation provided by Network Capabilities + optional int32 is_network_capabilities_upstream_sufficient = 53; + + // Downstream throughput estimation used in Network Selection + optional int32 is_throughput_predictor_downstream_sufficient = 54; + + // Upstream throughput estimation provided by Network Capabilities + optional int32 is_throughput_predictor_upstream_sufficient = 55; + + // If bluetooth is connected + optional bool is_bluetooth_connected = 56; + + // State of UWB adapter. Refers to + // UwbManager#registerAdapterStateCallback(Executor, AdapterStateCallback) + optional int32 uwb_adapter_state = 57; + + // Wifi Low Latency mode state + optional bool is_low_latency_activated = 58; + + // Maximum supported tx link speed in Mbps + optional int32 max_supported_tx_linkspeed = 59; + + // Maximum supported rx link speed in Mbps + optional int32 max_supported_rx_linkspeed = 60; + + // Wifi Voip mode state + optional int32 voip_mode = 61; } message ContentionTimeStats { @@ -2742,6 +2804,37 @@ message ContentionTimeStats { optional int64 contention_num_samples = 5; } +message PacketStats { + enum AccessCategory { + // WME Best Effort Access Category + WME_ACCESS_CATEGORY_BE = 0; + + // WME Background Access Category + WME_ACCESS_CATEGORY_BK = 1; + + // WME Video Access Category + WME_ACCESS_CATEGORY_VI = 2; + + // WME Voice Access Category + WME_ACCESS_CATEGORY_VO = 3; + } + + // WME access category + optional AccessCategory access_category = 1; + + // The number of tx success counted from the last radio chip reset + optional int64 tx_success = 2; + + // The number of MPDU data packet retries counted from the last radio chip reset + optional int64 tx_retries = 3; + + // The number of tx bad counted from the last radio chip reset + optional int64 tx_bad = 4; + + // The number of rx success counted from the last radio chip reset + optional int64 rx_success = 5; +} + message RateStats { enum WifiPreambleType { // Preamble type for IEEE 802.11a/g, IEEE Std 802.11-2020, Section 17 @@ -2786,6 +2879,8 @@ message RateStats { WIFI_BANDWIDTH_5_MHZ = 5; // Channel bandwidth: 10MHz WIFI_BANDWIDTH_10_MHZ = 6; + // Channel bandwidth: 320MHz + WIFI_BANDWIDTH_320_MHZ = 7; // Invalid channel bandwidth WIFI_BANDWIDTH_INVALID = -1; } @@ -2849,6 +2944,123 @@ message RadioStats { // The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio // chip reset optional int64 total_hotspot_2_scan_time_ms = 10; + + // Time for which the radio is in active tranmission per tx level + repeated int32 tx_time_ms_per_level = 11; +} + +message LinkStats { + enum LinkState { + // Chip does not support reporting the state of the link + LINK_STATE_UNKNOWN = 0; + + // Link has not been in use since last report. It is placed in power save + LINK_STATE_NOT_IN_USE = 1; + + // Link is in use. In presence of traffic, it is set to be power active. + LINK_STATE_IN_USE = 2; + } + + enum WifiChannelBandwidth { + // Channel bandwidth: 20MHz + WIFI_BANDWIDTH_20_MHZ = 0; + // Channel bandwidth: 40MHz + WIFI_BANDWIDTH_40_MHZ = 1; + // Channel bandwidth: 80MHz + WIFI_BANDWIDTH_80_MHZ = 2; + // Channel bandwidth: 160MHz + WIFI_BANDWIDTH_160_MHZ = 3; + // Channel bandwidth: 80MHz + 80MHz + WIFI_BANDWIDTH_80P80_MHZ = 4; + // Channel bandwidth: 5MHz + WIFI_BANDWIDTH_5_MHZ = 5; + // Channel bandwidth: 10MHz + WIFI_BANDWIDTH_10_MHZ = 6; + // Channel bandwidth: 320MHz + WIFI_BANDWIDTH_320_MHZ = 7; + // Invalid channel bandwidth + WIFI_BANDWIDTH_INVALID = -1; + } + + // The Link ID + optional int32 link_id = 1; + + // Link state + optional LinkState state = 2; + + // Identifier of the radio on which link is currently operating + optional int32 radio_id = 3; + + // Frequency of the link in MHz + optional int32 frequency_mhz = 4; + + // Number of beacons received from our own AP + optional int32 beacon_rx = 5; + + // RSSI of management frames + optional int32 rssi_mgmt = 6; + + // Duty cycle of the link. + optional int32 time_slice_duty_cycle_in_percent = 7; + + // Overall RSSI from wpa_supplicant signal_poll + optional int32 rssi = 8; + + // channel width of WiFi link. + optional WifiChannelBandwidth channel_width = 9; + + // Center frequency (MHz) of first segment. + optional int32 center_freq_first_seg = 10; + + // Center frequency (MHz) of second segment. + optional int32 center_freq_second_seg = 11; + + // Total time for which the radio is awake on this channel. + optional int64 on_time_in_ms = 12; + + // Total time for which CCA is held busy on this channel. + optional int64 cca_busy_time_in_ms = 13; + + // WME data packet contention time statistics for all four categories: BE, BK, VI, VO + repeated ContentionTimeStats contention_time_stats = 14; + + // Packet statistics for all four categories: BE, BK, VI, VO + repeated PacketStats packet_stats = 15; + + // Peer statistics on this WiFi link + repeated PeerInfo peer_info = 16; + + // List of scan results who have the same freq with current WiFi link + repeated ScanResultWithSameFreq scan_result_with_same_freq = 17; + + // TX linkspeed in this WiFi link + optional int32 tx_linkspeed = 18; + + // RX linkspeed in this WiFi link + optional int32 rx_linkspeed = 19; +} + +message PeerInfo { + // Station count. + optional int32 sta_count = 1; + + // Channel utilization. + optional int32 chan_util = 2; + + // Rate statistics, including number of successful packets, retries, etc., + // indexed by preamble, bandwidth, number of spatial streams, MCS. + repeated RateStats rate_stats = 3; +} + +message ScanResultWithSameFreq { + // timestamp in microseconds (since boot) when this result was last seen. + optional int64 scan_result_timestamp_micros = 1; + + // The detected signal level in dBm + optional int32 rssi = 2; + + // The center frequency of the primary 20 MHz frequency (in MHz) of the channel + optional int32 frequencyMhz = 3; } message WifiUsabilityStats { diff --git a/service/tests/wifitests/Android.bp b/service/tests/wifitests/Android.bp index 7349dcbdb0..98974c26c7 100644 --- a/service/tests/wifitests/Android.bp +++ b/service/tests/wifitests/Android.bp @@ -674,6 +674,9 @@ android_test { "com.android.server.wifi.WifiVendorHal", "com.android.server.wifi.WifiVendorHal$*", "com.android.server.wifi.WifiVendorHal.**", + "com.android.server.wifi.WifiVoipDetector", + "com.android.server.wifi.WifiVoipDetector$*", + "com.android.server.wifi.WifiVoipDetector.**", "com.android.server.wifi.WifiWakeMetrics", "com.android.server.wifi.WifiWakeMetrics$*", "com.android.server.wifi.WifiWakeMetrics.**", diff --git a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java index 78f28fb507..100e3849d1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java @@ -21,6 +21,7 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; @@ -30,6 +31,9 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; import static com.android.server.wifi.ActiveModeWarden.INTERNAL_REQUESTOR_WS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS; +import static com.android.server.wifi.TestUtil.addCapabilitiesToBitset; +import static com.android.server.wifi.TestUtil.combineBitsets; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -51,6 +55,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockingDetails; import static org.mockito.Mockito.never; @@ -63,10 +68,8 @@ import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.BroadcastReceiver; -import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.location.LocationManager; import android.net.MacAddress; import android.net.Network; @@ -80,10 +83,13 @@ import android.net.wifi.SoftApInfo; import android.net.wifi.SoftApState; import android.net.wifi.WifiClient; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; +import android.net.wifi.util.WifiResourceCache; import android.os.BatteryStatsManager; import android.os.Build; +import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -96,6 +102,7 @@ import android.util.Log; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ActiveModeManager.ClientConnectivityRole; import com.android.server.wifi.ActiveModeManager.Listener; @@ -119,6 +126,7 @@ import org.mockito.stubbing.Answer; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; +import java.util.BitSet; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -148,7 +156,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { private static final int TEST_AP_FREQUENCY = 2412; private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; private static final int TEST_UID = 435546654; - private static final long TEST_FEATURE_SET = 0xAB3DEF; + private static final BitSet TEST_FEATURE_SET = createCapabilityBitset( + WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_PNO, + WifiManager.WIFI_FEATURE_OWE, WifiManager.WIFI_FEATURE_DPP); private static final String TEST_PACKAGE = "com.test"; private static final String TEST_COUNTRYCODE = "US"; private static final WorkSource TEST_WORKSOURCE = new WorkSource(TEST_UID, TEST_PACKAGE); @@ -158,8 +168,8 @@ public class ActiveModeWardenTest extends WifiBaseTest { TestLooper mLooper; @Mock WifiInjector mWifiInjector; - @Mock Context mContext; - @Mock Resources mResources; + @Mock WifiContext mContext; + @Mock WifiResourceCache mWifiResourceCache; @Mock WifiNative mWifiNative; @Mock WifiApConfigStore mWifiApConfigStore; @Mock ConcreteClientModeManager mClientModeManager; @@ -206,6 +216,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { private BroadcastReceiver mEmergencyCallbackModeChangedBr; private BroadcastReceiver mEmergencyCallStateChangedBr; + private StaticMockitoSession mStaticMockSession; /** * Set up the test environment. @@ -215,8 +226,12 @@ public class ActiveModeWardenTest extends WifiBaseTest { Log.d(TAG, "Setting up ..."); MockitoAnnotations.initMocks(this); + mStaticMockSession = mockitoSession() + .mockStatic(WifiInjector.class) + .startMocking(); mLooper = new TestLooper(); + when(WifiInjector.getInstance()).thenReturn(mWifiInjector); when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); when(mWifiInjector.getSarManager()).thenReturn(mSarManager); when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager); @@ -226,16 +241,16 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); - when(mResources.getString(R.string.wifi_localhotspot_configure_ssid_default)) + when(mWifiResourceCache.getString(R.string.wifi_localhotspot_configure_ssid_default)) .thenReturn("AndroidShare"); - when(mResources.getInteger(R.integer.config_wifi_framework_recovery_timeout_delay)) + when(mWifiResourceCache.getInteger(R.integer.config_wifi_framework_recovery_timeout_delay)) .thenReturn(TEST_WIFI_RECOVERY_DELAY_MS); - when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) .thenReturn(false); - when(mResources.getBoolean(R.bool.config_wifi_turn_off_during_emergency_call)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifi_turn_off_during_emergency_call)) .thenReturn(true); when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); @@ -273,6 +288,8 @@ public class ActiveModeWardenTest extends WifiBaseTest { any(WifiServiceImpl.SoftApCallbackInternal.class), any(), any(), any(), anyBoolean()); when(mWifiNative.initialize()).thenReturn(true); + when(mWifiNative.getSupportedFeatureSet(isNull())).thenReturn(new BitSet()); + when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn(new BitSet()); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(true); mActiveModeWarden = createActiveModeWarden(); @@ -341,6 +358,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { @After public void cleanUp() throws Exception { mActiveModeWarden = null; + mStaticMockSession.finishMocking(); mLooper.dispatchAll(); } @@ -375,7 +393,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { * @param isClientModeSwitch true if switching from another mode, false if creating a new one * @param testFeatureSet a customized feature set to test */ - private void enterClientModeActiveState(boolean isClientModeSwitch, long testFeatureSet) + private void enterClientModeActiveState(boolean isClientModeSwitch, BitSet testFeatureSet) throws Exception { String fromState = mActiveModeWarden.getCurrentMode(); when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); @@ -385,7 +403,8 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); when(mClientModeManager.getCurrentNetwork()).thenReturn(mNetwork); - when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(testFeatureSet); + when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)) + .thenReturn(testFeatureSet); // ClientModeManager starts in SCAN_ONLY role. mClientListener.onRoleChanged(mClientModeManager); mLooper.dispatchAll(); @@ -406,7 +425,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { } verify(mClientModeManager, atLeastOnce()).getInterfaceName(); verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(WIFI_IFACE_NAME); - assertEquals(testFeatureSet, mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(testFeatureSet.equals(mActiveModeWarden.getSupportedFeatureSet())); verify(mScanRequestProxy, times(4)).enableScanning(true, true); assertEquals(mClientModeManager, mActiveModeWarden.getPrimaryClientModeManager()); verify(mModeChangeCallback).onActiveModeManagerRoleChanged(mClientModeManager); @@ -448,7 +467,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { verify(mModeChangeCallback, times(2)) .onActiveModeManagerRoleChanged(mClientModeManager); verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(null); - assertEquals(TEST_FEATURE_SET, mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(TEST_FEATURE_SET.equals(mActiveModeWarden.getSupportedFeatureSet())); } assertInEnabledState(); verify(mScanRequestProxy).enableScanning(true, false); @@ -489,7 +508,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { any(), any(), any(), eq(TEST_WORKSOURCE), eq(softApRole), anyBoolean()); mTimesCreatedSoftApManager++; if (fromState.equals(DISABLED_STATE_STRING)) { - verify(mBatteryStats).reportWifiOn(); + verify(mBatteryStats, atLeastOnce()).reportWifiOn(); } if (softApRole == ROLE_SOFTAP_TETHERED) { assertEquals(mSoftApManager, mActiveModeWarden.getTetheredSoftApManager()); @@ -678,7 +697,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { */ @Test public void testScanOnlyModeScanHiddenNetworks() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) .thenReturn(true); mActiveModeWarden = createActiveModeWarden(); @@ -787,7 +806,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testSwitchFromConnectModeToScanOnlyModeRemovesAdditionalCMMs() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -1498,16 +1517,20 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); reset(mContext); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); mActiveModeWarden = createActiveModeWarden(); mActiveModeWarden.start(); mLooper.dispatchAll(); ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver( + // Note: Ignore lint warning UnspecifiedRegisterReceiverFlag since here is using + // to test receiving for system broadcasts. The lint warning is a false alarm since + // here is using argThat and hasAction. + verify(mContext).registerReceiverForAllUsers( bcastRxCaptor.capture(), - argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + eq(null), any(Handler.class)); BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); assertInDisabledState(); @@ -1532,7 +1555,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mSettingsStore.updateAirplaneModeTracker()).thenReturn(true); reset(mContext); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); mActiveModeWarden = createActiveModeWarden(); mActiveModeWarden.start(); mLooper.dispatchAll(); @@ -1647,7 +1670,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); reset(mContext); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); mActiveModeWarden = createActiveModeWarden(); mActiveModeWarden.start(); mLooper.dispatchAll(); @@ -1656,9 +1679,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver( + verify(mContext).registerReceiverForAllUsers( bcastRxCaptor.capture(), - argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + eq(null), any(Handler.class)); BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); assertInEnabledState(); @@ -2661,6 +2685,52 @@ public class ActiveModeWardenTest extends WifiBaseTest { } /** + * The command to trigger WiFi restart on Bootup. + * WiFi is in connect mode, calls to reset the wifi stack due to connection failures + * should trigger a supplicant stop, and subsequently, a driver reload. (Reboot) + * Create and start WifiController in EnabledState, start softAP and then + * send command to restart WiFi + * <p> + * Expected: Wi-Fi should be restarted successfully on bootup. + */ + @Test + public void testRestartWifiStackInStaConnectEnabledStatewithSap() throws Exception { + enableWifi(); + assertInEnabledState(); + verify(mWifiInjector).makeClientModeManager( + any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); + + assertWifiShutDown(() -> { + mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, + true); + mLooper.dispatchAll(); + // Complete the stop + mClientListener.onStopped(mClientModeManager); + mLooper.dispatchAll(); + }); + + verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); + + // still only started once + verify(mWifiInjector).makeClientModeManager( + any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); + + // start softAp + enterSoftApActiveMode(); + assertInEnabledState(); + + mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); + mLooper.dispatchAll(); + + // started again + verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); + assertInEnabledState(); + + verify(mSubsystemRestartCallback).onSubsystemRestarting(); + verify(mSubsystemRestartCallback).onSubsystemRestarted(); + } + + /** * The command to trigger a WiFi reset should not trigger a reset when in ECM mode. * Enable wifi and enter ECM state, send command to restart wifi. * <p> @@ -3004,13 +3074,13 @@ public class ActiveModeWardenTest extends WifiBaseTest { enterClientModeActiveState(); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); mClientListener.onStarted(mClientModeManager); - assertEquals(0L, - mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA); + assertFalse(mActiveModeWarden.getSupportedFeatureSet() + .get(WifiManager.WIFI_FEATURE_AP_STA)); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); mClientListener.onStarted(mClientModeManager); - assertEquals(WifiManager.WIFI_FEATURE_AP_STA, - mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA); + assertTrue(mActiveModeWarden.getSupportedFeatureSet() + .get(WifiManager.WIFI_FEATURE_AP_STA)); } @Test @@ -3027,16 +3097,16 @@ public class ActiveModeWardenTest extends WifiBaseTest { assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); } @@ -3121,7 +3191,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testRemoveDefaultClientModeManager() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3159,7 +3229,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { private void requestRemoveAdditionalClientModeManagerWhenNotAllowed( ClientConnectivityRole role, boolean clientIsExpected, - long featureSet) throws Exception { + BitSet featureSet) throws Exception { enterClientModeActiveState(false, featureSet); // Connected to ssid1/bssid1 @@ -3361,7 +3431,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestRemoveLocalOnlyClientModeManager() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3383,7 +3453,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestRemoveLocalOnlyClientModeManagerWhenFeatureDisabled() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(false); assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3396,7 +3466,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3426,7 +3496,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestLocalOnlyClientModeManagerWhenAlreadyPresent() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3438,7 +3508,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestLocalOnlyClientModeManagerWhenAlreadyPresentSameBssid() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3450,7 +3520,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestLocalOnlyClientModeManagerWhenConnectingToPrimaryBssid() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -3463,7 +3533,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); @@ -3488,7 +3558,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); when(mWifiPermissionsUtil.isTargetSdkLessThan( @@ -3506,7 +3576,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { // should be able to do for <S apps) when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); when(mWifiPermissionsUtil.isTargetSdkLessThan( @@ -3514,14 +3584,16 @@ public class ActiveModeWardenTest extends WifiBaseTest { .thenReturn(true); assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); + BitSet expectedFeatureSet = addCapabilitiesToBitset( + TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, - true, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); + true, expectedFeatureSet); } private void testLoFallbackAboveAndroidS(boolean isStaStaSupported) throws Exception { when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(isStaStaSupported); when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); when(mWifiPermissionsUtil.isTargetSdkLessThan( @@ -3529,9 +3601,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { .thenReturn(false); assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); - long expectedFeatureSet = TEST_FEATURE_SET; + BitSet expectedFeatureSet = (BitSet) TEST_FEATURE_SET.clone(); if (isStaStaSupported) { - expectedFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY; + expectedFeatureSet.set(WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); } requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, @@ -3559,7 +3631,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestRemoveSecondaryLongLivedClientModeManager() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3583,7 +3655,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(false); assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3595,7 +3667,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestSecondaryLongLivedClientModeManagerWhenWifiIsOff() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3607,7 +3679,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestSecondaryLongLivedClientModeManagerWhenAlreadyPresent() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3620,7 +3692,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3634,7 +3706,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); @@ -3647,7 +3719,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestRemoveSecondaryTransientClientModeManager() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3672,7 +3744,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(false); assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3685,7 +3757,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestSecondaryTransientClientModeManagerWhenWifiIsOff() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3698,7 +3770,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void requestSecondaryTransientClientModeManagerWhenAlreadyPresent() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3712,7 +3784,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3727,7 +3799,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3742,10 +3814,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3827,10 +3899,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3908,7 +3980,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -3972,9 +4044,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiPermissionsUtil.checkEnterCarModePrioritized(anyInt())).thenReturn(true); // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -4032,9 +4104,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mWifiPermissionsUtil.checkEnterCarModePrioritized(anyInt())).thenReturn(true); // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); @@ -4080,7 +4152,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -4357,7 +4429,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testSwitchPrimaryClientModeManager() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( @@ -4435,7 +4507,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); ConcreteClientModeManager additionalClientModeManager = @@ -4739,9 +4811,9 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testRequestForSecondaryLocalOnlyForPreSAppWithUserConnect() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); when(mWifiPermissionsUtil.isTargetSdkLessThan( @@ -4804,7 +4876,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testRequestForSecondaryLocalOnlyForAppWithUserConnect() throws Exception { // Ensure that we can create more client ifaces. when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); when(mWifiPermissionsUtil.isTargetSdkLessThan( @@ -4864,20 +4936,21 @@ public class ActiveModeWardenTest extends WifiBaseTest { @Test public void testGetSupportedFeaturesForStaApConcurrency() throws Exception { enterScanOnlyModeActiveState(); - long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; - when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( - supportedFeaturesFromWifiNative); + BitSet supportedFeaturesFromWifiNative = + createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE); + when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(supportedFeaturesFromWifiNative); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative, - mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(supportedFeaturesFromWifiNative + .equals(mActiveModeWarden.getSupportedFeatureSet())); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative | WifiManager.WIFI_FEATURE_AP_STA, - mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(addCapabilitiesToBitset( + supportedFeaturesFromWifiNative, WifiManager.WIFI_FEATURE_AP_STA) + .equals(mActiveModeWarden.getSupportedFeatureSet())); } /** @@ -4888,53 +4961,55 @@ public class ActiveModeWardenTest extends WifiBaseTest { public void testGetSupportedFeaturesForStaStaConcurrency() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); enterScanOnlyModeActiveState(); - long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; + BitSet supportedFeaturesFromWifiNative = + createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE); when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( supportedFeaturesFromWifiNative); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative, mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(supportedFeaturesFromWifiNative + .equals(mActiveModeWarden.getSupportedFeatureSet())); when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) .thenReturn(true); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY, - mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY) + .equals(mActiveModeWarden.getSupportedFeatureSet())); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB, - mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB) + .equals(mActiveModeWarden.getSupportedFeatureSet())); - when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) - .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)) + when(mWifiResourceCache.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) .thenReturn(true); + when(mWifiResourceCache.getBoolean( + R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)).thenReturn(true); mClientListener.onStarted(mClientModeManager); - assertEquals(supportedFeaturesFromWifiNative - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED - | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET, - mActiveModeWarden.getSupportedFeatureSet()); + assertTrue(addCapabilitiesToBitset(supportedFeaturesFromWifiNative, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED, + WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET) + .equals(mActiveModeWarden.getSupportedFeatureSet())); } - private long testGetSupportedFeaturesCaseForMacRandomization( - long supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled, + private BitSet testGetSupportedFeaturesCaseForMacRandomization( + BitSet supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled, boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled) { - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifi_connected_mac_randomization_supported)) .thenReturn(staConnectedMacRandomizationEnabled); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifi_ap_mac_randomization_supported)) .thenReturn(apMacRandomizationEnabled); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifi_p2p_mac_randomization_supported)) .thenReturn(p2pMacRandomizationEnabled); when(mWifiNative.getSupportedFeatureSet(anyString())) @@ -4947,28 +5022,29 @@ public class ActiveModeWardenTest extends WifiBaseTest { /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ @Test public void syncGetSupportedFeaturesForMacRandomization() throws Exception { - final long featureStaConnectedMacRandomization = - WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; - final long featureApMacRandomization = - WifiManager.WIFI_FEATURE_AP_RAND_MAC; - final long featureP2pMacRandomization = - WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; + final BitSet featureStaConnectedMacRandomization = + createCapabilityBitset(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC); + final BitSet featureApMacRandomization = + createCapabilityBitset(WifiManager.WIFI_FEATURE_AP_RAND_MAC); + final BitSet featureP2pMacRandomization = + createCapabilityBitset(WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC); enterClientModeActiveState(); - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization - | featureP2pMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization( - featureP2pMacRandomization, true, true, true)); + assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization, + featureP2pMacRandomization) + .equals(testGetSupportedFeaturesCaseForMacRandomization( + featureP2pMacRandomization, true, true, true))); // p2p supported by HAL, but disabled by overlay. - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization( - featureP2pMacRandomization, true, true, false)); - assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, - testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false)); + assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization) + .equals(testGetSupportedFeaturesCaseForMacRandomization( + featureP2pMacRandomization, true, true, false))); + assertTrue(combineBitsets(featureStaConnectedMacRandomization, featureApMacRandomization) + .equals(testGetSupportedFeaturesCaseForMacRandomization( + new BitSet(), true, true, false))); } - private long testGetSupportedFeaturesCaseForRtt( - long supportedFeaturesFromWifiNative, boolean rttDisabled) { + private BitSet testGetSupportedFeaturesCaseForRtt( + BitSet supportedFeaturesFromWifiNative, boolean rttDisabled) { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( !rttDisabled); when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn( @@ -4981,39 +5057,41 @@ public class ActiveModeWardenTest extends WifiBaseTest { /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ @Test public void syncGetSupportedFeaturesForRtt() throws Exception { - final long featureAware = WifiManager.WIFI_FEATURE_AWARE; - final long featureInfra = WifiManager.WIFI_FEATURE_INFRA; - final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; - final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; - final long featureLongBits = 0x1000000000L; + final BitSet featureAware = createCapabilityBitset(WifiManager.WIFI_FEATURE_AWARE); + final BitSet featureInfra = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA); + final BitSet featureD2dRtt = createCapabilityBitset(WifiManager.WIFI_FEATURE_D2D_RTT); + final BitSet featureD2apRtt = createCapabilityBitset(WifiManager.WIFI_FEATURE_D2AP_RTT); + enterClientModeActiveState(); - assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, false)); - assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, true)); - assertEquals(featureAware | featureInfra, - testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, false)); - assertEquals(featureAware | featureInfra, - testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, true)); - assertEquals(featureInfra | featureD2dRtt, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, true)); - assertEquals(featureInfra | featureD2apRtt, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, true)); - assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, - testGetSupportedFeaturesCaseForRtt( - featureInfra | featureD2dRtt | featureD2apRtt, false)); - assertEquals(featureInfra, - testGetSupportedFeaturesCaseForRtt( - featureInfra | featureD2dRtt | featureD2apRtt, true)); - assertEquals(featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, + assertTrue(testGetSupportedFeaturesCaseForRtt(new BitSet(), false).equals(new BitSet())); + assertTrue(testGetSupportedFeaturesCaseForRtt(new BitSet(), true).equals(new BitSet())); + assertTrue(combineBitsets(featureAware, featureInfra).equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureAware, featureInfra), + false))); + assertTrue(combineBitsets(featureAware, featureInfra).equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureAware, featureInfra), + true))); + assertTrue(combineBitsets(featureInfra, featureD2dRtt).equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2dRtt), + false))); + assertTrue(featureInfra.equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2dRtt), + true))); + assertTrue(combineBitsets(featureInfra, featureD2apRtt).equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2apRtt), + false))); + assertTrue(featureInfra.equals( + testGetSupportedFeaturesCaseForRtt(combineBitsets(featureInfra, featureD2apRtt), + true))); + assertTrue(combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt).equals( testGetSupportedFeaturesCaseForRtt( - featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, false)); - assertEquals(featureLongBits | featureInfra, + combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt), + false))); + assertTrue(featureInfra.equals( testGetSupportedFeaturesCaseForRtt( - featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true)); + combineBitsets(featureInfra, featureD2dRtt, featureD2apRtt), + true))); } @Test @@ -5345,9 +5423,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { // Location state changes ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); - verify(mContext).registerReceiver( + verify(mContext).registerReceiverForAllUsers( bcastRxCaptor.capture(), - argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + eq(null), any(Handler.class)); BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); @@ -5373,13 +5452,17 @@ public class ActiveModeWardenTest extends WifiBaseTest { @Test public void testWepNotDeprecated() throws Exception { when(mWifiGlobals.isWepSupported()).thenReturn(true); - enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WEP); + BitSet featureSet = + addCapabilitiesToBitset(TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_WEP); + enterClientModeActiveState(false, featureSet); } @Test public void testWpaPersonalNotDeprecated() throws Exception { when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false); - enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WPA_PERSONAL); + BitSet featureSet = + addCapabilitiesToBitset(TEST_FEATURE_SET, WifiManager.WIFI_FEATURE_WPA_PERSONAL); + enterClientModeActiveState(false, featureSet); } @Test @@ -5405,4 +5488,21 @@ public class ActiveModeWardenTest extends WifiBaseTest { verify(mWifiGlobals).setD2dStaConcurrencySupported(true); verify(mWifiGlobals, atLeastOnce()).isD2dSupportedWhenInfraStaDisabled(); } + + @Test + public void testGetNumberOf11beSoftApManager() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + enterSoftApActiveMode(); + when(mSoftApManager.isStarted()).thenReturn(true); + SoftApModeConfiguration mockSoftApModeConfiguration = mock(SoftApModeConfiguration.class); + SoftApConfiguration mockSoftApConfiguration = mock(SoftApConfiguration.class); + when(mockSoftApConfiguration.isIeee80211beEnabled()).thenReturn(true); + when(mockSoftApModeConfiguration.getSoftApConfiguration()) + .thenReturn(mockSoftApConfiguration); + when(mSoftApManager.getSoftApModeConfiguration()).thenReturn(mockSoftApModeConfiguration); + assertEquals(1, mActiveModeWarden.getNumberOf11beSoftApManager()); + when(mockSoftApConfiguration.isIeee80211beEnabled()).thenReturn(false); + assertEquals(0, mActiveModeWarden.getNumberOf11beSoftApManager()); + } + } diff --git a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index fddabc74b8..ca4d224336 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -46,6 +46,7 @@ import static com.android.server.wifi.ClientModeImpl.CMD_UNWANTED_NETWORK; import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE; import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -641,6 +642,7 @@ public class ClientModeImplTest extends WifiBaseTest { when(mWifiNative.connectToNetwork(any(), any())).thenReturn(true); when(mWifiNative.getApfCapabilities(anyString())).thenReturn(APF_CAP); when(mWifiNative.isQosPolicyFeatureEnabled()).thenReturn(true); + when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet()); } /** Reset verify() counters on WifiNative, and restore when() mocks on mWifiNative */ @@ -733,7 +735,8 @@ public class ClientModeImplTest extends WifiBaseTest { when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread); when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator); @@ -852,6 +855,7 @@ public class ClientModeImplTest extends WifiBaseTest { assertNotNull(mOffloadDisabledListenerArgumentCaptor.getValue()); mCmi.enableVerboseLogging(true); + mCmi.disconnect(); mLooper.dispatchAll(); verify(mWifiLastResortWatchdog, atLeastOnce()).clearAllFailureCounts(); @@ -1574,6 +1578,29 @@ public class ClientModeImplTest extends WifiBaseTest { assertEquals("L3ProvisioningState", getCurrentState().getName()); } + private void setupCarrierConnectionNotSimBased() throws Exception { + mConnectedNetwork.carrierId = CARRIER_ID_1; + when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(any(WifiConfiguration.class))) + .thenReturn(DATA_SUBID); + when(mWifiCarrierInfoManager.isSimReady(DATA_SUBID)).thenReturn(true); + + triggerConnect(); + + when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) + .thenReturn(mScanDetailCache); + when(mScanDetailCache.getScanDetail(TEST_BSSID_STR)).thenReturn( + getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq)); + when(mScanDetailCache.getScanResult(TEST_BSSID_STR)).thenReturn( + getGoogleGuestScanDetail(TEST_RSSI, TEST_BSSID_STR, sFreq).getScanResult()); + + WifiSsid wifiSsid = WifiSsid.fromBytes( + NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(mConnectedNetwork.SSID))); + mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, + new NetworkConnectionEventInfo(0, wifiSsid, TEST_BSSID_STR, false, null)); + mLooper.dispatchAll(); + assertEquals("L3ProvisioningState", getCurrentState().getName()); + } + @Test public void testUpdatingOobPseudonymToSupplicant() throws Exception { when(mWifiCarrierInfoManager.isOobPseudonymFeatureEnabled(anyInt())).thenReturn(true); @@ -1778,6 +1805,25 @@ public class ClientModeImplTest extends WifiBaseTest { } /** + * When the default data SIM is changed, if the current wifi connection is carrier wifi, + * the connection should be disconnected, and if the network is not SIM-based, no notification + * should be send + */ + @Test + public void testDefaultDataSimChangedNotSimBased() throws Exception { + setupCarrierConnectionNotSimBased(); + doReturn(false).when(mWifiCarrierInfoManager).isSimReady(eq(DATA_SUBID)); + mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS, + ClientModeImpl.RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED); + mLooper.dispatchAll(); + + verify(mWifiNative, times(2)).removeAllNetworks(WIFI_IFACE_NAME); + verify(mWifiMetrics).logStaEvent(anyString(), eq(StaEvent.TYPE_FRAMEWORK_DISCONNECT), + eq(StaEvent.DISCONNECT_RESET_SIM_NETWORKS)); + verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), anyString()); + } + + /** * Tests anonymous identity is set again whenever a connection is established for the carrier * that supports encrypted IMSI and anonymous identity and no real pseudonym was provided. */ @@ -2607,6 +2653,17 @@ public class ClientModeImplTest extends WifiBaseTest { verify(mActiveModeWarden).setCurrentNetwork(null); } + @Test + public void testWifiInfoNetworkIdSetInScanningState() throws Exception { + triggerConnect(); + assertEquals(WifiConfiguration.INVALID_NETWORK_ID, mWifiInfo.getNetworkId()); + mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, + new StateChangeResult(0, TEST_WIFI_SSID, TEST_BSSID_STR, sFreq, + SupplicantState.SCANNING)); + mLooper.dispatchAll(); + assertEquals(0, mWifiInfo.getNetworkId()); + } + /** * If caller tries to connect to a new network while still provisioning the current one, * the connection attempt should succeed. @@ -3294,7 +3351,7 @@ public class ClientModeImplTest extends WifiBaseTest { // "normal" commands. mCmi.sendMessage(ClientModeImpl.CMD_DISCONNECT); mLooper.dispatchAll(); - assertEquals(1, mCmi.copyLogRecs() + assertEquals(2, mCmi.copyLogRecs() .stream() .filter(logRec -> logRec.getWhat() == ClientModeImpl.CMD_DISCONNECT) .count()); @@ -3970,7 +4027,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, -42, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); @@ -4005,7 +4062,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, -42, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); @@ -4059,7 +4116,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, -42, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); @@ -4119,7 +4176,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, -42, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); @@ -4660,7 +4717,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -4687,7 +4744,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, TEST_RSSI, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -5407,7 +5464,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(0, RSSI_THRESHOLD_BREACH_MIN, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -6028,7 +6085,7 @@ public class ClientModeImplTest extends WifiBaseTest { failOnRssiChangeBroadcast(); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); mCmi.sendMessage(ClientModeImpl.CMD_RSSI_POLL, 1); @@ -6055,7 +6112,7 @@ public class ClientModeImplTest extends WifiBaseTest { failOnRssiChangeBroadcast(); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats stats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats); when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), @@ -6891,9 +6948,10 @@ public class ClientModeImplTest extends WifiBaseTest { when(mWifiConfigManager.getConfiguredNetworkWithoutMasking(anyInt())).thenReturn(config); if (isDriverSupportFils) { when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_FILS_SHA256 | WifiManager.WIFI_FEATURE_FILS_SHA384); + createCapabilityBitset(WifiManager.WIFI_FEATURE_FILS_SHA256, + WifiManager.WIFI_FEATURE_FILS_SHA384)); } else { - when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn((long) 0); + when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet()); } return config; @@ -7800,12 +7858,14 @@ public class ClientModeImplTest extends WifiBaseTest { final IpClientCallbacks callback = mIpClientCallback; final ReachabilityLossInfoParcelable lossInfo = new ReachabilityLossInfoParcelable("", lossReason); + assertNull(mCmi.getConnectingWifiConfiguration()); callback.onReachabilityFailure(lossInfo); callback.onProvisioningFailure(new LinkProperties()); mLooper.dispatchAll(); verify(mWifiNetworkAgent).unregisterAfterReplacement(anyInt()); verify(mWifiNative, never()).disconnect(WIFI_IFACE_NAME); assertEquals("L3ProvisioningState", getCurrentState().getName()); + assertEquals(FRAMEWORK_NETWORK_ID, mCmi.getConnectingWifiConfiguration().networkId); // Verify that onProvisioningFailure from the current IpClientCallbacks instance // triggers wifi disconnection. @@ -7983,7 +8043,7 @@ public class ClientModeImplTest extends WifiBaseTest { @Test public void testWifiScoreReportDump() throws Exception { when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); InOrder inOrder = inOrder(mWifiNative, mWifiScoreReport); inOrder.verify(mWifiNative, never()).getWifiLinkLayerStats(any()); connect(); @@ -8996,7 +9056,7 @@ public class ClientModeImplTest extends WifiBaseTest { clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis()); @@ -9040,7 +9100,7 @@ public class ClientModeImplTest extends WifiBaseTest { verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats()); // No link layer stats collection on secondary CMM. @@ -9059,7 +9119,7 @@ public class ClientModeImplTest extends WifiBaseTest { clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats()); // No link layer stats collection on secondary CMM. @@ -9092,7 +9152,7 @@ public class ClientModeImplTest extends WifiBaseTest { // RSSI polling is enabled on primary. when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis()); @@ -9121,7 +9181,7 @@ public class ClientModeImplTest extends WifiBaseTest { connect(); clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall); - when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(0L); + when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(new BitSet()); WifiLinkLayerStats stats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats); mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis()); @@ -9744,7 +9804,7 @@ public class ClientModeImplTest extends WifiBaseTest { throws Exception { if (isTrustOnFirstUseSupported) { when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); } mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler; @@ -10099,6 +10159,8 @@ public class ClientModeImplTest extends WifiBaseTest { assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR))); assertTrue(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR1))); assertFalse(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR2))); + // Check for null BSSID + assertFalse(mCmi.isAffiliatedLinkBssid(null)); } @Test @@ -10126,6 +10188,8 @@ public class ClientModeImplTest extends WifiBaseTest { mLooper.dispatchAll(); // Test isAffiliatedLinkBssid match fails with no NPE assertFalse(mCmi.isAffiliatedLinkBssid(MacAddress.fromString(TEST_BSSID_STR))); + // Check for null BSSID + assertFalse(mCmi.isAffiliatedLinkBssid(null)); } /** @@ -10817,7 +10881,7 @@ public class ClientModeImplTest extends WifiBaseTest { connect(); when(mWifiNative.getMaxSupportedConcurrentTdlsSessions(WIFI_IFACE_NAME)).thenReturn(1); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)) - .thenReturn(WifiManager.WIFI_FEATURE_TDLS); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_TDLS)); when(mWifiNative.startTdls(eq(WIFI_IFACE_NAME), eq(TEST_TDLS_PEER_ADDR_STR), anyBoolean())) .thenReturn(true); assertEquals(1, mCmi.getMaxSupportedConcurrentTdlsSessions()); @@ -10911,7 +10975,7 @@ public class ClientModeImplTest extends WifiBaseTest { WifiSignalPollResults signalPollResults = new WifiSignalPollResults(); signalPollResults.addEntry(TEST_MLO_LINK_ID, -42, 65, 54, sFreq); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); when(mClock.getWallClockMillis()).thenReturn(startMillis + 0); @@ -11142,4 +11206,21 @@ public class ClientModeImplTest extends WifiBaseTest { eq(WifiMetricsProto.ConnectionEvent.AUTH_FAILURE_EAP_FAILURE), anyInt(), eq(ClientModeImpl.EAP_FAILURE_CODE_CERTIFICATE_EXPIRED)); } + + /** + * Verify that the Sae H2E Feature is set even though config_wifiSaeH2eSupported + * is not enabled through overlay. + */ + @Test + public void testSaeH2eSetEvenThoughConfigForSaeH2eIsNotTrue() throws Exception { + when(mWifiNative.isSupplicantAidlServiceVersionAtLeast(3)).thenReturn(true); + when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_WPA3_SAE)); + initializeCmi(); + if (SdkLevel.isAtLeastV()) { + verify(mWifiGlobals).enableWpa3SaeH2eSupport(); + } else { + verify(mWifiGlobals, never()).enableWpa3SaeH2eSupport(); + } + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java index e30e8f8262..0f6ebe895c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ConcreteClientModeManagerTest.java @@ -187,13 +187,15 @@ public class ConcreteClientModeManagerTest extends WifiBaseTest { * * no deferring time for wifi off */ mStaticMockSession = mockitoSession() - .mockStatic(ImsMmTelManager.class) - .mockStatic(SubscriptionManager.class) - .startMocking(); + .mockStatic(ImsMmTelManager.class) + .mockStatic(SubscriptionManager.class) + .mockStatic(WifiInjector.class) + .startMocking(); lenient().when(ImsMmTelManager.createForSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID))) .thenReturn(mImsMmTelManager); lenient().when(SubscriptionManager.isValidSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID))) .thenReturn(true); + when(WifiInjector.getInstance()).thenReturn(mWifiInjector); doAnswer(new AnswerWithArguments() { public void answer(Executor executor, RegistrationManager.RegistrationCallback c) { mImsMmTelManagerRegistrationCallback = c; diff --git a/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java b/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java index dc8f7f676e..b282fd1b14 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ConfigurationMapTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -111,7 +112,8 @@ public class ConfigurationMapTest extends WifiBaseTest { when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); diff --git a/service/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java b/service/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java index 04536b8c55..40c46b08e8 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java @@ -52,10 +52,14 @@ import java.util.function.Consumer; */ @SmallTest public class DeviceConfigFacadeTest extends WifiBaseTest { + private static final String DRY_RUN_SCORER_PKG_NAME = + "com.google.android.apps.carrier.carrierwifi"; @Mock Context mContext; @Mock WifiMetrics mWifiMetrics; @Mock Consumer<Boolean> mOobPseudonymFeatureFlagChangedListener; + @Mock + Consumer<String> mDryRunScorerPkgNameChangedListener; final ArgumentCaptor<OnPropertiesChangedListener> mOnPropertiesChangedListenerCaptor = ArgumentCaptor.forClass(OnPropertiesChangedListener.class); @@ -105,6 +109,8 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { mOnPropertiesChangedListenerCaptor.capture())); mDeviceConfigFacade.setOobPseudonymFeatureFlagChangedListener( mOobPseudonymFeatureFlagChangedListener); + mDeviceConfigFacade.setDryRunScorerPkgNameChangedListener( + mDryRunScorerPkgNameChangedListener); } /** @@ -229,8 +235,11 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { assertEquals(true, mDeviceConfigFacade.isAwareSuspensionEnabled()); assertEquals(true, mDeviceConfigFacade.isHighPerfLockDeprecated()); assertEquals(true, mDeviceConfigFacade.isOobPseudonymEnabled()); + assertEquals(DeviceConfigFacade.DEFAULT_DRY_RUN_SCORER_PKG_NAME, + mDeviceConfigFacade.getDryRunScorerPkgName()); mLooper.dispatchAll(); verify(mOobPseudonymFeatureFlagChangedListener, never()).accept(anyBoolean()); + verify(mDryRunScorerPkgNameChangedListener, never()).accept(anyString()); assertEquals(true, mDeviceConfigFacade.isApplicationQosPolicyApiEnabled()); assertEquals(false, mDeviceConfigFacade.isAdjustPollRssiIntervalEnabled()); assertEquals(true, mDeviceConfigFacade.includePasspointSsidsInPnoScans()); @@ -451,6 +460,8 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { assertEquals(true, mDeviceConfigFacade.isAwareSuspensionEnabled()); assertEquals(true, mDeviceConfigFacade.isHighPerfLockDeprecated()); assertEquals(true, mDeviceConfigFacade.isOobPseudonymEnabled()); + assertEquals(DeviceConfigFacade.DEFAULT_DRY_RUN_SCORER_PKG_NAME, + mDeviceConfigFacade.getDryRunScorerPkgName()); assertEquals(true, mDeviceConfigFacade.isApplicationQosPolicyApiEnabled()); assertEquals(true, mDeviceConfigFacade.isAdjustPollRssiIntervalEnabled()); assertEquals(true, mDeviceConfigFacade.includePasspointSsidsInPnoScans()); @@ -463,10 +474,14 @@ public class DeviceConfigFacadeTest extends WifiBaseTest { when(DeviceConfig.getBoolean(anyString(), eq("oob_pseudonym_enabled"), anyBoolean())).thenReturn(false); + when(DeviceConfig.getString(anyString(), eq("dry_run_scorer_pkg_name"), anyString())) + .thenReturn(DRY_RUN_SCORER_PKG_NAME); mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null); mLooper.dispatchAll(); assertEquals(false, mDeviceConfigFacade.isOobPseudonymEnabled()); verify(mOobPseudonymFeatureFlagChangedListener).accept(false); + assertEquals(DRY_RUN_SCORER_PKG_NAME, mDeviceConfigFacade.getDryRunScorerPkgName()); + verify(mDryRunScorerPkgNameChangedListener).accept(DRY_RUN_SCORER_PKG_NAME); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java index 36e54b0680..a56ade7373 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/HalDeviceManagerTest.java @@ -23,6 +23,7 @@ import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDG import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_NAN; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_P2P; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; @@ -106,6 +107,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -1020,6 +1022,24 @@ public class HalDeviceManagerTest extends WifiBaseTest { HDM_CREATE_IFACE_AP, TEST_WORKSOURCE_1)); } + /** + * Test that BitSet comparisons are performed correctly in + * {@link HalDeviceManager#areChipCapabilitiesSupported(BitSet, BitSet)} + */ + @Test + public void testRequiredCapabilitiesComparison() { + BitSet capabilitySubset = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G); + BitSet capabilitySuperset = (BitSet) capabilitySubset.clone(); + capabilitySuperset.set(WifiManager.WIFI_FEATURE_BRIDGED_AP); + + assertTrue(HalDeviceManager.areChipCapabilitiesSupported( + capabilitySuperset /* current caps */, new BitSet() /* no desired caps */)); + assertTrue(HalDeviceManager.areChipCapabilitiesSupported( + capabilitySuperset /* current caps */, capabilitySubset /* desired caps */)); + assertFalse(HalDeviceManager.areChipCapabilitiesSupported( + capabilitySubset /* current caps */, capabilitySuperset /* desired caps */)); + } + ////////////////////////////////////////////////////////////////////////////////////// // Chip Specific Tests - but should work on all chips! // (i.e. add copies for each test chip) @@ -1738,6 +1758,36 @@ public class HalDeviceManagerTest extends WifiBaseTest { } /** + * Validate {@link HalDeviceManager#canDeviceSupportCreateTypeCombo(SparseArray)} with stored + * static chip info. + */ + @Test + public void testReportImpactToCreateIfaceChipV1WithStoredStaticChipInfo() + throws Exception { + TestChipV1 chipMock = new TestChipV1(); + chipMock.initialize(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); + + // Try to query iface support before starting the HAL. Should return true with the stored + // static chip info. + when(mWifiMock.isStarted()).thenReturn(false); + when(mWifiSettingsConfigStore.get(WifiSettingsConfigStore.WIFI_STATIC_CHIP_INFO)) + .thenReturn(TestChipV1.STATIC_CHIP_INFO_JSON_STRING); + assertTrue(mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_STA, true, TEST_WORKSOURCE_0).isEmpty()); + assertTrue(mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_AP, true, TEST_WORKSOURCE_0).isEmpty()); + assertNull(mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_AP_BRIDGE, true, TEST_WORKSOURCE_0)); + assertTrue(mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_0).isEmpty()); + assertTrue(mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_NAN, true, TEST_WORKSOURCE_0).isEmpty()); + + verifyNoMoreInteractions(mManagerStatusListenerMock); + } + + /** * Validates that {@link HalDeviceManager#canDeviceSupportCreateTypeCombo(SparseArray)} with * outdated stored static chip info will be updated once we load the chip info when the driver * is up. @@ -1755,7 +1805,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { "[" + " {" + " \"chipId\": 10," - + " \"chipCapabilities\": -1," + " \"availableModes\": [" + " {" + " \"id\": 0," @@ -3256,7 +3305,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { public void verify60GhzIfaceCreation( ChipMockBase chipMock, int chipModeId, int finalChipModeId, boolean isWigigSupported) throws Exception { - long requiredChipCapabilities = WifiManager.WIFI_FEATURE_INFRA_60G; + BitSet requiredChipCapabilities = + createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G); chipMock.initialize(); mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); executeAndValidateStartupSequence(); @@ -3318,7 +3368,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { when(mWorkSourceHelper1.getRequestorWsPriority()) .thenReturn(WorkSourceHelper.PRIORITY_PRIVILEGED); assertThat(mDut.isItPossibleToCreateIface(HDM_CREATE_IFACE_P2P, - WifiManager.WIFI_FEATURE_INFRA_60G, + createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA_60G), TEST_WORKSOURCE_1), is(isWigigSupported)); } } @@ -3987,6 +4037,104 @@ public class HalDeviceManagerTest extends WifiBaseTest { ); } + /** + * Validate a P2P request from requestors not on the P2P/NAN concurrency allowlist. + */ + @Test + public void testP2pNanConcurrencyNotAllowedTestChipV11() + throws Exception { + when(mResources.getStringArray(R.array.config_wifiP2pAwareConcurrencyAllowlist)).thenReturn( + new String[]{"Some other package"}); + + TestChipV11 chipMock = new TestChipV11(); + chipMock.initialize(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); + executeAndValidateStartupSequence(); + + InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class); + + // Create a NAN + WifiInterface nanIface = validateInterfaceSequence(chipMock, + false, // chipModeValid + -1000, // chipModeId (only used if chipModeValid is true) + HDM_CREATE_IFACE_NAN, + "wlan0", + TestChipV11.CHIP_MODE_ID, + null, // tearDownList + idl, // destroyedListener + TEST_WORKSOURCE_0 // requestorWs + ); + collector.checkThat("interface was null", nanIface, IsNull.notNullValue()); + + // P2P request from Worksource 1 (lower priority) should be blocked. + when(mWorkSourceHelper1.getRequestorWsPriority()) + .thenReturn(WorkSourceHelper.PRIORITY_FG_APP); + List<Pair<Integer, WorkSource>> p2pDetails = mDut.reportImpactToCreateIface( + HDM_CREATE_IFACE_P2P, true, TEST_WORKSOURCE_1); + if (SdkLevel.isAtLeastS()) { + assertNull("Should not be able to create this P2P", p2pDetails); + } else { + // Pre-S lets P2P/NAN destroy each other. + assertEquals(p2pDetails.get(0).second, TEST_WORKSOURCE_0); + } + + // P2P request from Worksource 2 (same privileged priority) should tear down NAN. + WifiInterface p2pIface = validateInterfaceSequence(chipMock, + true, // chipModeValid + TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) + HDM_CREATE_IFACE_P2P, + "wlan1", + TestChipV11.CHIP_MODE_ID, + new WifiInterface[]{nanIface}, // tearDownList + idl, // destroyedListener + TEST_WORKSOURCE_2 // requestorWs + ); + collector.checkThat("interface was null", p2pIface, IsNull.notNullValue()); + } + + /** + * Validate a P2P request from a requestor on the P2P/NAN concurrency allowlist. + */ + @Test + public void testP2pNanConcurrencyAllowedTestChipV11() + throws Exception { + when(mResources.getStringArray(R.array.config_wifiP2pAwareConcurrencyAllowlist)).thenReturn( + new String[]{TEST_WORKSOURCE_1.getPackageName(0)}); + + TestChipV11 chipMock = new TestChipV11(); + chipMock.initialize(); + mInOrder = inOrder(mWifiMock, chipMock.chip, mManagerStatusListenerMock); + executeAndValidateStartupSequence(); + + InterfaceDestroyedListener idl = mock(InterfaceDestroyedListener.class); + + // Create a NAN + WifiInterface nanIface = validateInterfaceSequence(chipMock, + false, // chipModeValid + -1000, // chipModeId (only used if chipModeValid is true) + HDM_CREATE_IFACE_NAN, + "wlan0", + TestChipV11.CHIP_MODE_ID, + null, // tearDownList + idl, // destroyedListener + TEST_WORKSOURCE_0 // requestorWs + ); + collector.checkThat("interface was null", nanIface, IsNull.notNullValue()); + + // P2P request from Worksource 1 (on allowlist) should be allowed. + WifiInterface p2pIface = validateInterfaceSequence(chipMock, + true, // chipModeValid + TestChipV11.CHIP_MODE_ID, // chipModeId (only used if chipModeValid is true) + HDM_CREATE_IFACE_P2P, + "wlan1", + TestChipV11.CHIP_MODE_ID, + null, // tearDownList + idl, // destroyedListener + TEST_WORKSOURCE_1 // requestorWs + ); + collector.checkThat("interface was null", p2pIface, IsNull.notNullValue()); + } + /////////////////////////////////////////////////////////////////////////////////////// // utilities /////////////////////////////////////////////////////////////////////////////////////// @@ -4164,7 +4312,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { private WifiInterface validateInterfaceSequence(ChipMockBase chipMock, boolean chipModeValid, int chipModeId, int createIfaceType, String ifaceName, int finalChipMode, - long requiredChipCapabilities, + BitSet requiredChipCapabilities, WifiInterface[] tearDownList, InterfaceDestroyedListener destroyedListener, WorkSource requestorWs, @@ -4361,8 +4509,8 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public WifiChip.Response<Long> answer() { - WifiChip.Response<Long> response = + public WifiChip.Response<BitSet> answer() { + WifiChip.Response<BitSet> response = new WifiChip.Response<>(mChipMockBase.chipCapabilities); response.setStatusCode(mChipMockBase.allowGetCapsBeforeIfaceCreated ? WifiHal.WIFI_STATUS_SUCCESS : WifiHal.WIFI_STATUS_ERROR_UNKNOWN); @@ -4679,7 +4827,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { public boolean chipModeValid = false; public int chipModeId = -1000; public int chipModeIdValidForRtt = -1; // single chip mode ID where RTT can be created - public long chipCapabilities = 0L; + public BitSet chipCapabilities = new BitSet(); public boolean allowGetCapsBeforeIfaceCreated = true; public List<WifiChip.WifiRadioCombination> chipSupportedRadioCombinations = null; public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>(); @@ -4756,7 +4904,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { static final String STATIC_CHIP_INFO_JSON_STRING = "[" + " {" + " \"chipId\": 10," - + " \"chipCapabilities\": 0," + " \"availableModes\": [" + " {" + " \"id\": 0," @@ -4833,7 +4980,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { static final String STATIC_CHIP_INFO_JSON_STRING = "[" + " {" + " \"chipId\": 12," - + " \"chipCapabilities\": 0," + " \"availableModes\": [" + " {" + " \"id\": 5," @@ -4982,7 +5128,7 @@ public class HalDeviceManagerTest extends WifiBaseTest { super.initialize(); chipMockId = CHIP_MOCK_V5; - chipCapabilities |= WifiManager.WIFI_FEATURE_INFRA_60G; + chipCapabilities.set(WifiManager.WIFI_FEATURE_INFRA_60G); // chip Id configuration ArrayList<Integer> chipIds; @@ -5039,7 +5185,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { static final String STATIC_CHIP_INFO_JSON_STRING = "[" + " {" + " \"chipId\": 6," - + " \"chipCapabilities\": 0," + " \"availableModes\": [" + " {" + " \"id\": 60," @@ -5222,7 +5367,6 @@ public class HalDeviceManagerTest extends WifiBaseTest { static final String STATIC_CHIP_INFO_JSON_STRING = "[" + " {" + " \"chipId\": 10," - + " \"chipCapabilities\": -1," + " \"availableModes\": [" + " {" + " \"id\": 100," @@ -5285,4 +5429,37 @@ public class HalDeviceManagerTest extends WifiBaseTest { configureDriverAvailableModes(); } } + + // Test chip configuration V11 for P2P/NAN concurrency + // mode: + // (STA + AP + NAN + P2P) + private class TestChipV11 extends ChipMockBase { + static final int CHIP_MODE_ID = 90; + + void initialize() throws Exception { + super.initialize(); + + // chip Id configuration + ArrayList<Integer> chipIds; + chipId = 11; + chipIds = new ArrayList<>(); + chipIds.add(chipId); + doAnswer(new GetChipIdsAnswer(true, chipIds)).when(mWifiMock).getChipIds(); + doAnswer(new GetChipAnswer(true, chip)).when(mWifiMock).getChip(anyInt()); + + // Initialize availableModes + availableModes = new ArrayList<>(); + + // Mode 90 (only one): (1xSTA + 1xAP + 1xP2P + 1xNAN) + WifiChip.ChipConcurrencyCombination combo1 = createConcurrencyCombo( + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_STA), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_AP), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_P2P), + createConcurrencyComboLimit(1, WifiChip.IFACE_CONCURRENCY_TYPE_NAN)); + availableModes.add(createChipMode(CHIP_MODE_ID, combo1)); + + chipModeIdValidForRtt = CHIP_MODE_ID; + doAnswer(new GetAvailableModesAnswer(this)).when(chip).getAvailableModes(); + } + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java index 8328dd3618..e8e1b9d1ad 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalAidlImpTest.java @@ -38,7 +38,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.test.MockAnswerUtil; -import android.content.Context; import android.hardware.wifi.hostapd.ApInfo; import android.hardware.wifi.hostapd.BandMask; import android.hardware.wifi.hostapd.ChannelBandwidth; @@ -54,11 +53,14 @@ import android.hardware.wifi.hostapd.Ieee80211ReasonCode; import android.hardware.wifi.hostapd.IfaceParams; import android.hardware.wifi.hostapd.NetworkParams; import android.net.MacAddress; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.OuiKeyedData; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.Builder; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.net.wifi.util.PersistableBundleUtils; +import android.net.wifi.util.WifiResourceCache; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -101,11 +103,15 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { private static final int TEST_FREQ_5G = 5745; private static final int TEST_BANDWIDTH = ChannelBandwidth.BANDWIDTH_20; private static final int TEST_GENERATION = Generation.WIFI_STANDARD_11N; + private static final int TEST_HAL_DEAUTHENTICATION_REASON_CODE = + android.hardware.wifi.common.DeauthenticationReasonCode.GROUP_CIPHER_NOT_VALID; + private static final int DEFAULT_DISCONNECT_REASON = + DeauthenticationReasonCode.REASON_UNKNOWN; private final int mBand256G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ; - private @Mock Context mContext; + private @Mock WifiContext mContext; private @Mock IHostapd mIHostapdMock; private @Mock IBinder mServiceBinderMock; private @Mock WifiNative.HostapdDeathEventHandler mHostapdHalDeathHandler; @@ -192,6 +198,7 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { mResources.setString(R.string.config_wifiSoftap6gChannelList, ""); when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(new WifiResourceCache(mContext)); doNothing().when(mIHostapdMock).addAccessPoint( mIfaceParamsCaptor.capture(), mNetworkParamsCaptor.capture()); doNothing().when(mIHostapdMock).removeAccessPoint(any()); @@ -867,6 +874,7 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { */ @Test public void testHostapdCallbackEvent() throws Exception { + when(mIHostapdMock.getInterfaceVersion()).thenReturn(3); executeAndValidateInitializationSequence(true); Builder configurationBuilder = new SoftApConfiguration.Builder(); configurationBuilder.setSsid(NETWORK_SSID); @@ -904,9 +912,25 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { clientInfo.isConnected = true; mIHostapdCallback.onConnectedClientsChanged(clientInfo); verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE), - eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true)); + eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true), + eq(DEFAULT_DISCONNECT_REASON)); verify(mSoftApHalCallback1, never()).onConnectedClientsChanged( - anyString(), any(), anyBoolean()); + anyString(), any(), anyBoolean(), anyInt()); + + // Trigger client disconnect + clientInfo = new ClientInfo(); + clientInfo.ifaceName = IFACE_NAME; + clientInfo.apIfaceInstance = TEST_AP_INSTANCE; + clientInfo.clientAddress = MacAddress.fromString(TEST_CLIENT_MAC).toByteArray(); + clientInfo.isConnected = false; + clientInfo.disconnectReasonCode = TEST_HAL_DEAUTHENTICATION_REASON_CODE; + mIHostapdCallback.onConnectedClientsChanged(clientInfo); + verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE), + eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(false), + eq(mHostapdHal.mapHalToFrameworkDeauthenticationReasonCode( + TEST_HAL_DEAUTHENTICATION_REASON_CODE))); + verify(mSoftApHalCallback1, never()).onConnectedClientsChanged( + anyString(), any(), anyBoolean(), anyInt()); } /** @@ -1194,15 +1218,50 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { mHostapdHal.registerApCallback(IFACE_NAME, mSoftApHalCallback); // Trigger on info changed and verify. + mockApInfoChangedAndVerify(IFACE_NAME, 1, mIHostapdCallback, mSoftApHalCallback); mockApInfoChangedAndVerify(IFACE_NAME, 2, mIHostapdCallback, mSoftApHalCallback); - // Trigger on failure from first instance. + // Trigger on instance failure from first instance. mIHostapdCallback.onFailure(IFACE_NAME, TEST_AP_INSTANCE); verify(mSoftApHalCallback).onInstanceFailure(TEST_AP_INSTANCE); // Trigger on failure from second instance. mIHostapdCallback.onFailure(IFACE_NAME, TEST_AP_INSTANCE_2); - verify(mSoftApHalCallback).onFailure(); + verify(mSoftApHalCallback).onInstanceFailure(TEST_AP_INSTANCE_2); + } + + /** + * Verifies the onFailure is ignored if it's for an instance that was already removed. + */ + @Test + public void testHostapdCallbackOnFailureIgnoredForAlreadyRemovedInstance() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + executeAndValidateInitializationSequence(true); + Builder configurationBuilder = new SoftApConfiguration.Builder(); + configurationBuilder.setSsid(NETWORK_SSID); + configurationBuilder.setBands(new int[] {SoftApConfiguration.BAND_2GHZ, + SoftApConfiguration.BAND_5GHZ}); + + doNothing().when(mIHostapdMock).addAccessPoint(any(), any()); + assertTrue(mHostapdHal.addAccessPoint(IFACE_NAME, + configurationBuilder.build(), true, + () -> mSoftApHalCallback.onFailure())); + verify(mIHostapdMock).addAccessPoint(any(), any()); + + // Register SoftApManager callback + mHostapdHal.registerApCallback(IFACE_NAME, mSoftApHalCallback); + + // Trigger on info changed and verify. + mockApInfoChangedAndVerify(IFACE_NAME, 1, mIHostapdCallback, mSoftApHalCallback); + + // Trigger on failure from first instance. + mIHostapdCallback.onFailure(IFACE_NAME, TEST_AP_INSTANCE); + verify(mSoftApHalCallback).onInstanceFailure(TEST_AP_INSTANCE); + + // Trigger on failure from first instance again. + mIHostapdCallback.onFailure(IFACE_NAME, TEST_AP_INSTANCE); + verify(mSoftApHalCallback, times(1)).onInstanceFailure(TEST_AP_INSTANCE); + verify(mSoftApHalCallback, never()).onFailure(); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java index f1a3c312d7..fa54288801 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalHidlImpTest.java @@ -15,16 +15,30 @@ */ package com.android.server.wifi; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyList; +import static org.mockito.Mockito.anyShort; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.test.MockAnswerUtil; -import android.content.Context; import android.hardware.wifi.hostapd.V1_0.HostapdStatus; import android.hardware.wifi.hostapd.V1_0.HostapdStatusCode; import android.hardware.wifi.hostapd.V1_0.IHostapd; @@ -35,8 +49,10 @@ import android.hardware.wifi.hostapd.V1_3.Generation; import android.hidl.manager.V1_0.IServiceManager; import android.hidl.manager.V1_0.IServiceNotification; import android.net.MacAddress; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.Builder; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.IHwBinder; @@ -71,11 +87,13 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { private static final String NETWORK_PSK = "test-psk"; private static final String TEST_CLIENT_MAC = "11:22:33:44:55:66"; private static final String TEST_AP_INSTANCE = "instance-wlan0"; + private static final int DEFAULT_DISCONNECT_REASON = + DeauthenticationReasonCode.REASON_UNKNOWN; private final int mBand256G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ; - private @Mock Context mContext; + private @Mock WifiContext mContext; private @Mock IServiceManager mServiceManagerMock; private @Mock IHostapd mIHostapdMock; private @Mock WifiNative.HostapdDeathEventHandler mHostapdHalDeathHandler; @@ -86,7 +104,7 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { private android.hardware.wifi.hostapd.V1_3.IHostapd mIHostapdMockV13; private IHostapdCallback mIHostapdCallback; private android.hardware.wifi.hostapd.V1_3.IHostapdCallback mIHostapdCallback13; - private MockResources mResources; + private MockResourceCache mResources; HostapdStatus mStatusSuccess; HostapdStatus mStatusFailure; android.hardware.wifi.hostapd.V1_2.HostapdStatus mStatusSuccess12; @@ -158,7 +176,7 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mResources = new MockResources(); + mResources = new MockResourceCache(mContext); mResources.setBoolean(R.bool.config_wifi_softap_acs_supported, false); mResources.setBoolean(R.bool.config_wifi_softap_ieee80211ac_supported, false); mResources.setBoolean(R.bool.config_wifiSoftapIeee80211axSupported, false); @@ -175,7 +193,7 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { mStatusSuccess12 = createHostapdStatus_1_2(HostapdStatusCode.SUCCESS); mStatusFailure12 = createHostapdStatus_1_2(HostapdStatusCode.FAILURE_UNKNOWN); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResources); when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn(true); when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), @@ -1329,9 +1347,10 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { mIHostapdCallback13.onConnectedClientsChanged(IFACE_NAME, TEST_AP_INSTANCE, MacAddress.fromString(TEST_CLIENT_MAC).toByteArray(), true); verify(mSoftApHalCallback).onConnectedClientsChanged(eq(TEST_AP_INSTANCE), - eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true)); + eq(MacAddress.fromString(TEST_CLIENT_MAC)), eq(true), + eq(DEFAULT_DISCONNECT_REASON)); verify(mSoftApHalCallback1, never()).onConnectedClientsChanged(anyString(), any(), - anyBoolean()); + anyBoolean(), anyInt()); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java index 579e6f7816..a8ec7da515 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/HostapdHalTest.java @@ -28,10 +28,10 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.Context; import android.net.MacAddress; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.Builder; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.test.TestLooper; @@ -53,7 +53,7 @@ public class HostapdHalTest extends WifiBaseTest { private IHostapdHal mIHostapd; private @Mock HostapdHalAidlImp mIHostapdAidlMock; private @Mock HostapdHalHidlImp mIHostapdHidlMock; - private @Mock Context mContext; + private @Mock WifiContext mContext; private @Mock WifiNative.HostapdDeathEventHandler mHostapdHalDeathHandler; private @Mock WifiNative.SoftApHalCallback mSoftApHalCallback; private TestLooper mLooper = new TestLooper(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java index f7a801b32e..96c6cb1af7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java @@ -34,6 +34,7 @@ import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.BitSet; /** * unit tests for {@link com.android.server.wifi.MboOceController}. @@ -75,14 +76,14 @@ public class MboOceControllerTest extends WifiBaseTest { * Helper function to initialize mboOceController */ private PhoneStateListener enableMboOceController(boolean isMboEnabled, boolean isOceEnabled) { - long featureSet = 0; + BitSet featureSet = new BitSet(); PhoneStateListener dataConnectionStateListener = null; if (isMboEnabled) { - featureSet |= WifiManager.WIFI_FEATURE_MBO; + featureSet.set(WifiManager.WIFI_FEATURE_MBO); } if (isOceEnabled) { - featureSet |= WifiManager.WIFI_FEATURE_OCE; + featureSet.set(WifiManager.WIFI_FEATURE_OCE); } when(mClientModeManager.getSupportedFeatures()).thenReturn(featureSet); diff --git a/service/tests/wifitests/src/com/android/server/wifi/MockResourceCache.java b/service/tests/wifitests/src/com/android/server/wifi/MockResourceCache.java new file mode 100644 index 0000000000..4f7b656814 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/MockResourceCache.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 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 com.android.server.wifi; + +import android.content.Context; +import android.net.wifi.util.WifiResourceCache; + +import java.util.HashMap; + +public class MockResourceCache extends WifiResourceCache { + + private final HashMap<Integer, Boolean> mBooleanValues; + private final HashMap<Integer, Integer> mIntegerValues; + private final HashMap<Integer, String> mStringValues; + private final HashMap<Integer, int[]> mIntArrayValues; + private final HashMap<Integer, String[]> mStringArrayValues; + + public MockResourceCache(Context context) { + super(context); + mBooleanValues = new HashMap<Integer, Boolean>(); + mIntegerValues = new HashMap<Integer, Integer>(); + mStringValues = new HashMap<Integer, String>(); + mIntArrayValues = new HashMap<Integer, int[]>(); + mStringArrayValues = new HashMap<Integer, String[]>(); + } + + @Override + public boolean getBoolean(int id) { + return mBooleanValues.getOrDefault(id, false); + } + + @Override + public int getInteger(int id) { + return mIntegerValues.getOrDefault(id, 0); + } + + @Override + public String getString(int id) { + return mStringValues.getOrDefault(id, null); + } + + @Override + public int[] getIntArray(int id) { + return mIntArrayValues.getOrDefault(id, null); + } + + @Override + public String[] getStringArray(int id) { + return mStringArrayValues.getOrDefault(id, null); + } + + public void setBoolean(int id, boolean value) { + mBooleanValues.put(id, value); + } + + public void setInteger(int id, int value) { + mIntegerValues.put(id, value); + } + + public void setString(int id, String value) { + mStringValues.put(id, value); + } + + public void setIntArray(int id, int[] value) { + mIntArrayValues.put(id, value); + } + + public void setStringArray(int id, String[] value) { + mStringArrayValues.put(id, value); + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/MockResources.java b/service/tests/wifitests/src/com/android/server/wifi/MockResources.java index e6ccb6e523..1473a1d23c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MockResources.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MockResources.java @@ -95,6 +95,11 @@ public class MockResources extends android.test.mock.MockResources { return 0; } + @Override + public String getResourceEntryName(int id) { + return String.valueOf(id); + } + public void setBoolean(int id, boolean value) { mBooleanValues.put(id, value); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/RssiMonitorTest.java b/service/tests/wifitests/src/com/android/server/wifi/RssiMonitorTest.java index 60eff99ff2..6866d587cb 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/RssiMonitorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/RssiMonitorTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.when; import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.util.WifiResourceCache; import android.os.Handler; import android.os.test.TestLooper; @@ -63,6 +64,7 @@ public class RssiMonitorTest extends WifiBaseTest { private TestLooper mLooper; @Mock WifiContext mContext; MockResources mMockResources = new MockResources(); + WifiResourceCache mWifiResourceCache; private final WifiInfo mWifiInfo = new ExtendedWifiInfo(mWifiGlobals, TEST_INTERFACE_NAME); @Mock WifiNative mWifiNative; @Mock Runnable mUpdateCapabilityRunnable; @@ -76,6 +78,8 @@ public class RssiMonitorTest extends WifiBaseTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mMockResources); + mWifiResourceCache = new WifiResourceCache(mContext); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); when(mDeviceConfigFacade.isAdjustPollRssiIntervalEnabled()).thenReturn(true); mMockResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, diff --git a/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java index 850f8a7a82..9cc7f5b438 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SavedNetworkNominatorTest.java @@ -19,6 +19,7 @@ package com.android.server.wifi; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; @@ -68,7 +69,8 @@ public class SavedNetworkNominatorTest extends WifiBaseTest { when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); diff --git a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java index eb38f5a4a2..77c9351aa5 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ScanResultMatchInfoTest.java @@ -18,6 +18,8 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -73,7 +75,7 @@ public class ScanResultMatchInfoTest extends WifiBaseTest { when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); when(mClientModeManager.getSupportedFeatures()).thenReturn( - WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE); + createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java index aeb84c21e5..bb7cfab8ac 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java @@ -29,6 +29,7 @@ import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING; import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; @@ -61,10 +62,10 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.net.MacAddress; import android.net.TetheringManager; import android.net.wifi.CoexUnsafeChannel; +import android.net.wifi.DeauthenticationReasonCode; import android.net.wifi.OuiKeyedData; import android.net.wifi.ScanResult; import android.net.wifi.SoftApCapability; @@ -79,6 +80,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.nl80211.DeviceWiphyCapabilities; import android.net.wifi.nl80211.NativeWifiClient; +import android.net.wifi.util.WifiResourceCache; import android.os.BatteryManager; import android.os.Message; import android.os.UserHandle; @@ -92,20 +94,24 @@ import android.util.SparseIntArray; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.internal.util.StateMachine; import com.android.internal.util.WakeupMessage; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.coex.CoexManager; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import com.google.common.collect.ImmutableList; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.quality.Strictness; import java.util.ArrayList; import java.util.Arrays; @@ -131,6 +137,7 @@ public class SoftApManagerTest extends WifiBaseTest { private static final String TEST_SECOND_INSTANCE_NAME = "testif2"; private static final String OTHER_INTERFACE_NAME = "otherif"; private static final String TEST_STA_INTERFACE_NAME = "testif0sta"; + private static final long TEST_START_TIME_MILLIS = 1234567890; private static final long TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLIS = 600_000; private static final long TEST_DEFAULT_SHUTDOWN_IDLE_INSTANCE_IN_BRIDGED_MODE_TIMEOUT_MILLIS = 300_000; @@ -159,6 +166,8 @@ public class SoftApManagerTest extends WifiBaseTest { private static final int TEST_AP_BANDWIDTH_FROM_IFACE_CALLBACK = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; private static final int TEST_AP_BANDWIDTH_IN_SOFTAPINFO = SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; + private static final int TEST_DISCONNECT_REASON = + DeauthenticationReasonCode.REASON_UNKNOWN; private static final int[] EMPTY_CHANNEL_ARRAY = {}; private static final int[] ALLOWED_2G_FREQS = {2462}; //ch# 11 private static final int[] ALLOWED_5G_FREQS = {5745, 5765}; //ch# 149, 153 @@ -195,7 +204,7 @@ public class SoftApManagerTest extends WifiBaseTest { private List<ClientModeManager> mTestClientModeManagers = new ArrayList<>(); @Mock WifiContext mContext; - @Mock Resources mResources; + @Mock WifiResourceCache mResourceCache; @Mock WifiNative mWifiNative; @Mock CoexManager mCoexManager; @Mock WifiServiceImpl.SoftApCallbackInternal mCallback; @@ -218,6 +227,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Mock InterfaceConflictManager mInterfaceConflictManager; @Mock WifiInjector mWifiInjector; @Mock WifiCountryCode mWifiCountryCode; + @Mock Clock mClock; @Mock LocalLog mLocalLog; @Mock DeviceWiphyCapabilities mDeviceWiphyCapabilities; @@ -238,6 +248,7 @@ public class SoftApManagerTest extends WifiBaseTest { ArgumentCaptor.forClass(BroadcastReceiver.class); SoftApManager mSoftApManager; + private StaticMockitoSession mStaticMockSession; /** Old callback event from wificond */ private void mockChannelSwitchEvent(int frequency, int bandwidth) { @@ -259,9 +270,9 @@ public class SoftApManagerTest extends WifiBaseTest { private void mockClientConnectedEvent(MacAddress mac, boolean isConnected, String apIfaceInstance, boolean updateTheTestMap) { mSoftApHalCallbackCaptor.getValue().onConnectedClientsChanged( - apIfaceInstance, mac, isConnected); + apIfaceInstance, mac, isConnected, TEST_DISCONNECT_REASON); if (mac == null || !updateTheTestMap) return; - WifiClient client = new WifiClient(mac, apIfaceInstance); + WifiClient client = new WifiClient(mac, apIfaceInstance, TEST_DISCONNECT_REASON); List<WifiClient> targetList = mTempConnectedClientListMap.get(apIfaceInstance); if (isConnected) { targetList.add(client); @@ -323,8 +334,14 @@ public class SoftApManagerTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mStaticMockSession = mockitoSession() + .mockStatic(WifiInjector.class) + .mockStatic(Flags.class) + .strictness(Strictness.LENIENT) + .startMocking(); mLooper = new TestLooper(); + when(WifiInjector.getInstance()).thenReturn(mWifiInjector); when(mWifiNative.isItPossibleToCreateApIface(any())).thenReturn(true); when(mWifiNative.isItPossibleToCreateBridgedApIface(any())).thenReturn(true); when(mWifiNative.isApSetMacAddressSupported(any())).thenReturn(true); @@ -340,24 +357,25 @@ public class SoftApManagerTest extends WifiBaseTest { mAlarmManager = new TestAlarmManager(); when(mContext.getSystemService(Context.ALARM_SERVICE)) .thenReturn(mAlarmManager.getAlarmManager()); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResourceCache); when(mContext.getWifiOverlayApkPkgName()).thenReturn("test.com.android.wifi.resources"); when(mContext.registerReceiver(any(), any())).thenReturn(new Intent()); - when(mResources.getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds)) + when(mResourceCache.getInteger( + R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds)) .thenReturn((int) TEST_DEFAULT_SHUTDOWN_TIMEOUT_MILLIS); - when(mResources.getInteger(R.integer + when(mResourceCache.getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond)) .thenReturn( (int) TEST_DEFAULT_SHUTDOWN_IDLE_INSTANCE_IN_BRIDGED_MODE_TIMEOUT_MILLIS); - when(mResources.getBoolean(R.bool.config_wifiBridgedSoftApSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiBridgedSoftApSupported)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true); when(mWifiNative.setApCountryCode( TEST_INTERFACE_NAME, TEST_COUNTRY_CODE.toUpperCase(Locale.ROOT))) .thenReturn(true); @@ -392,7 +410,7 @@ public class SoftApManagerTest extends WifiBaseTest { any(), any(), anyInt(), any(), anyBoolean())).thenReturn( InterfaceConflictManager.ICM_EXECUTE_COMMAND); // Default init STA enabled - when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) .thenReturn(true); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); when(mActiveModeWarden.getClientModeManagers()) @@ -407,6 +425,8 @@ public class SoftApManagerTest extends WifiBaseTest { when(mWifiNative.forceClientDisconnect(any(), any(), anyInt())).thenReturn(true); when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); when(mWifiInjector.getWifiCountryCode()).thenReturn(mWifiCountryCode); + when(mWifiInjector.getClock()).thenReturn(mClock); + when(mClock.getWallClockMillis()).thenReturn(TEST_START_TIME_MILLIS); when(mWifiNative.getDeviceWiphyCapabilities(any(), anyBoolean())).thenReturn( mDeviceWiphyCapabilities); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) @@ -452,6 +472,12 @@ public class SoftApManagerTest extends WifiBaseTest { mTempConnectedClientListMap.forEach((key, value) -> value.clear()); } + @After + public void cleanUp() throws Exception { + mStaticMockSession.finishMocking(); + } + + private SoftApConfiguration createDefaultApConfig() { Builder defaultConfigBuilder = new SoftApConfiguration.Builder(); defaultConfigBuilder.setSsid(DEFAULT_SSID); @@ -537,7 +563,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_INTERFACE_CONFLICT_USER_REJECTED), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** Verifies startSoftAp will skip checking for user approval for the Tethering case. */ @@ -614,7 +640,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_GENERAL), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -652,7 +678,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_GENERAL), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -694,7 +720,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_INTERFACE_CONFLICT), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -733,7 +759,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_CREATE_INTERFACE), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -767,7 +793,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_SET_COUNTRY_CODE), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -1012,7 +1038,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_ADD_AP_HOSTAPD), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } /** @@ -1027,9 +1053,13 @@ public class SoftApManagerTest extends WifiBaseTest { // reset to clear verified Intents for ap state change updates reset(mContext); + when(mContext.getResourceCache()).thenReturn(mResourceCache); InOrder order = inOrder(mCallback, mListener, mContext); + int sessionDurationSeconds = 3000; + when(mClock.getWallClockMillis()).thenReturn( + TEST_START_TIME_MILLIS + (sessionDurationSeconds * 1000)); mSoftApManager.stop(); mLooper.dispatchAll(); @@ -1065,6 +1095,10 @@ public class SoftApManagerTest extends WifiBaseTest { softApModeConfig.getTargetMode()); order.verify(mListener).onStopped(mSoftApManager); verify(mCmiMonitor).unregisterListener(mCmiListenerCaptor.getValue()); + verify(mWifiMetrics).writeSoftApStoppedEvent(eq(SoftApManager.STOP_EVENT_STOPPED), + any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), anyBoolean(), + eq(sessionDurationSeconds), anyInt(), anyInt(), anyInt(), anyBoolean(), anyInt(), + anyInt(), any()); } /** @@ -1079,7 +1113,7 @@ public class SoftApManagerTest extends WifiBaseTest { // reset to clear verified Intents for ap state change updates reset(mContext); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResourceCache); InOrder order = inOrder(mCallback, mListener, mContext); @@ -1157,7 +1191,7 @@ public class SoftApManagerTest extends WifiBaseTest { // reset to clear verified Intents for ap state change updates reset(mContext, mCallback, mWifiNative); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResourceCache); InOrder order = inOrder(mCallback, mListener, mContext); @@ -1225,7 +1259,7 @@ public class SoftApManagerTest extends WifiBaseTest { // reset to clear verified Intents for ap state change updates reset(mContext, mCallback, mWifiNative); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResourceCache); InOrder order = inOrder(mCallback, mListener, mContext); mSoftApHalCallbackCaptor.getValue().onFailure(); @@ -1279,7 +1313,10 @@ public class SoftApManagerTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mCallback, times(2)).onConnectedClientsOrInfoChanged( mTestSoftApInfoMap, mTestWifiClientsMap, true); - + when(mWifiNative.getBridgedApInstances(any())) + .thenReturn(new ArrayList<>(ImmutableList.of(TEST_FIRST_INSTANCE_NAME, + TEST_SECOND_INSTANCE_NAME)), + new ArrayList<>(ImmutableList.of(TEST_FIRST_INSTANCE_NAME))); // Trigger onInstanceFailure mSoftApHalCallbackCaptor.getValue().onInstanceFailure(TEST_SECOND_INSTANCE_NAME); mLooper.dispatchAll(); @@ -1311,6 +1348,11 @@ public class SoftApManagerTest extends WifiBaseTest { mLooper.dispatchAll(); // Trigger onInstanceFailure on the second instance + when(mWifiNative.getBridgedApInstances(eq(TEST_INTERFACE_NAME))) + .thenReturn(new ArrayList<>( + ImmutableList.of(TEST_FIRST_INSTANCE_NAME, TEST_SECOND_INSTANCE_NAME)), + new ArrayList<>( + ImmutableList.of(TEST_FIRST_INSTANCE_NAME))); mSoftApHalCallbackCaptor.getValue().onInstanceFailure(TEST_SECOND_INSTANCE_NAME); mLooper.dispatchAll(); // Verify the remove correct iface and instance @@ -1353,33 +1395,44 @@ public class SoftApManagerTest extends WifiBaseTest { // SoftApInfo updated mockSoftApInfoUpdateAndVerifyAfterSapStarted(true /* bridged mode*/, true); mLooper.dispatchAll(); - + when(mWifiNative.getBridgedApInstances(any())) + .thenReturn(null); // Trigger onInstanceFailure on the second instance mSoftApHalCallbackCaptor.getValue().onInstanceFailure(TEST_SECOND_INSTANCE_NAME); mLooper.dispatchAll(); - // Verify the remove correct iface and instance + // Verify the remove correct iface and instance but SAP off since it can't get instances. verify(mWifiNative).removeIfaceInstanceFromBridgedApIface(eq(TEST_INTERFACE_NAME), eq(TEST_SECOND_INSTANCE_NAME)); mLooper.dispatchAll(); mTestSoftApInfoMap.clear(); mTestWifiClientsMap.clear(); - mTestSoftApInfoMap.put(mTestSoftApInfoOnFirstInstance.getApInstanceIdentifier(), - mTestSoftApInfoOnFirstInstance); - mTestWifiClientsMap.put(mTestSoftApInfoOnFirstInstance.getApInstanceIdentifier(), - new ArrayList<WifiClient>()); - verify(mCallback, times(3)).onConnectedClientsOrInfoChanged( + verify(mCallback, times(4)).onConnectedClientsOrInfoChanged( mTestSoftApInfoMap, mTestWifiClientsMap, true); + } + @Test + public void testHostapdInstanceFailureBeforeSecondInstanceInitialized() + throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, generateBridgedModeSoftApConfig(null), + mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig); when(mWifiNative.getBridgedApInstances(any())) - .thenReturn(null); + .thenReturn(new ArrayList<>(ImmutableList.of(TEST_FIRST_INSTANCE_NAME, + TEST_SECOND_INSTANCE_NAME)), + new ArrayList<>(ImmutableList.of(TEST_SECOND_INSTANCE_NAME))); + // SoftApInfo updated for first instance only + mockApInfoChangedEvent(mTestSoftApInfoOnFirstInstance); + mLooper.dispatchAll(); - // Trigger onFailure since only left 1 instance - mSoftApHalCallbackCaptor.getValue().onFailure(); + // Trigger onInstanceFailure on the first instance + mSoftApHalCallbackCaptor.getValue().onInstanceFailure(TEST_FIRST_INSTANCE_NAME); mLooper.dispatchAll(); - mTestSoftApInfoMap.clear(); - mTestWifiClientsMap.clear(); - verify(mCallback, times(4)).onConnectedClientsOrInfoChanged( - mTestSoftApInfoMap, mTestWifiClientsMap, true); + // Verify AP remains up while waiting for the second instance. + verify(mWifiNative).removeIfaceInstanceFromBridgedApIface(eq(TEST_INTERFACE_NAME), + eq(TEST_FIRST_INSTANCE_NAME)); + verify(mWifiNative, never()).teardownInterface(TEST_INTERFACE_NAME); } @Test @@ -1953,9 +2006,9 @@ public class SoftApManagerTest extends WifiBaseTest { new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -2517,10 +2570,6 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiNative, never()).isItPossibleToCreateApIface(any()); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mFakeSoftApNotifier).dismissSoftApShutdownTimeoutExpiredNotification(); - order.verify(mWifiNative).setupInterfaceForSoftApMode( - mWifiNativeInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE), - eq(expectedConfig.getBand()), eq(expectedConfig.getBands().length > 1), - eq(mSoftApManager), anyList()); ArgumentCaptor<SoftApConfiguration> configCaptor = ArgumentCaptor.forClass(SoftApConfiguration.class); if (!TextUtils.isEmpty(softApConfig.getCountryCode()) @@ -2562,6 +2611,10 @@ public class SoftApManagerTest extends WifiBaseTest { assertThat(mSoftApManager.getSoftApModeConfiguration().getCapability().getCountryCode()) .isEqualTo("some country"); } + order.verify(mWifiNative).setupInterfaceForSoftApMode( + mWifiNativeInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE), + eq(expectedConfig.getBand()), eq(expectedConfig.getBands().length > 1), + eq(mSoftApManager), anyList()); order.verify(mCallback).onStateChanged(eq(new SoftApState( WifiManager.WIFI_AP_STATE_ENABLING, 0, softApConfig.getTetheringRequest(), TEST_INTERFACE_NAME))); @@ -2703,7 +2756,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_UNSUPPORTED_CONFIG), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } @Test @@ -2731,7 +2784,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_UNSUPPORTED_CONFIG), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } @Test @@ -2767,7 +2820,7 @@ public class SoftApManagerTest extends WifiBaseTest { verify(mWifiMetrics).writeSoftApStartedEvent( eq(SoftApManager.START_RESULT_FAILURE_UNSUPPORTED_CONFIG), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean(), anyInt(), - anyInt()); + anyInt(), eq(TEST_WORKSOURCE)); } @Test @@ -3161,9 +3214,9 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -3197,9 +3250,9 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -3308,9 +3361,9 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -3342,9 +3395,9 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -3519,8 +3572,8 @@ public class SoftApManagerTest extends WifiBaseTest { throws Exception { assumeTrue(SdkLevel.isAtLeastS()); String worldModeCC = "00"; - when(mContext.getResources() - .getString(R.string.config_wifiDriverWorldModeCountryCode)).thenReturn(worldModeCC); + when(mResourceCache.getString(R.string.config_wifiDriverWorldModeCountryCode)) + .thenReturn(worldModeCC); SoftApCapability testCapability = new SoftApCapability(mTestSoftApCapability); Builder configBuilder = new SoftApConfiguration.Builder( @@ -3759,7 +3812,7 @@ public class SoftApManagerTest extends WifiBaseTest { public void testBridgedModeKeepIfMovingFromUnsupportedCCtoSupportedCC() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); String worldModeCC = "00"; - when(mContext.getResources().getString(R.string.config_wifiDriverWorldModeCountryCode)) + when(mResourceCache.getString(R.string.config_wifiDriverWorldModeCountryCode)) .thenReturn(worldModeCC); // Simulate stale world mode CC without 5GHz band @@ -3782,7 +3835,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testWaitForDriverCountryCode() throws Exception { - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)).thenReturn(true); mIsDriverSupportedRegChangedEvent = true; SoftApModeConfiguration apConfig = @@ -3793,7 +3846,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testWaitForDriverCountryCodeTimedOut() throws Exception { - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)).thenReturn(true); mIsDriverSupportedRegChangedEvent = true; SoftApModeConfiguration apConfig = @@ -3815,7 +3868,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testWaitForDriverCountryCodeWhenNoInitialCountryCodeFor5GHz() throws Exception { - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)).thenReturn(true); mIsDriverSupportedRegChangedEvent = true; Builder configBuilder = new SoftApConfiguration.Builder(); @@ -3832,7 +3885,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testUpdateCountryCodeWhenConfigDisabled() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) .thenReturn(false); SoftApModeConfiguration apConfig = new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, @@ -3846,7 +3899,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testUpdateCountryCodeWhenConfigEnabled() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) .thenReturn(true); SoftApModeConfiguration apConfig = new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, @@ -3860,7 +3913,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testUpdateSameCountryCodeWhenConfigEnabled() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApDynamicCountryCodeUpdateSupported)) .thenReturn(true); SoftApModeConfiguration apConfig = new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, @@ -3876,7 +3929,7 @@ public class SoftApManagerTest extends WifiBaseTest { public void testFallbackToSingleModeDueToStaExistButStaWithBridgedApNotSupportedByOverlay() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); - when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) .thenReturn(false); Builder configBuilder = new SoftApConfiguration.Builder( generateBridgedModeSoftApConfig(null)); @@ -3894,7 +3947,7 @@ public class SoftApManagerTest extends WifiBaseTest { public void testFallbackToSingleModeDueToStaExistButStaWithBridgedApNotSupportedByDriver() throws Exception { assumeTrue(SdkLevel.isAtLeastS()); - when(mResources.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiStaWithBridgedSoftApConcurrencySupported)) .thenReturn(true); mApBridgeWithStaIfaceCombinationSupported = false; Builder configBuilder = new SoftApConfiguration.Builder( @@ -3963,7 +4016,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testSchedulesTimeoutTimerWhenPluggedChanged() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool + when(mResourceCache.getBoolean(R.bool .config_wifiFrameworkSoftApDisableBridgedModeShutdownIdleInstanceWhenCharging)) .thenReturn(true); @@ -3972,9 +4025,9 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer.config_wifiFrameworkSoftApShutDownTimeoutMilliseconds); - verify(mResources) + verify(mResourceCache) .getInteger(R.integer .config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond); @@ -4043,7 +4096,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApRemoves11BEIfNotSupportedByDeviceCapabilities() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(false); @@ -4067,7 +4120,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApRemoves11BEIfNotSupportedByOverlay() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(false); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(true); @@ -4091,7 +4144,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApRemoves11BEInWpa2()throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(true); @@ -4117,9 +4170,9 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApRemoves11BEInBridgedModeIfNotSupportedByOverlay()throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) .thenReturn(false); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(true); @@ -4146,9 +4199,9 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApInBridgedMode11BEConfiguration()throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) .thenReturn(true); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(true); @@ -4173,7 +4226,7 @@ public class SoftApManagerTest extends WifiBaseTest { @Test public void testStartSoftApInSingleAp11BEConfiguration()throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) .thenReturn(true); @@ -4189,4 +4242,171 @@ public class SoftApManagerTest extends WifiBaseTest { mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false); } + + /** + * Tests that 11BE configuration is disabled if there is existing 11Be SoftApManager. + */ + @Test + public void testStartSoftApWith11BEConfigurationWhenExistingOther11BeSoftApManager() + throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + when(Flags.mloSap()).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + .thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) + .thenReturn(false); + when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) + .thenReturn(true); + when(mActiveModeWarden.getNumberOf11beSoftApManager()).thenReturn(1); + mDeviceWiphyCapabilitiesSupports11Be = true; + Builder configBuilder = new SoftApConfiguration.Builder(); + configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); + configBuilder.setSsid(TEST_SSID); + configBuilder.setIeee80211beEnabled(true); + configBuilder.setPassphrase("somepassword", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), + mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + SoftApConfiguration expectedConfig = configBuilder.setIeee80211beEnabled(false).build(); + startSoftApAndVerifyEnabled(apConfig, expectedConfig, false); + } + + /** + * Tests that 11BE configuration is NOT disabled even if there is existing 11Be SoftApManager + * when device support single link MLO in bridged mode. (2 MLDs are allowed case) + */ + @Test + public void testStartSoftApWith11BEWhenExistingOther11BeSoftApButDualSingleLinkMLoSupported() + throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + when(Flags.mloSap()).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) + .thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) + .thenReturn(true); + when(mDeviceWiphyCapabilities.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11BE)) + .thenReturn(true); + when(mActiveModeWarden.getNumberOf11beSoftApManager()).thenReturn(1); + mDeviceWiphyCapabilitiesSupports11Be = true; + Builder configBuilder = new SoftApConfiguration.Builder(); + configBuilder.setBand(SoftApConfiguration.BAND_5GHZ); + configBuilder.setSsid(TEST_SSID); + configBuilder.setIeee80211beEnabled(true); + configBuilder.setPassphrase("somepassword", + SoftApConfiguration.SECURITY_TYPE_WPA3_SAE); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), + mTestSoftApCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig, configBuilder.build(), false); + } + + + @Test + public void testStartSoftApAutoUpgradeTo2g5gDbs() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mResourceCache.getBoolean( + R.bool.config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset)) + .thenReturn(true); + int[] dual_bands = {SoftApConfiguration.BAND_2GHZ, + SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ}; + + SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid(TEST_SSID) + .setSsid(TEST_SSID) + .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ + | SoftApConfiguration.BAND_6GHZ) + .build(); + SoftApConfiguration dualBandConfig = new SoftApConfiguration.Builder(config) + .setBands(dual_bands) + .build(); + + SoftApCapability no6GhzCapability = new SoftApCapability(mTestSoftApCapability); + no6GhzCapability.setSupportedChannelList(WifiScanner.WIFI_BAND_6_GHZ, new int[0]); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, config, + no6GhzCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig, dualBandConfig, false); + } + + @Test + public void testStartSoftApDoesNotAutoUpgradeTo2g5gDbsWhen6GhzAvailable() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean( + R.bool.config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset)) + .thenReturn(true); + + SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid(TEST_SSID) + .setSsid(TEST_SSID) + .setPassphrase("somepassword", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) + .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ + | SoftApConfiguration.BAND_6GHZ) + .build(); + + SoftApCapability with6GhzCapability = new SoftApCapability(mTestSoftApCapability); + with6GhzCapability.setSupportedChannelList( + SoftApConfiguration.BAND_6GHZ, new int[]{5, 21}); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, config, + with6GhzCapability, TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig, config, false); + } + + @Test + public void testStartSoftApAutoUpgradeTo2g5gDbsWithCountryCodeChange() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mResourceCache.getBoolean( + R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)).thenReturn(true); + mIsDriverSupportedRegChangedEvent = true; + when(mResourceCache.getBoolean( + R.bool.config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset)) + .thenReturn(true); + int[] dual_bands = {SoftApConfiguration.BAND_2GHZ, + SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ}; + + SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid(TEST_SSID) + .setSsid(TEST_SSID) + .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ + | SoftApConfiguration.BAND_6GHZ) + .build(); + SoftApConfiguration dualBandConfig = new SoftApConfiguration.Builder(config) + .setBands(dual_bands) + .build(); + + when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ)) + .thenReturn(new int[0]); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, config, + mTestSoftApCapability, "Not " + TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig, dualBandConfig, false); + } + + @Test + public void testStartSoftApDoesNotAutoUpgradeTo2g5gDbsWhen6GhzAvailableWithCountryCodeChange() + throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean( + R.bool.config_wifiDriverSupportedNl80211RegChangedEvent)).thenReturn(true); + mIsDriverSupportedRegChangedEvent = true; + when(mResourceCache.getBoolean( + R.bool.config_wifiSoftapUpgradeTetheredTo2g5gBridgedIfBandsAreSubset)) + .thenReturn(true); + + SoftApConfiguration config = new SoftApConfiguration.Builder().setSsid(TEST_SSID) + .setSsid(TEST_SSID) + .setPassphrase("somepassword", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE) + .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ + | SoftApConfiguration.BAND_6GHZ) + .build(); + + when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_6_GHZ)) + .thenReturn(ALLOWED_6G_FREQS); + SoftApModeConfiguration apConfig = new SoftApModeConfiguration( + WifiManager.IFACE_IP_MODE_TETHERED, config, + mTestSoftApCapability, "Not " + TEST_COUNTRY_CODE, TEST_TETHERING_REQUEST); + startSoftApAndVerifyEnabled(apConfig, config, false); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java index 108d4faf6f..b87832c669 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApStoreDataTest.java @@ -25,13 +25,16 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; +import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import android.app.test.MockAnswerUtil; import android.content.Context; import android.net.MacAddress; import android.net.wifi.SoftApConfiguration; +import android.net.wifi.SoftApInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiMigration; import android.net.wifi.WifiSsid; @@ -40,12 +43,14 @@ import android.util.Xml; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.internal.util.FastXmlSerializer; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.util.EncryptedData; import com.android.server.wifi.util.InformationElementUtil; import com.android.server.wifi.util.SettingsMigrationDataHolder; import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; +import com.android.wifi.flags.Flags; import org.junit.After; import org.junit.Before; @@ -53,6 +58,7 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; @@ -108,6 +114,9 @@ public class SoftApStoreDataTest extends WifiBaseTest { private static final boolean TEST_80211BE_ENABLED = false; private static final boolean TEST_USER_CONFIGURATION = false; private static final String TEST_TWO_VENDOR_ELEMENTS_HEX = "DD04AABBCCDDDD0401020304"; + private static final int TEST_MAX_CHANNEL_WIDTH = SoftApInfo.CHANNEL_WIDTH_40MHZ; + private MockitoSession mSession; + private static final String TEST_CONFIG_STRING_FROM_WIFICONFIGURATION = "<string name=\"WifiSsid\">" @@ -293,6 +302,11 @@ public class SoftApStoreDataTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + // Mock WifiMigration to avoid calling into its static methods + mSession = ExtendedMockito.mockitoSession() + .mockStatic(Flags.class, withSettings().lenient()) + .mockStatic(WifiMigration.class, withSettings().lenient()) + .startMocking(); when(mSettingsMigrationDataHolder.retrieveData()) .thenReturn(mOemMigrationData); when(mOemMigrationData.isSoftApTimeoutEnabled()).thenReturn(true); @@ -312,6 +326,7 @@ public class SoftApStoreDataTest extends WifiBaseTest { return mEncryptedDataMap.get(data); } }).when(mWifiConfigStoreEncryptionUtil).decrypt(any()); + when(Flags.softapConfigStoreMaxChannelWidth()).thenReturn(false); } /** @@ -321,6 +336,10 @@ public class SoftApStoreDataTest extends WifiBaseTest { public void cleanup() { TEST_BLOCKEDLIST.clear(); TEST_ALLOWEDLIST.clear(); + validateMockitoUsage(); + if (mSession != null) { + mSession.finishMocking(); + } } /** @@ -623,18 +642,16 @@ public class SoftApStoreDataTest extends WifiBaseTest { assertEquals(softApConfig.getBand(), TEST_BAND); } - /** - * Verify that the store data is serialized/deserialized correctly. - * - * @throws Exception - */ - @Test - public void serializeDeserializeSoftAp() throws Exception { + private void serializeDeserializeSoftAp(int expectedMaxChannelWidth, int actualMaxChannelWidth) + throws Exception { SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder(); softApConfigBuilder.setSsid(TEST_SSID); softApConfigBuilder.setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK); softApConfigBuilder.setBand(TEST_BAND); + if (SdkLevel.isAtLeastT()) { + softApConfigBuilder.setMaxChannelBandwidth(actualMaxChannelWidth); + } SoftApConfiguration softApConfig = softApConfigBuilder.build(); // Serialize first. @@ -657,6 +674,30 @@ public class SoftApStoreDataTest extends WifiBaseTest { assertEquals(softApConfig.isHiddenSsid(), softApConfigDeserialized.isHiddenSsid()); assertEquals(softApConfig.getBand(), softApConfigDeserialized.getBand()); assertEquals(softApConfig.getChannel(), softApConfigDeserialized.getChannel()); + if (SdkLevel.isAtLeastT()) { + assertEquals(expectedMaxChannelWidth, + softApConfigDeserialized.getMaxChannelBandwidth()); + } + } + + /** + * Verify that the store data is serialized/deserialized correctly with the feature + * Flags.softapConfigStoreMaxChannelWidth() disabled. + */ + @Test + public void serializeDeserializeSoftAp() throws Exception { + when(Flags.softapConfigStoreMaxChannelWidth()).thenReturn(false); + serializeDeserializeSoftAp(SoftApInfo.CHANNEL_WIDTH_AUTO, TEST_MAX_CHANNEL_WIDTH); + } + + /** + * Verify that the store data is serialized/deserialized correctly with the feature + * Flags.softapConfigStoreMaxChannelWidth() enabled. + */ + @Test + public void serializeDeserializeSoftApWithMaxChannelWidth() throws Exception { + when(Flags.softapConfigStoreMaxChannelWidth()).thenReturn(true); + serializeDeserializeSoftAp(TEST_MAX_CHANNEL_WIDTH, TEST_MAX_CHANNEL_WIDTH); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java index 8747683c77..77bd86f675 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalAidlImplTest.java @@ -24,9 +24,13 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS; +import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; +import static android.os.Build.VERSION.SDK_INT; + +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -52,9 +56,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; +import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import android.annotation.NonNull; import android.annotation.Nullable; @@ -114,7 +120,9 @@ import android.net.wifi.SupplicantState; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiManager; +import android.net.wifi.WifiMigration; import android.net.wifi.WifiSsid; +import android.net.wifi.flags.Flags; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; @@ -124,6 +132,7 @@ import android.text.TextUtils; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.MboOceController.BtmFrameData; import com.android.server.wifi.hal.HalTestUtils; @@ -132,6 +141,7 @@ import com.android.server.wifi.hotspot2.IconEvent; import com.android.server.wifi.hotspot2.WnmData; import com.android.server.wifi.util.NativeUtil; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -139,6 +149,7 @@ import org.mockito.Captor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import org.mockito.stubbing.Answer; import java.net.InetAddress; @@ -178,6 +189,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { private static final String HS20_URL = "http://blahblah"; private static final long PMK_CACHE_EXPIRATION_IN_SEC = 1024; private static final byte[] CONNECTED_MAC_ADDRESS_BYTES = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; + private static final long TIME_START_MS = 0L; private @Mock ISupplicant mISupplicantMock; private @Mock IBinder mServiceBinderMock; @@ -200,6 +212,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { IfaceInfo[] mIfaceInfoList; ISupplicantStaIfaceCallback mISupplicantStaIfaceCallback; + private MockitoSession mSession; private TestLooper mLooper = new TestLooper(); private Handler mHandler = null; private SupplicantStaIfaceHalSpy mDut; @@ -244,6 +257,11 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + // Mock WifiMigration to avoid calling into its static methods + mSession = ExtendedMockito.mockitoSession() + .mockStatic(Flags.class, withSettings().lenient()) + .mockStatic(WifiMigration.class, withSettings().lenient()) + .startMocking(); mIfaceInfoList = new IfaceInfo[3]; mIfaceInfoList[0] = createIfaceInfo(IfaceType.STA, WLAN0_IFACE_NAME); mIfaceInfoList[1] = createIfaceInfo(IfaceType.STA, WLAN1_IFACE_NAME); @@ -263,9 +281,18 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { return ssids; }); when(mWifiInjector.getSettingsConfigStore()).thenReturn(mWifiSettingsConfigStore); + when(Flags.legacyKeystoreToWifiBlobstoreMigrationReadOnly()).thenReturn(true); mDut = new SupplicantStaIfaceHalSpy(); } + @After + public void cleanup() { + validateMockitoUsage(); + if (mSession != null) { + mSession.finishMocking(); + } + } + /** * Sunny day scenario for SupplicantStaIfaceHal initialization * Asserts successful initialization @@ -1232,43 +1259,6 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { } /** - * Tests the handling of association rejection for WPA3-Personal networks - */ - @Test - public void testWpa3AuthRejectionEverConnected() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - WifiConfiguration config = executeAndValidateConnectSequenceWithKeyMgmt( - SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), - WifiConfiguration.SECURITY_TYPE_SAE, null, true); - mISupplicantStaIfaceCallback.onStateChanged( - StaIfaceCallbackState.ASSOCIATING, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false); - int statusCode = StaIfaceStatusCode.UNSPECIFIED_FAILURE; - AssociationRejectionData rejectionData = createAssocRejectData(SUPPLICANT_SSID, BSSID, - statusCode, false); - mISupplicantStaIfaceCallback.onAssociationRejected(rejectionData); - verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME), - anyInt(), anyInt(), any(), any()); - ArgumentCaptor<AssocRejectEventInfo> assocRejectEventInfoCaptor = - ArgumentCaptor.forClass(AssocRejectEventInfo.class); - verify(mWifiMonitor).broadcastAssociationRejectionEvent( - eq(WLAN0_IFACE_NAME), assocRejectEventInfoCaptor.capture()); - AssocRejectEventInfo assocRejectEventInfo = assocRejectEventInfoCaptor.getValue(); - assertNotNull(assocRejectEventInfo); - assertEquals(TRANSLATED_SUPPLICANT_SSID.toString(), assocRejectEventInfo.ssid); - assertEquals(BSSID, assocRejectEventInfo.bssid); - assertEquals(SupplicantStaIfaceCallbackAidlImpl.halToFrameworkStatusCode( - statusCode), assocRejectEventInfo.statusCode); - assertFalse(assocRejectEventInfo.timedOut); - assertNull(assocRejectEventInfo.oceRssiBasedAssocRejectInfo); - assertNull(assocRejectEventInfo.mboAssocDisallowedInfo); - } - - /** * Tests that association rejection due to timeout doesn't broadcast authentication failure * with reason code ERROR_AUTH_FAILURE_WRONG_PSWD. * Driver/Supplicant sets the timedOut field when there is no ACK or response frame for @@ -1409,6 +1399,9 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { public void testIeDiffers() throws Exception { executeAndValidateInitializationSequence(); assertNotNull(mISupplicantStaIfaceCallback); + executeAndValidateConnectSequenceWithKeyMgmt( + SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), + WifiConfiguration.SECURITY_TYPE_PSK, null, false); int reasonCode = StaIfaceReasonCode.IE_IN_4WAY_DIFFERS; @@ -1433,6 +1426,9 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { public void testApBusy() throws Exception { executeAndValidateInitializationSequence(); assertNotNull(mISupplicantStaIfaceCallback); + executeAndValidateConnectSequenceWithKeyMgmt( + SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), + WifiConfiguration.SECURITY_TYPE_PSK, null, false); int reasonCode = StaIfaceReasonCode.DISASSOC_AP_BUSY; @@ -1442,7 +1438,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { SUPPLICANT_NETWORK_ID, NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false); mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); + NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt(), any(), any()); } @@ -1798,12 +1794,12 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { /** * Helper function for tests involving getAdvancedCapabilities. */ - private void checkKeyMgmtCapabilities(int serviceCapabilities, long expectedCapabilities) + private void checkKeyMgmtCapabilities(int serviceCapabilities, BitSet expectedCapabilities) throws Exception { executeAndValidateInitializationSequence(); doReturn(serviceCapabilities).when(mISupplicantStaIfaceMock).getKeyMgmtCapabilities(); expectedCapabilities = addDefaultKeyMgmtCap(expectedCapabilities); - assertEquals(expectedCapabilities, mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(expectedCapabilities.equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -1811,7 +1807,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesWpa3Sae() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.SAE, WIFI_FEATURE_WPA3_SAE); + checkKeyMgmtCapabilities(KeyMgmtMask.SAE, createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); } /** @@ -1819,7 +1815,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesWpa3SuiteB() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.SUITE_B_192, WIFI_FEATURE_WPA3_SUITE_B); + checkKeyMgmtCapabilities(KeyMgmtMask.SUITE_B_192, + createCapabilityBitset(WIFI_FEATURE_WPA3_SUITE_B)); } /** @@ -1827,7 +1824,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesOwe() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.OWE, WIFI_FEATURE_OWE); + checkKeyMgmtCapabilities(KeyMgmtMask.OWE, createCapabilityBitset(WIFI_FEATURE_OWE)); } /** @@ -1836,7 +1833,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { @Test public void testGetKeyMgmtCapabilitiesOweAndSae() throws Exception { checkKeyMgmtCapabilities(KeyMgmtMask.OWE | KeyMgmtMask.SAE, - WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE); + createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE)); } /** @@ -1844,8 +1841,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesDpp() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.DPP, WIFI_FEATURE_DPP - | WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); + checkKeyMgmtCapabilities(KeyMgmtMask.DPP, + createCapabilityBitset(WIFI_FEATURE_DPP, WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); } /** @@ -1853,7 +1850,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesWapi() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, WIFI_FEATURE_WAPI); + checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, createCapabilityBitset(WIFI_FEATURE_WAPI)); } /** @@ -1861,7 +1858,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesFilsSha256() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256, WIFI_FEATURE_FILS_SHA256); + checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256, + createCapabilityBitset(WIFI_FEATURE_FILS_SHA256)); } /** @@ -1869,7 +1867,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesFilsSha384() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384, WIFI_FEATURE_FILS_SHA384); + checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384, + createCapabilityBitset(WIFI_FEATURE_FILS_SHA384)); } /** @@ -2133,7 +2132,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { executeAndValidateInitializationSequence(); doReturn(WpaDriverCapabilitiesMask.MBO).when(mISupplicantStaIfaceMock) .getWpaDriverCapabilities(); - assertEquals(WIFI_FEATURE_MBO, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -2144,8 +2144,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { executeAndValidateInitializationSequence(); doReturn(WpaDriverCapabilitiesMask.MBO | WpaDriverCapabilitiesMask.OCE) .when(mISupplicantStaIfaceMock).getWpaDriverCapabilities(); - assertEquals(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE, - mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -2156,8 +2156,23 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { executeAndValidateInitializationSequence(); doReturn(WpaDriverCapabilitiesMask.TRUST_ON_FIRST_USE) .when(mISupplicantStaIfaceMock).getWpaDriverCapabilities(); - assertEquals(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE, - mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_TRUST_ON_FIRST_USE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); + } + + /** + * Test RSN Overriding feature capability. + */ + @Test + public void testIsRsnOverridingSupported() throws Exception { + executeAndValidateInitializationSequence(); + doReturn(WpaDriverCapabilitiesMask.RSN_OVERRIDING) + .when(mISupplicantStaIfaceMock).getWpaDriverCapabilities(); + if (mDut.isServiceVersionAtLeast(4)) { + assertTrue(mDut.isRsnOverridingSupported(WLAN0_IFACE_NAME)); + } else { + assertFalse(mDut.isRsnOverridingSupported(WLAN0_IFACE_NAME)); + } } /** @@ -2263,30 +2278,6 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { } /** - * Tests the handling of incorrect network passwords when - * onStateChanged() is used, edge case. - * - * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch. - */ - @Test - public void testIeDiffersWhenOnStateChangedIsUsed() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - int reasonCode = StaIfaceReasonCode.IE_IN_4WAY_DIFFERS; - - mISupplicantStaIfaceCallback.onStateChanged( - StaIfaceCallbackState.FOURWAY_HANDSHAKE, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(SUPPLICANT_SSID)), false); - mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); - verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), - anyInt(), any(), any()); - } - - /** * Tests the handling of state change notification to * completed (with FILS HLP IE sent) after configuring a network. */ @@ -2374,6 +2365,16 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { assertNotNull(mISupplicantStaIfaceCallback); executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString()); + + // Do not broadcast NETWORK_NOT_FOUND for the specified duration. + mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( + NativeUtil.decodeSsid(SUPPLICANT_SSID))); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + + // NETWORK_NOT_FOUND should be broadcasted after the duration. + when(mClock.getElapsedSinceBootMillis()).thenReturn(TIME_START_MS + + SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS + 1); mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( NativeUtil.decodeSsid(SUPPLICANT_SSID))); @@ -2399,28 +2400,75 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { }); executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString()); + + // SSID was not found, but don't broadcast NETWORK_NOT_FOUND since we're still in + // the ignore duration. mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( NativeUtil.decodeSsid(SUPPLICANT_SSID))); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + validateConnectSequence(false, 1, TRANSLATED_SUPPLICANT_SSID.toString()); + + // Receive NETWORK_NOT_FOUND after the ignore duration. This should trigger a connection + // to the fallback without broadcasting NETWORK_NOT_FOUND yet. + long time = TIME_START_MS + + SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(time); + mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( + NativeUtil.decodeSsid(TRANSLATED_SUPPLICANT_SSID.toString()))); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + validateConnectSequence(false, 2, SUPPLICANT_SSID); - // Validate that we initiated another connect sequence to the fallback SUPPLICANT_SSID. + // Fallback SSID was not found, but don't broadcast NETWORK_NOT_FOUND because we're in the + // ignore duration for the fallback connection. + mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( + NativeUtil.decodeSsid(SUPPLICANT_SSID))); verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); validateConnectSequence(false, 2, SUPPLICANT_SSID); - // Fallback SSID was not found, finally broadcast NETWORK_NOT_FOUND and try the first SSID - // again. + // Receive NETWORK_NOT_FOUND after the new ignore duration. This should trigger a connection + // to the first SSID and finally broadcast the NETWORK_NOT_FOUND. + time += SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(time); mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( NativeUtil.decodeSsid(SUPPLICANT_SSID))); verify(mWifiMonitor).broadcastNetworkNotFoundEvent( eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); validateConnectSequence(false, 3, TRANSLATED_SUPPLICANT_SSID.toString()); + } - // First SSID not found, try the fallback without broadcasting NETWORK_NOT_FOUND. + /** + * Tests that network not found notification won't trigger connecting to the fallback SSIDs if + * the network has been disabled. + */ + @Test + public void testNetworkNotFoundCallbackDoesNotConnectToFallbackAfterDisabled() + throws Exception { + when(mSupplicantStaNetworkMock.disable()).thenReturn(true); + executeAndValidateInitializationSequence(); + assertNotNull(mISupplicantStaIfaceCallback); + // Setup mocks to return two possible original SSIDs. We will pick + // TRANSLATED_SUPPLICANT_SSID as the first SSID to try. + when(mSsidTranslator.getAllPossibleOriginalSsids(TRANSLATED_SUPPLICANT_SSID)).thenAnswer( + (Answer<List<WifiSsid>>) invocation -> { + List<WifiSsid> ssids = new ArrayList<>(); + ssids.add(TRANSLATED_SUPPLICANT_SSID); + ssids.add(WifiSsid.fromString(SUPPLICANT_SSID)); + return ssids; + }); + executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false, + TRANSLATED_SUPPLICANT_SSID.toString()); + + // Disable the current network and issue a NETWORK_NOT_FOUND + assertTrue(mDut.disableCurrentNetwork(WLAN0_IFACE_NAME)); + verify(mSupplicantStaNetworkMock).disable(); mISupplicantStaIfaceCallback.onNetworkNotFound(NativeUtil.byteArrayFromArrayList( - NativeUtil.decodeSsid(TRANSLATED_SUPPLICANT_SSID.toString()))); - verify(mWifiMonitor, times(1)).broadcastNetworkNotFoundEvent( - eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); - validateConnectSequence(false, 4, SUPPLICANT_SSID); + NativeUtil.decodeSsid(SUPPLICANT_SSID))); + + // Validate that we don't initiate another connect sequence. + validateConnectSequence(false, 1, TRANSLATED_SUPPLICANT_SSID.toString()); } /** @@ -2786,9 +2834,10 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { * Indicate support for key mgmt features supported by default in HIDL HAL V1.4, * i.e. the latest HIDL version before the conversion to AIDL. */ - private long addDefaultKeyMgmtCap(long capabilities) { - return capabilities | WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS - | WIFI_FEATURE_DECORATED_IDENTITY; + private BitSet addDefaultKeyMgmtCap(BitSet capabilities) { + capabilities.set(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS); + capabilities.set(WIFI_FEATURE_DECORATED_IDENTITY); + return capabilities; } /** @@ -3396,4 +3445,19 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { mDut.resendMscs(WLAN0_IFACE_NAME); verify(mISupplicantStaIfaceMock, times(2)).configureMscs(halParamsCaptor.capture()); } + + /** + * Verify that the Legacy Keystore migration only occurs once during the initial setup. + */ + @Test + public void testLegacyKeystoreMigration() throws Exception { + assumeTrue(SDK_INT >= 36); + executeAndValidateInitializationSequence(); + assertFalse(mDut.mHasMigratedLegacyKeystoreAliases); + + // Migration is complete when the consumer receives a success code + mDut.mKeystoreMigrationStatusConsumer.accept( + WifiMigration.KEYSTORE_MIGRATION_SUCCESS_MIGRATION_COMPLETE); + assertTrue(mDut.mHasMigratedLegacyKeystoreAliases); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java index 5d4507c69d..0bde06bf5e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalHidlImplTest.java @@ -26,6 +26,8 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_WAPI; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -107,6 +109,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -136,6 +139,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { private static final long PMK_CACHE_EXPIRATION_IN_SEC = 1024; private static final byte[] CONNECTED_MAC_ADDRESS_BYTES = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; + private static final long TIME_START_MS = 0L; private @Mock IServiceManager mServiceManagerMock; private @Mock ISupplicant mISupplicantMock; @@ -312,6 +316,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { ssids.add(TRANSLATED_SUPPLICANT_SSID); return ssids; }); + when(mClock.getElapsedSinceBootMillis()).thenReturn(TIME_START_MS); mDut = new SupplicantStaIfaceHalSpy(); } @@ -1465,42 +1470,6 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { } /** - * Tests the handling of association rejection for WPA3-Personal networks - */ - @Test - public void testWpa3AuthRejectionEverConnected() throws Exception { - executeAndValidateInitializationSequence(); - assertNotNull(mISupplicantStaIfaceCallback); - - WifiConfiguration config = executeAndValidateConnectSequenceWithKeyMgmt( - SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), - WifiConfiguration.SECURITY_TYPE_SAE, null, true); - mISupplicantStaIfaceCallback.onStateChanged( - ISupplicantStaIfaceCallback.State.ASSOCIATING, - NativeUtil.macAddressToByteArray(BSSID), - SUPPLICANT_NETWORK_ID, - NativeUtil.decodeSsid(SUPPLICANT_SSID)); - int statusCode = ISupplicantStaIfaceCallback.StatusCode.UNSPECIFIED_FAILURE; - mISupplicantStaIfaceCallback.onAssociationRejected( - NativeUtil.macAddressToByteArray(BSSID), statusCode, false); - verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME), - anyInt(), anyInt(), any(), any()); - ArgumentCaptor<AssocRejectEventInfo> assocRejectEventInfoCaptor = - ArgumentCaptor.forClass(AssocRejectEventInfo.class); - verify(mWifiMonitor).broadcastAssociationRejectionEvent( - eq(WLAN0_IFACE_NAME), assocRejectEventInfoCaptor.capture()); - AssocRejectEventInfo assocRejectEventInfo = - (AssocRejectEventInfo) assocRejectEventInfoCaptor.getValue(); - assertNotNull(assocRejectEventInfo); - assertEquals(TRANSLATED_SUPPLICANT_SSID.toString(), assocRejectEventInfo.ssid); - assertEquals(BSSID, assocRejectEventInfo.bssid); - assertEquals(statusCode, assocRejectEventInfo.statusCode); - assertFalse(assocRejectEventInfo.timedOut); - assertNull(assocRejectEventInfo.oceRssiBasedAssocRejectInfo); - assertNull(assocRejectEventInfo.mboAssocDisallowedInfo); - } - - /** * Tests that association rejection due to timeout doesn't broadcast authentication failure * with reason code ERROR_AUTH_FAILURE_WRONG_PSWD. * Driver/Supplicant sets the timedOut field when there is no ACK or response frame for @@ -1638,6 +1607,9 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { public void testIeDiffers() throws Exception { executeAndValidateInitializationSequence(); assertNotNull(mISupplicantStaIfaceCallback); + executeAndValidateConnectSequenceWithKeyMgmt( + SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), + WifiConfiguration.SECURITY_TYPE_PSK, null, false); int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS; @@ -1662,6 +1634,9 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { public void testApBusy() throws Exception { executeAndValidateInitializationSequence(); assertNotNull(mISupplicantStaIfaceCallback); + executeAndValidateConnectSequenceWithKeyMgmt( + SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), + WifiConfiguration.SECURITY_TYPE_PSK, null, false); int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.DISASSOC_AP_BUSY; @@ -1671,7 +1646,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { SUPPLICANT_NETWORK_ID, NativeUtil.decodeSsid(SUPPLICANT_SSID)); mISupplicantStaIfaceCallback.onDisconnected( - NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); + NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); verify(mWifiMonitor, never()).broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt(), any(), any()); } @@ -2179,7 +2154,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { } /** - * Test get advanced capabilities API on old HAL, should return 0 (not supported) + * Test get advanced capabilities API on old HAL, should return an empty BitSet (not supported) */ @Test public void testGetKeyMgmtCapabilitiesOldHal() throws Exception { @@ -2187,7 +2162,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { executeAndValidateInitializationSequenceV1_1(false, false); - assertTrue(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME) == 0); + assertTrue(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME).equals(new BitSet())); + } /** @@ -2205,7 +2181,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface .getKeyMgmtCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_WPA3_SAE, mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2223,8 +2200,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface .getKeyMgmtCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_WPA3_SUITE_B, - mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_WPA3_SUITE_B) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2242,7 +2219,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface .getKeyMgmtCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_OWE, mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_OWE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2261,8 +2239,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface .getKeyMgmtCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE, - mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2280,7 +2258,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_2.ISupplicantStaIface .getKeyMgmtCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_DPP, mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_DPP) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2297,9 +2276,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getKeyMgmtCapabilities_1_3Callback.class)); - assertTrue((WIFI_FEATURE_DPP_ENROLLEE_RESPONDER - & mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)) - == WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); + assertTrue(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME) + .get(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); } /** @@ -2317,9 +2295,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getKeyMgmtCapabilities_1_3Callback.class)); - assertFalse((WIFI_FEATURE_DPP_ENROLLEE_RESPONDER - & mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)) - == WIFI_FEATURE_DPP_ENROLLEE_RESPONDER); + assertFalse(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME) + .get(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); } /** @@ -2337,7 +2314,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getKeyMgmtCapabilities_1_3Callback.class)); - assertEquals(WIFI_FEATURE_WAPI, mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_WAPI) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2355,8 +2333,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getKeyMgmtCapabilities_1_3Callback.class)); - assertEquals(WIFI_FEATURE_FILS_SHA256, - mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_FILS_SHA256) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2374,8 +2352,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getKeyMgmtCapabilities_1_3Callback.class)); - assertEquals(WIFI_FEATURE_FILS_SHA384, - mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_FILS_SHA384) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -3506,15 +3484,15 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { /** * Test To get wpa driver capabilities API on old HAL, should - * return 0 (not supported) + * return an empty BitSet (not supported) */ @Test - public void tetGetWpaDriverCapabilitiesOldHal() throws Exception { + public void testGetWpaDriverCapabilitiesOldHal() throws Exception { setupMocksForHalV1_2(); executeAndValidateInitializationSequenceV1_2(); - assertEquals(0, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME).equals(new BitSet())); } /** @@ -3532,7 +3510,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getWpaDriverCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_MBO, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3552,8 +3531,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_3.ISupplicantStaIface .getWpaDriverCapabilitiesCallback.class)); - assertEquals(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE, - mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3573,8 +3552,8 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { android.hardware.wifi.supplicant.V1_4.ISupplicantStaIface .getWpaDriverCapabilities_1_4Callback.class)); - assertEquals(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE, - mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(createCapabilityBitset(WIFI_FEATURE_MBO, WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3751,6 +3730,9 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { setupMocksForHalV1_3(); executeAndValidateInitializationSequenceV1_3(); assertNotNull(mISupplicantStaIfaceCallbackV13); + executeAndValidateConnectSequenceWithKeyMgmt( + SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString(), + WifiConfiguration.SECURITY_TYPE_PSK, null, false); int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS; @@ -3852,8 +3834,16 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { setupMocksForHalV1_4(); executeAndValidateInitializationSequenceV1_4(); assertNotNull(mISupplicantStaIfaceCallbackV14); + + // Do not broadcast NETWORK_NOT_FOUND for the specified duration. mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + // NETWORK_NOT_FOUND should be broadcasted after the duration. + when(mClock.getElapsedSinceBootMillis()).thenReturn(TIME_START_MS + + SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS + 1); + mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); verify(mWifiMonitor).broadcastNetworkNotFoundEvent( eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); } @@ -3877,26 +3867,72 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { }); executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false, TRANSLATED_SUPPLICANT_SSID.toString()); + + // SSID was not found, but don't broadcast NETWORK_NOT_FOUND since we're still in + // the ignore duration. mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + validateConnectSequence(false, 1, TRANSLATED_SUPPLICANT_SSID.toString()); + + // Receive NETWORK_NOT_FOUND after the ignore duration. This should trigger a connection + // to the fallback without broadcasting NETWORK_NOT_FOUND yet. + long time = TIME_START_MS + + SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(time); + mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid( + TRANSLATED_SUPPLICANT_SSID.toString())); + verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( + eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); + validateConnectSequence(false, 2, SUPPLICANT_SSID); - // Validate that we initiated another connect sequence to the fallback SUPPLICANT_SSID. + // Fallback SSID was not found, but don't broadcast NETWORK_NOT_FOUND because we're in the + // ignore duration for the fallback connection. + mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); verify(mWifiMonitor, never()).broadcastNetworkNotFoundEvent( eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); validateConnectSequence(false, 2, SUPPLICANT_SSID); - // Fallback SSID was not found, finally broadcast NETWORK_NOT_FOUND and try the first SSID - // again. + // Receive NETWORK_NOT_FOUND after the new ignore duration. This should trigger a connection + // to the first SSID and finally broadcast the NETWORK_NOT_FOUND. + time += SupplicantStaIfaceHalHidlImpl.IGNORE_NETWORK_NOT_FOUND_DURATION_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(time); mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); verify(mWifiMonitor).broadcastNetworkNotFoundEvent( eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); validateConnectSequence(false, 3, TRANSLATED_SUPPLICANT_SSID.toString()); + } - // First SSID not found, try the fallback without broadcasting NETWORK_NOT_FOUND. - mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid( - TRANSLATED_SUPPLICANT_SSID.toString())); - verify(mWifiMonitor, times(1)).broadcastNetworkNotFoundEvent( - eq(WLAN0_IFACE_NAME), eq(TRANSLATED_SUPPLICANT_SSID.toString())); - validateConnectSequence(false, 4, SUPPLICANT_SSID); + /** + * Tests that network not found notification won't trigger connecting to the fallback SSIDs if + * the network has been disabled. + */ + @Test + public void testNetworkNotFoundCallbackDoesNotConnectToFallbackAfterDisabled() + throws Exception { + when(mSupplicantStaNetworkMock.disable()).thenReturn(true); + setupMocksForHalV1_4(); + executeAndValidateInitializationSequenceV1_4(); + assertNotNull(mISupplicantStaIfaceCallbackV14); + // Setup mocks to return two possible original SSIDs. We will pick + // TRANSLATED_SUPPLICANT_SSID as the first SSID to try. + when(mSsidTranslator.getAllPossibleOriginalSsids(TRANSLATED_SUPPLICANT_SSID)).thenAnswer( + (Answer<List<WifiSsid>>) invocation -> { + List<WifiSsid> ssids = new ArrayList<>(); + ssids.add(TRANSLATED_SUPPLICANT_SSID); + ssids.add(WifiSsid.fromString(SUPPLICANT_SSID)); + return ssids; + }); + executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false, + TRANSLATED_SUPPLICANT_SSID.toString()); + + // Disable the current network and issue a NETWORK_NOT_FOUND + assertTrue(mDut.disableCurrentNetwork(WLAN0_IFACE_NAME)); + verify(mSupplicantStaNetworkMock).disable(); + mISupplicantStaIfaceCallbackV14.onNetworkNotFound(NativeUtil.decodeSsid(SUPPLICANT_SSID)); + + // Validate that we don't initiate another connect sequence. + validateConnectSequence(false, 1, TRANSLATED_SUPPLICANT_SSID.toString()); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java index 6efeec6ebf..e93932b6f8 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java @@ -16,6 +16,10 @@ package com.android.server.wifi; +import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; + +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -49,6 +53,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.HashMap; import java.util.Map; @@ -925,9 +930,9 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest { @Test public void testGetAdvancedCapabilities() { initializeWithAidlImpl(true); - long capabilities = 0X1234; + BitSet capabilities = createCapabilityBitset(WIFI_FEATURE_OWE); // arbitrary feature when(mStaIfaceHalAidlMock.getAdvancedCapabilities(anyString())).thenReturn(capabilities); - assertEquals(capabilities, mDut.getAdvancedCapabilities(IFACE_NAME)); + assertTrue(capabilities.equals(mDut.getAdvancedCapabilities(IFACE_NAME))); verify(mStaIfaceHalAidlMock).getAdvancedCapabilities(eq(IFACE_NAME)); } @@ -937,9 +942,9 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest { @Test public void testGetWpaDriverFeatureSet() { initializeWithAidlImpl(true); - long capabilities = 0X1234; + BitSet capabilities = createCapabilityBitset(WIFI_FEATURE_OWE); // arbitrary feature when(mStaIfaceHalAidlMock.getWpaDriverFeatureSet(anyString())).thenReturn(capabilities); - assertEquals(capabilities, mDut.getWpaDriverFeatureSet(IFACE_NAME)); + assertTrue(capabilities.equals(mDut.getWpaDriverFeatureSet(IFACE_NAME))); verify(mStaIfaceHalAidlMock).getWpaDriverFeatureSet(eq(IFACE_NAME)); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java index fbd03da9c8..4d399f1142 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalAidlImplTest.java @@ -15,6 +15,8 @@ */ package com.android.server.wifi; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -104,8 +106,8 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { @Mock private Context mContext; @Mock private WifiMonitor mWifiMonitor; @Mock private WifiGlobals mWifiGlobals; - private long mAdvanceKeyMgmtFeatures = 0; - private long mWpaDriverFeatures = 0; + private BitSet mAdvanceKeyMgmtFeatures = new BitSet(); + private BitSet mWpaDriverFeatures = new BitSet(); private SupplicantNetworkVariables mSupplicantVariables; private MockResources mResources; @@ -122,7 +124,7 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false); - mAdvanceKeyMgmtFeatures |= WifiManager.WIFI_FEATURE_WPA3_SUITE_B; + mAdvanceKeyMgmtFeatures.set(WifiManager.WIFI_FEATURE_WPA3_SUITE_B); mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); @@ -1193,7 +1195,7 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { @Test public void testSupportedCiphersNoGcmp256() throws Exception { // Reinitialize mSupplicantNetwork without support for WPA3 SUITE-B - mAdvanceKeyMgmtFeatures = 0; + mAdvanceKeyMgmtFeatures.clear(); mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); @@ -1329,7 +1331,7 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { // Re-init mock to AIDL v2 without TLS v1.3 support. mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(2, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, - mWifiGlobals, mAdvanceKeyMgmtFeatures, 0); + mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); config.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); // Assume that the default params is used for this test. @@ -1347,10 +1349,10 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV2TlsV13Supported() throws Exception { // Re-init mock to AIDL v2 with TLS v1.3 support. + mWpaDriverFeatures = createCapabilityBitset(WifiManager.WIFI_FEATURE_TLS_V1_3); mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(2, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, - mWifiGlobals, mAdvanceKeyMgmtFeatures, - WifiManager.WIFI_FEATURE_TLS_V1_3); + mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); WifiConfiguration config = WifiConfigurationTestUtil.createEapNetwork(); config.enterpriseConfig.setMinimumTlsVersion(WifiEnterpriseConfig.TLS_V1_3); // Assume that the default params is used for this test. diff --git a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java index 191cc11135..d1e32ebcd7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SupplicantStaNetworkHalHidlImplTest.java @@ -15,6 +15,8 @@ */ package com.android.server.wifi; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -96,7 +98,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { @Mock private Context mContext; @Mock private WifiMonitor mWifiMonitor; @Mock private WifiGlobals mWifiGlobals; - private long mAdvanceKeyMgmtFeatures = 0; + private BitSet mAdvanceKeyMgmtFeatures = new BitSet(); private SupplicantNetworkVariables mSupplicantVariables; private MockResources mResources; @@ -121,7 +123,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { SupplicantStaNetworkHalSpyV1_2(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeatures) { + BitSet advanceKeyMgmtFeatures) { super(iSupplicantStaNetwork, ifaceName, context, monitor, wifiGlobals, advanceKeyMgmtFeatures); } @@ -141,7 +143,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { SupplicantStaNetworkHalSpyV1_3(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeatures) { + BitSet advanceKeyMgmtFeatures) { super(iSupplicantStaNetwork, ifaceName, context, monitor, wifiGlobals, advanceKeyMgmtFeatures); } @@ -161,7 +163,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { SupplicantStaNetworkHalSpyV1_4(ISupplicantStaNetwork iSupplicantStaNetwork, String ifaceName, Context context, WifiMonitor monitor, WifiGlobals wifiGlobals, - long advanceKeyMgmtFeatures) { + BitSet advanceKeyMgmtFeatures) { super(iSupplicantStaNetwork, ifaceName, context, monitor, wifiGlobals, advanceKeyMgmtFeatures); } @@ -190,7 +192,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false); - mAdvanceKeyMgmtFeatures |= WifiManager.WIFI_FEATURE_WPA3_SUITE_B; + mAdvanceKeyMgmtFeatures = createCapabilityBitset(WifiManager.WIFI_FEATURE_WPA3_SUITE_B); createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_0); } @@ -1608,7 +1610,7 @@ public class SupplicantStaNetworkHalHidlImplTest extends WifiBaseTest { @Test public void testUnsupportingGcmp256Ciphers1_2OrHigher() throws Exception { - mAdvanceKeyMgmtFeatures = 0; + mAdvanceKeyMgmtFeatures.clear(); createSupplicantStaNetwork(SupplicantStaNetworkVersion.V1_2); WifiConfiguration config = WifiConfigurationTestUtil.createSaeNetwork(); int expectedHalPairwiseCiphers = diff --git a/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java index 2640209a1c..c12e064ab1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java +++ b/service/tests/wifitests/src/com/android/server/wifi/TestUtil.java @@ -26,6 +26,7 @@ import android.net.wifi.WifiManager; import android.os.PowerManager; import java.util.ArrayList; +import java.util.BitSet; /** * Utils for wifi tests. @@ -106,4 +107,45 @@ public class TestUtil { Intent intent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); broadcastReceiver.onReceive(context, intent); } + + /** + * Create a new capability BitSet containing the provided capabilities. + * + * @param capabilities One or more WifiManager.WIFI_FEATURE_* capabilities + */ + public static BitSet createCapabilityBitset(int... capabilities) { + BitSet capabilityBitset = new BitSet(); + for (int capability : capabilities) { + capabilityBitset.set(capability); + } + return capabilityBitset; + } + + /** + * Add additional capabilities to the provided BitSet. + * + * @param bitset BitSet that the capabilities should be added to + * @param capabilities One or more WifiManager.WIFI_FEATURE_* capabilities + */ + public static BitSet addCapabilitiesToBitset(BitSet bitset, int... capabilities) { + // Clone to avoid modifying the input BitSet + BitSet clonedBitset = (BitSet) bitset.clone(); + for (int capability : capabilities) { + clonedBitset.set(capability); + } + return clonedBitset; + } + + /** + * Combine several BitSets using an OR operation. + * + * @param bitsets BitSets that should be combined + */ + public static BitSet combineBitsets(BitSet... bitsets) { + BitSet combinedBitset = new BitSet(); + for (BitSet bitset : bitsets) { + combinedBitset.or(bitset); + } + return combinedBitset; + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java index 10ae4d9fbb..8674ed38ec 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -128,7 +129,8 @@ public class WakeupControllerTest extends WifiBaseTest { when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); when(mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)) .thenReturn(new int[]{DFS_CHANNEL_FREQ}); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java index d256106967..064283e044 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WakeupEvaluatorTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -106,7 +107,8 @@ public class WakeupEvaluatorTest extends WifiBaseTest { when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java index d1642fa328..77274c17ec 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiApConfigStoreTest.java @@ -42,7 +42,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.MacAddress; @@ -50,6 +49,7 @@ import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.Builder; import android.net.wifi.SoftApInfo; +import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; import android.os.Build; import android.os.Handler; @@ -100,7 +100,7 @@ public class WifiApConfigStoreTest extends WifiBaseTest { private final int mBand25660G = SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ | SoftApConfiguration.BAND_6GHZ | SoftApConfiguration.BAND_60GHZ; - @Mock private Context mContext; + @Mock private WifiContext mContext; @Mock private WifiInjector mWifiInjector; @Mock private WifiNative mWifiNative; @Mock private WifiMetrics mWifiMetrics; @@ -116,7 +116,7 @@ public class WifiApConfigStoreTest extends WifiBaseTest { @Mock private WifiSettingsConfigStore mWifiSettingsConfigStore; private Random mRandom; - private MockResources mResources; + private MockResourceCache mResources; @Mock private ApplicationInfo mMockApplInfo; @Mock private MacAddressUtil mMacAddressUtil; private SoftApStoreData.DataSource mDataStoreSource; @@ -138,7 +138,7 @@ public class WifiApConfigStoreTest extends WifiBaseTest { // Default assume true for all old test cases. when(mHalDeviceManager.isConcurrencyComboLoadedFromDriver()).thenReturn(true); /* Setup expectations for Resources to return some default settings. */ - mResources = new MockResources(); + mResources = new MockResourceCache(mContext); mResources.setString(R.string.config_wifiSoftap2gChannelList, TEST_DEFAULT_2G_CHANNEL_LIST); mResources.setString(R.string.wifi_tether_configure_ssid_default, @@ -148,7 +148,7 @@ public class WifiApConfigStoreTest extends WifiBaseTest { mResources.setBoolean(R.bool.config_wifiSoftapPassphraseAsciiEncodableCheck, true); setupAllBandsSupported(); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResources); when(mContext.getPackageManager()).thenReturn(mPackageManager); // build the known good 2G channel list: TEST_DEFAULT_2G_CHANNEL_LIST diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java index 1f5345c459..40f94fe9ff 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCandidatesTest.java @@ -19,6 +19,8 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE; import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -97,7 +99,7 @@ public class WifiCandidatesTest extends WifiBaseTest { when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); when(mClientModeManager.getSupportedFeatures()).thenReturn( - WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE); + createCapabilityBitset(WIFI_FEATURE_OWE, WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java index 71a7a82dd2..2c629de390 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCarrierInfoManagerTest.java @@ -2531,4 +2531,67 @@ public class WifiCarrierInfoManagerTest extends WifiBaseTest { wifiCaptor.capture()); assertThat(wifiCaptor.getValue()).containsExactly(DATA_SUBID, NON_DATA_SUBID); } + + @Test + public void isMobileDataEnabled_true() { + assumeTrue(SdkLevel.isAtLeastS()); + when(mDataTelephonyManager.isDataEnabled()).thenReturn(true); + assertTrue(mWifiCarrierInfoManager.isMobileDataEnabled()); + } + + @Test + public void isMobileDataEnabled_false_null() { + assumeTrue(SdkLevel.isAtLeastS()); + when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()) + .thenReturn(null); + mListenerArgumentCaptor.getValue().onSubscriptionsChanged(); + mLooper.dispatchAll(); + + assertFalse(mWifiCarrierInfoManager.isMobileDataEnabled()); + } + @Test + public void isMobileDataEnabled_false_empty() { + assumeTrue(SdkLevel.isAtLeastS()); + when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()) + .thenReturn(new ArrayList<>()); + mListenerArgumentCaptor.getValue().onSubscriptionsChanged(); + mLooper.dispatchAll(); + + assertFalse(mWifiCarrierInfoManager.isMobileDataEnabled()); + } + + @Test + public void isMobileDataEnabled_false_present() { + assumeTrue(SdkLevel.isAtLeastS()); + when(mDataTelephonyManager.isDataEnabled()).thenReturn(false); + when(mNonDataTelephonyManager.isDataEnabled()).thenReturn(false); + mListenerArgumentCaptor.getValue().onSubscriptionsChanged(); + mLooper.dispatchAll(); + + assertFalse(mWifiCarrierInfoManager.isMobileDataEnabled()); + } + + @Test + public void hasActiveSubInfo_true() { + assertTrue(mWifiCarrierInfoManager.hasActiveSubInfo()); + } + + @Test + public void hasActiveSubInfo_false_null() { + when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(null); + mListenerArgumentCaptor.getValue().onSubscriptionsChanged(); + mLooper.dispatchAll(); + + assertFalse(mWifiCarrierInfoManager.hasActiveSubInfo()); + } + + @Test + public void hasActiveSubInfo_false_empty() { + when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()) + .thenReturn(new ArrayList<>()); + mListenerArgumentCaptor.getValue().onSubscriptionsChanged(); + mLooper.dispatchAll(); + + assertFalse(mWifiCarrierInfoManager.hasActiveSubInfo()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index d5709575ed..75f044f76c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -16,9 +16,12 @@ package com.android.server.wifi; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static com.android.server.wifi.WifiConfigManager.BUFFERED_WRITE_ALARM_TAG; +import static com.android.server.wifi.WifiConfigurationUtil.validatePassword; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -115,6 +118,7 @@ import java.io.StringWriter; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -364,7 +368,8 @@ public class WifiConfigManagerTest extends WifiBaseTest { when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); @@ -2030,8 +2035,8 @@ public class WifiConfigManagerTest extends WifiBaseTest { */ @Test public void testEnterpriseConfigTofuStateMerge() { - long featureSet = WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; - when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet); + when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); // If the configuration has never connected, the merged TOFU connection state // should be set based on the latest external configuration. @@ -3335,7 +3340,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { for (WifiConfiguration network : mWifiConfigManager.getLinkedNetworksWithoutMasking( network1.networkId).values()) { assertTrue(network.getNetworkSelectionStatus().getCandidateSecurityParams() - .isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)); + .isSecurityType(SECURITY_TYPE_PSK)); } } @@ -4608,7 +4613,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { assertTrue(mWifiConfigManager.setNetworkCandidateScanResult(network2.networkId, createScanDetailForNetwork(network2).getScanResult(), 54, SecurityParams.createSecurityParamsBySecurityType( - WifiConfiguration.SECURITY_TYPE_PSK))); + SECURITY_TYPE_PSK))); // Retrieve the hidden network list & verify the order of the networks returned. List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks = @@ -4676,7 +4681,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { // successfully. WifiConfiguration network1 = new WifiConfiguration(); network1.SSID = ssid; - network1.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + network1.setSecurityParams(SECURITY_TYPE_PSK); network1.preSharedKey = "\"test_blah\""; NetworkUpdateResult result = addNetworkToWifiConfigManager(network1); assertTrue(result.getNetworkId() != WifiConfiguration.INVALID_NETWORK_ID); @@ -5551,6 +5556,43 @@ public class WifiConfigManagerTest extends WifiBaseTest { assertTrue(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled(visibleNetwork)); mWifiConfigManager.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE); + assertTrue(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled( + visibleNetwork)); + + mWifiConfigManager.considerStopRestrictingAutoJoinToSubscriptionId(); + assertFalse(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled( + visibleNetwork)); + } + + @Test + public void testFlakyNoCellularNotEnableNonCarrierMergedWifi() { + verifyAddNetworkToWifiConfigManager(WifiConfigurationTestUtil.createOpenNetwork()); + List<WifiConfiguration> retrievedNetworks = + mWifiConfigManager.getConfiguredNetworksWithPasswords(); + WifiConfiguration visibleNetwork = retrievedNetworks.get(0); + ScanDetail scanDetail = createScanDetailForNetwork(visibleNetwork, TEST_BSSID, + TEST_RSSI, TEST_FREQUENCY_1); + mWifiConfigManager.updateScanDetailCacheFromScanDetailForSavedNetwork(scanDetail); + + // verify the network is disabled after startRestrictingAutoJoinToSubscriptionId is called + when(mClock.getWallClockMillis()).thenReturn(0L); + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + mWifiConfigManager.startRestrictingAutoJoinToSubscriptionId(5); + mWifiConfigManager.updateUserDisabledList(new ArrayList<String>()); + assertTrue(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled(visibleNetwork)); + + // Simulate flaky cellular connection + mWifiConfigManager.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE); + mWifiConfigManager.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_AVAILABLE); + // wifi should still be disabled since cellular recovered + mWifiConfigManager.considerStopRestrictingAutoJoinToSubscriptionId(); + assertTrue(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled( + visibleNetwork)); + + // Cellular lost again + mWifiConfigManager.onCellularConnectivityChanged(WifiDataStall.CELLULAR_DATA_NOT_AVAILABLE); + mWifiConfigManager.considerStopRestrictingAutoJoinToSubscriptionId(); + // wifi should be enabled now assertFalse(mWifiConfigManager.isNonCarrierMergedNetworkTemporarilyDisabled( visibleNetwork)); } @@ -6799,7 +6841,13 @@ public class WifiConfigManagerTest extends WifiBaseTest { // Two networks should be merged into one. assertEquals(1, retrievedNetworks.size()); WifiConfiguration mergedNetwork = retrievedNetworks.get(0); - assertTrue(mergedNetwork.isSecurityType(baseSecurityType)); + if (baseConfig.isSecurityType(SECURITY_TYPE_PSK) + && !validatePassword(upgradableConfig.preSharedKey, false, false, false)) { + // PSK should be removed if we saved an SAE-only passphrase over it. + assertFalse(mergedNetwork.isSecurityType(SECURITY_TYPE_PSK)); + } else { + assertTrue(mergedNetwork.isSecurityType(baseSecurityType)); + } assertTrue(mergedNetwork.isSecurityType(upgradableSecurityType)); assertEquals(upgradableConfig.getDefaultSecurityParams().isAddedByAutoUpgrade(), mergedNetwork.getSecurityParams(upgradableSecurityType).isAddedByAutoUpgrade()); @@ -6814,7 +6862,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testAddUpgradableNetworkForPskSae() { WifiConfiguration baseConfig = new WifiConfiguration(); baseConfig.SSID = "\"upgradableNetwork\""; - baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); baseConfig.preSharedKey = "\"Passw0rd\""; WifiConfiguration upgradableConfig = new WifiConfiguration(); upgradableConfig.SSID = "\"upgradableNetwork\""; @@ -6825,6 +6873,24 @@ public class WifiConfigManagerTest extends WifiBaseTest { } /** + * Verifies the addition of an SAE network with an SAE-only passphrase over a PSK/SAE network. + * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} + */ + @Test + public void testAddUpgradableNetworkForPskSaeIncompatiblePassphrase() { + WifiConfiguration baseConfig = new WifiConfiguration(); + baseConfig.SSID = "\"upgradableNetwork\""; + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); + baseConfig.preSharedKey = "\"Passw0rd\""; + WifiConfiguration upgradableConfig = new WifiConfiguration(); + upgradableConfig.SSID = "\"upgradableNetwork\""; + upgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + upgradableConfig.preSharedKey = "\"P\""; + + verifyAddUpgradableNetwork(baseConfig, upgradableConfig); + } + + /** * Verifies that updating an existing upgradable network that was added by auto upgrade will * retain the isAddedByAutoUpgrade() value. * {@link WifiConfigManager#addOrUpdateNetwork(WifiConfiguration, int)} @@ -6833,7 +6899,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testUpdateUpgradedNetworkKeepsIsAddedByAutoUpgradeValue() { WifiConfiguration baseConfig = new WifiConfiguration(); baseConfig.SSID = "\"upgradableNetwork\""; - baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); baseConfig.preSharedKey = "\"Passw0rd\""; WifiConfiguration upgradedConfig = new WifiConfiguration(); upgradedConfig.SSID = "\"upgradableNetwork\""; @@ -6853,7 +6919,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testAddUnhiddenUpgradedNetworkOverwritesHiddenSsidValue() { WifiConfiguration baseConfig = new WifiConfiguration(); baseConfig.SSID = "\"upgradableNetwork\""; - baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); baseConfig.preSharedKey = "\"Passw0rd\""; baseConfig.hiddenSSID = true; WifiConfiguration upgradedConfig = new WifiConfiguration(); @@ -6873,7 +6939,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testAddHiddenUpgradedNetworkOverwritesHiddenSsidValue() { WifiConfiguration baseConfig = new WifiConfiguration(); baseConfig.SSID = "\"upgradableNetwork\""; - baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); baseConfig.preSharedKey = "\"Passw0rd\""; baseConfig.hiddenSSID = false; WifiConfiguration upgradedConfig = new WifiConfiguration(); @@ -6974,7 +7040,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { baseConfig.preSharedKey = "\"Passw0rd\""; WifiConfiguration downgradableConfig = new WifiConfiguration(); downgradableConfig.SSID = "\"downgradableNetwork\""; - downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK); downgradableConfig.preSharedKey = "\"Passw0rd\""; verifyAddDowngradableNetwork( @@ -7035,7 +7101,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { baseConfig.hiddenSSID = true; WifiConfiguration downgradableConfig = new WifiConfiguration(); downgradableConfig.SSID = "\"downgradableConfig\""; - downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK); downgradableConfig.preSharedKey = "\"Passw0rd\""; downgradableConfig.hiddenSSID = false; @@ -7055,7 +7121,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { baseConfig.hiddenSSID = false; WifiConfiguration downgradableConfig = new WifiConfiguration(); downgradableConfig.SSID = "\"downgradableConfig\""; - downgradableConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + downgradableConfig.setSecurityParams(SECURITY_TYPE_PSK); downgradableConfig.preSharedKey = "\"Passw0rd\""; downgradableConfig.hiddenSSID = true; @@ -7098,7 +7164,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testLoadFromStoreMergeUpgradableConfigurationsPskSae() { WifiConfiguration baseConfig = new WifiConfiguration(); baseConfig.SSID = "\"upgradableNetwork\""; - baseConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + baseConfig.setSecurityParams(SECURITY_TYPE_PSK); baseConfig.preSharedKey = "\"Passw0rd\""; WifiConfiguration upgradableConfig = new WifiConfiguration(); upgradableConfig.SSID = "\"upgradableNetwork\""; @@ -7399,7 +7465,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { int networkIdBefore = verifyAddNetworkToWifiConfigManager(testNetwork).getNetworkId(); WifiConfiguration configBefore = mWifiConfigManager.getConfiguredNetwork(networkIdBefore); assertFalse(configBefore.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)); - assertTrue(configBefore.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)); + assertTrue(configBefore.isSecurityType(SECURITY_TYPE_PSK)); // Change the type from PSK to Open. testNetwork.networkId = networkIdBefore; @@ -7409,7 +7475,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { assertEquals(networkIdBefore, networkIdAfter); WifiConfiguration configAfter = mWifiConfigManager.getConfiguredNetwork(networkIdAfter); - assertFalse(configAfter.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)); + assertFalse(configAfter.isSecurityType(SECURITY_TYPE_PSK)); assertTrue(configAfter.isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN)); } @@ -7939,7 +8005,10 @@ public class WifiConfigManagerTest extends WifiBaseTest { } private void verifyAddTofuEnterpriseConfig(boolean isTofuSupported) { - long featureSet = isTofuSupported ? WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE : 0L; + BitSet featureSet = new BitSet(); + if (isTofuSupported) { + featureSet.set(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + } when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet); WifiConfiguration config = prepareTofuEapConfig( @@ -8061,7 +8130,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); @@ -8076,7 +8145,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificatePathSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); @@ -8094,7 +8163,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateWithoutAltSubjectNames() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8120,7 +8189,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateWithAltSubjectNames() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8160,7 +8229,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateFaiulreInvalidArgument() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int openNetId = verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8196,7 +8265,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateSuccessWithSelfSignedCertificate() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); X509Certificate mockCaCert = mock(X509Certificate.class); @@ -8212,7 +8281,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateServerCertificateHashSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); assertTrue(mWifiConfigManager.updateCaCertificate(eapPeapNetId, FakeKeys.CA_CERT1, @@ -8227,7 +8296,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testUpdateCaCertificateFailureWithSelfSignedCertificateAndTofuNotEnabled() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + createCapabilityBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); X509Certificate mockCaCert = mock(X509Certificate.class); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java index 8dbe628f5c..f938371f5e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import static android.net.wifi.WifiEnterpriseConfig.OCSP_NONE; import static android.net.wifi.WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -53,9 +54,11 @@ import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; +import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.List; @@ -76,7 +79,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { static final List<UserInfo> PROFILES = Arrays.asList( new UserInfo(CURRENT_USER_ID, "owner", 0), new UserInfo(CURRENT_USER_MANAGED_PROFILE_USER_ID, "managed profile", 0)); - private static final long SUPPORTED_FEATURES_ALL = Long.MAX_VALUE; + private static final BitSet SUPPORTED_FEATURES_ALL = new BitSet(); + private final String mGeneratedString256 = "a".repeat(256); private MockitoSession mSession; @@ -95,6 +99,7 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { .startMocking(); when(WifiInjector.getInstance()).thenReturn(mWifiInjector); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); + SUPPORTED_FEATURES_ALL.set(0, 63); // mark all features as supported } @After @@ -1498,7 +1503,8 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { */ @Test public void testValidateSecurityTypeDppAkm() { - long supportedFeatures = SUPPORTED_FEATURES_ALL & ~WifiManager.WIFI_FEATURE_DPP_AKM; + BitSet supportedFeatures = SUPPORTED_FEATURES_ALL; + supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP_AKM, false); WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); config.setSecurityParams(WifiInfo.SECURITY_TYPE_DPP); @@ -1507,7 +1513,7 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { assertFalse(WifiConfigurationUtil.validate(config, supportedFeatures, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)); - supportedFeatures = WifiManager.WIFI_FEATURE_DPP_AKM; + supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP_AKM, true); assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures, WifiConfigurationUtil.VALIDATE_FOR_ADD)); assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures, @@ -1606,4 +1612,76 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { assertTrue(WifiConfigurationUtil.isConfigLinkable(saeConfig)); assertFalse(WifiConfigurationUtil.isConfigLinkable(saeDisabledConfig)); } + + @Test + public void testWepKeyOnNonWepConfig() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + pskConfig.wepKeys = new String[4]; + pskConfig.wepKeys[0] = mGeneratedString256; + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + + @Test + public void testInvalidFqdnAndFriendlyName() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + + pskConfig.FQDN = mGeneratedString256; + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + + pskConfig.FQDN = null; + pskConfig.providerFriendlyName = mGeneratedString256; + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + + @Test + public void testInvalidDhcpAndGtw() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + pskConfig.dhcpServer = TEST_BSSID; + pskConfig.defaultGwMacAddress = TEST_BSSID; + assertTrue(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + pskConfig.dhcpServer = mGeneratedString256; + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + pskConfig.dhcpServer = TEST_BSSID; + pskConfig.defaultGwMacAddress = mGeneratedString256; + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + + @Test + public void testInvalidSecurityParameter() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + List<SecurityParams> securityParamsList = new ArrayList<>(); + securityParamsList.add(SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + securityParamsList.add(SecurityParams.createSecurityParamsBySecurityType( + WifiConfiguration.SECURITY_TYPE_PSK)); + + pskConfig.setSecurityParams(securityParamsList); + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + + @Test + public void testInvalidUserConnectChoice() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + String generatedString513 = "a".repeat(513); + pskConfig.getNetworkSelectionStatus().setConnectChoice(generatedString513); + + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } + + @Test + public void testInvalidDppConfig() { + WifiConfiguration pskConfig = WifiConfigurationTestUtil.createPskNetwork(); + String generatedString = "a".repeat(MAX_URL_BYTES + 1); + pskConfig.setDppConfigurator(generatedString.getBytes(StandardCharsets.UTF_8)); + assertFalse(WifiConfigurationUtil.validate(pskConfig, SUPPORTED_FEATURES_ALL, + WifiConfigurationUtil.VALIDATE_FOR_ADD)); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java index bbe9cf7ea8..f78f6ec4c9 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityHelperTest.java @@ -18,6 +18,8 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -32,6 +34,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.BitSet; /** * Unit tests for {@link com.android.server.wifi.WifiConnectivityHelper}. @@ -68,7 +71,8 @@ public class WifiConnectivityHelperTest extends WifiBaseTest { when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); // Return firmware roaming feature as supported by default. - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_CONTROL_ROAMING); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_CONTROL_ROAMING)); WifiNative.RoamingCapabilities roamCap = new WifiNative.RoamingCapabilities(); roamCap.maxBlocklistSize = MAX_BSSID_BLOCKLIST_SIZE; @@ -119,7 +123,9 @@ public class WifiConnectivityHelperTest extends WifiBaseTest { */ @Test public void returnFirmwareRoamingNotSupported() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_CONTROL_ROAMING); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(WIFI_FEATURE_CONTROL_ROAMING, false); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); assertTrue(mWifiConnectivityHelper.getFirmwareRoamingInfo()); assertFalse(mWifiConnectivityHelper.isFirmwareRoamingSupported()); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java index e5ddabb0e1..05464fd237 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -179,6 +179,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mPrimaryClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY); when(mPrimaryClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); + when(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(anyInt(), anyBoolean())) + .thenReturn(true); doAnswer(new AnswerWithArguments() { public void answer(ExternalClientModeManagerRequestListener listener, WorkSource requestorWs, String ssid, String bssid) { @@ -267,6 +269,10 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { resources.setInteger(R.integer.config_wifiPnoScanIterations, EXPECTED_PNO_ITERATIONS); resources.setInteger(R.integer.config_wifiPnoScanIntervalMultiplier, EXPECTED_PNO_MULTIPLIER); + resources.setIntArray(R.array.config_wifiDelayedSelectionCarrierIds, + DELAYED_SELECTION_CARRIER_IDS); + resources.setInteger(R.integer.config_wifiDelayedCarrierSelectionTimeMs, + DELAYED_CARRIER_SELECTION_TIME_MS); } /** @@ -350,6 +356,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Captor ArgumentCaptor<MultiInternetManager.ConnectionStatusListener> mMultiInternetConnectionStatusListenerCaptor; @Captor ArgumentCaptor<WifiDialogManager.SimpleDialogCallback> mSimpleDialogCallbackCaptor; + @Captor ArgumentCaptor<WifiScannerInternal.ScanListener> mAllSingleScanListenerCaptor; private MockitoSession mSession; private MockResources mResources; @@ -408,6 +415,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { private static final int EXPECTED_PNO_MULTIPLIER = 4; private static final int TEST_FREQUENCY_2G = 2412; private static final int TEST_FREQUENCY_5G = 5262; + private static final int[] DELAYED_SELECTION_CARRIER_IDS = new int[]{123}; + private static final int DELAYED_CARRIER_SELECTION_TIME_MS = 100_000; /** * A test Handler that stores one single incoming Message with delayed time internally, to be @@ -477,10 +486,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } void mockWifiScanner() { - ArgumentCaptor<WifiScannerInternal.ScanListener> allSingleScanListenerCaptor = - ArgumentCaptor.forClass(WifiScannerInternal.ScanListener.class); - - doNothing().when(mWifiScanner).registerScanListener(allSingleScanListenerCaptor.capture()); + doNothing().when(mWifiScanner).registerScanListener(mAllSingleScanListenerCaptor.capture()); ScanData[] scanDatas = new ScanData[1]; scanDatas[0] = mScanData; @@ -493,11 +499,11 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // same as onResult for single scans). if (mScanData != null && mScanData.getResults() != null) { for (int i = 0; i < mScanData.getResults().length; i++) { - allSingleScanListenerCaptor.getValue().getWifiScannerListener() + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener() .onFullResult(mScanData.getResults()[i]); } } - allSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults( + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults( scanDatas); }}).when(mWifiScanner).startScan(anyObject(), anyObject()); @@ -579,7 +585,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mCandidateList = new ArrayList<WifiCandidates.Candidate>(); mCandidateList.add(mCandidate1); when(ns.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(mCandidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(mCandidateList); when(ns.selectNetwork(any())) .then(new AnswerWithArguments() { public WifiConfiguration answer(List<WifiCandidates.Candidate> candidateList) { @@ -752,6 +758,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { assertEquals(WifiConnectivityManager.WIFI_STATE_DISCONNECTED, mWifiConnectivityManager.getWifiState()); mLooper.dispatchAll(); + verify(mWifiConfigManager).considerStopRestrictingAutoJoinToSubscriptionId(); verify(mPrimaryClientModeManager).startConnectToNetwork( CANDIDATE_NETWORK_ID, Process.WIFI_UID, "any"); verify(mPrimaryClientModeManager).enableRoaming(true); @@ -1406,7 +1413,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mCandidateList.add(mCandidate3); } when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(mCandidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(mCandidateList); doAnswer(new AnswerWithArguments() { public void answer(ExternalClientModeManagerRequestListener listener, @@ -2272,6 +2279,131 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } } + private void setAllScanCandidatesToDelayedCarrierCandidates() { + WifiConfiguration delayedCarrierSelectionConfig = + getTestWifiConfig(CANDIDATE_NETWORK_ID, "DelayedSelectionCarrier"); + delayedCarrierSelectionConfig.carrierId = DELAYED_SELECTION_CARRIER_IDS[0]; + when(mWifiConfigManager.getConfiguredNetwork(anyInt())) + .thenReturn(delayedCarrierSelectionConfig); + } + + /** + * Verify that candidates with a carrier ID in the delayed selection list are only considered + * for network selection after the specified delay. + */ + @Test + public void testDelayedCarrierCandidateSelection() { + ScanData[] scanDatas = new ScanData[]{mScanData}; + setAllScanCandidatesToDelayedCarrierCandidates(); + + // Produce results for the initial scan. Expect no connection, + // since this is the first time we're seeing the carrier network. + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Complete an additional scan before the delay period has ended. Expect no connection. + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS - 1000L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Complete a scan after the delay period has ended. Expect a connection. + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS + 1000L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + } + + /** + * Verify that a partial scan containing no results does not affect the delayed carrier + * selection cache. Partial scans may be running on channels where carrier networks + * are not operating. + */ + @Test + public void testDelayedCarrierSelectionEmptyPartialScan() { + ScanData[] scanDatas = new ScanData[]{mScanData}; + setAllScanCandidatesToDelayedCarrierCandidates(); + + // Issue a full scan to add the carrier candidate to the cache. + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + when(mScanData.getScannedBandsInternal()).thenReturn(WifiScanner.WIFI_BAND_ALL); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Issue a partial scan that does not locate any candidates. This should not affect + // the cache populated by the full scan. + when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(null); + when(mScanData.getScannedBandsInternal()).thenReturn(WifiScanner.WIFI_BAND_6_GHZ); + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS - 1000L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager, never()).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + + // Issue a full scan after the delay period has passed. Since the cache was not modified by + // the partial scan, the delayed carrier candidate should still be in the timestamp cache. + when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(Arrays.asList( + mCandidate1)); + when(mScanData.getScannedBandsInternal()).thenReturn(WifiScanner.WIFI_BAND_ALL); + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS + 1000L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + verify(mPrimaryClientModeManager).startConnectToNetwork( + CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID); + } + + /** + * Verify that a partial scan is scheduled when a full scan locates delayed carrier + * selection candidates. + */ + @Test + public void testDelayedCarrierSelectionSchedulePartialScan() { + ScanData[] scanDatas = new ScanData[]{mScanData}; + setAllScanCandidatesToDelayedCarrierCandidates(); + + // Initial full scan with a delayed carrier candidate should schedule a partial scan. + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + + // Move time forward and verify that the delayed partial scan is started. + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS + 1L); + mLooper.dispatchAll(); + verify(mWifiScanner).startScan( + (ScanSettings) argThat(new WifiPartialScanSettingMatcher()), any()); + } + + /** + * Verify that if a delayed carrier partial scan is cancelled, no scan is triggered + * at the end of the delay period. + */ + @Test + public void testDelayedCarrierSelectionCancelPartialScan() { + ScanData[] scanDatas = new ScanData[]{mScanData}; + setAllScanCandidatesToDelayedCarrierCandidates(); + + // Initial full scan with a delayed carrier candidate should schedule a partial scan. + when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + mAllSingleScanListenerCaptor.getValue().getWifiScannerListener().onResults(scanDatas); + + // Turn off Wifi to cancel the partial scan. + setWifiEnabled(false); + + // Move time forward and verify that a delayed partial scan is not started. + when(mClock.getElapsedSinceBootMillis()) + .thenReturn(DELAYED_CARRIER_SELECTION_TIME_MS + 1L); + mLooper.dispatchAll(); + verify(mWifiScanner, never()).startScan( + (ScanSettings) argThat(new WifiPartialScanSettingMatcher()), any()); + } + /** * Verify that when there are we obtain more than one valid candidates from scan results and * network connection fails, connection is immediately retried on the remaining candidates. @@ -2288,7 +2420,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2330,6 +2462,41 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { } @Test + public void testNoRetryConnectionOnNetworkNotFoundFailure() { + // Setup WifiNetworkSelector to return 2 valid candidates from scan results + MacAddress macAddress = MacAddress.fromString(CANDIDATE_BSSID_2); + WifiCandidates.Key key = new WifiCandidates.Key(mock(ScanResultMatchInfo.class), + macAddress, 0, WifiConfiguration.SECURITY_TYPE_OPEN); + WifiCandidates.Candidate otherCandidate = mock(WifiCandidates.Candidate.class); + when(otherCandidate.getKey()).thenReturn(key); + List<WifiCandidates.Candidate> candidateList = new ArrayList<>(); + candidateList.add(mCandidate1); + candidateList.add(otherCandidate); + when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); + + // Set WiFi to disconnected state to trigger scan + mWifiConnectivityManager.handleConnectionStateChanged( + mPrimaryClientModeManager, + WifiConnectivityManager.WIFI_STATE_DISCONNECTED); + mLooper.dispatchAll(); + // Verify a connection starting + verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>) + argThat(new WifiCandidatesListSizeMatcher(2))); + verify(mPrimaryClientModeManager).startConnectToNetwork(anyInt(), anyInt(), any()); + + // Simulate the connection failing due to FAILURE_NO_RESPONSE + WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork(CANDIDATE_SSID); + mWifiConnectivityManager.handleConnectionAttemptEnded( + mPrimaryClientModeManager, + WifiMetrics.ConnectionEvent.FAILURE_NO_RESPONSE, + WifiMetricsProto.ConnectionEvent.FAILURE_REASON_UNKNOWN, CANDIDATE_BSSID, + config); + // Verify there is no retry + verify(mPrimaryClientModeManager).startConnectToNetwork(anyInt(), anyInt(), any()); + } + + @Test public void testRetryConnectionEapFailureIgnoreSameNetwork() { // Setup WifiNetworkSelector to return 2 valid candidates with the same // ScanResultMatchInfo so they are the same network, but different BSSID. @@ -2347,7 +2514,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(candidate1); candidateList.add(candidate2); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2382,7 +2549,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2424,7 +2591,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2479,7 +2646,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2519,7 +2686,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2563,7 +2730,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2606,7 +2773,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { candidateList.add(mCandidate1); candidateList.add(otherCandidate); when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(candidateList); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(candidateList); // Set WiFi to disconnected state to trigger scan mWifiConnectivityManager.handleConnectionStateChanged( @@ -2729,7 +2896,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { public void wifiDisconnected_noCandidatesInScan_openNetworkNotifierScanResultsHandled() { // no connection candidates from scan. when(mWifiNS.getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), - anyBoolean(), any(), anyBoolean())).thenReturn(null); + anyBoolean(), any(), anyBoolean(), anyInt())).thenReturn(null); List<ScanDetail> expectedOpenNetworks = new ArrayList<>(); expectedOpenNetworks.add( @@ -2857,6 +3024,26 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { verify(mOpenNetworkNotifier).handleScreenStateChanged(true); } + @Test + public void testInitialFastScanAfterStartup() { + // Enable the fast initial scan feature + mResources.setBoolean(R.bool.config_wifiEnablePartialInitialScan, true); + // return 2 available frequencies + when(mWifiScoreCard.lookupNetwork(anyString())).thenReturn(mPerNetwork); + when(mPerNetwork.getFrequencies(anyLong())).thenReturn(new ArrayList<>( + Arrays.asList(TEST_FREQUENCY_1, TEST_FREQUENCY_2))); + + // Simulate wifi toggle + setScreenState(true); + setWifiEnabled(false); + setWifiEnabled(true); + + // verify initial fast scan is triggered + assertEquals(WifiConnectivityManager.INITIAL_SCAN_STATE_AWAITING_RESPONSE, + mWifiConnectivityManager.getInitialScanState()); + verify(mWifiMetrics).incrementInitialPartialScanCount(); + } + /** * Verify that the initial fast scan schedules the scan timer just like regular scans. */ @@ -4732,6 +4919,30 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { assertFalse(mWifiConnectivityManager.getAutoJoinEnabledExternal()); } + /** + * Verify if setAutojoinDisallowedSecurityTypes method is working correctly. + * Also verify getAutojoinDisallowedSecurityTypes method is working correctly. + */ + @Test + public void testSetAndGetAutojoinDisallowedSecurityTypes() { + // test default value of auto-join restriction secirity types (NONE) + assertEquals(0/*restrict none by default*/, + mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes()); + + // test setting auto-join restriction on secirity types OPEN, WEP, and OWE + int restrictOpenWepOwe = (0x1 << WifiInfo.SECURITY_TYPE_OPEN) + | (0x1 << WifiInfo.SECURITY_TYPE_WEP) + | (0x1 << WifiInfo.SECURITY_TYPE_OWE); + mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(restrictOpenWepOwe); + assertEquals(restrictOpenWepOwe, mWifiConnectivityManager + .getAutojoinDisallowedSecurityTypes()); + + // test resetting auto-join restriction on all secirity types + mWifiConnectivityManager.setAutojoinDisallowedSecurityTypes(0/*restrict none*/); + assertEquals(0/*restrict none*/, mWifiConnectivityManager + .getAutojoinDisallowedSecurityTypes()); + } + /* * Firmware supports controlled roaming. * Connect to a network which doesn't have a config specified BSSID. @@ -5071,7 +5282,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { * on a DBS supported device. * * Expected behavior: WifiConnectivityManager invokes - * {@link WifiNetworkSelector#getCandidatesFromScan(List, Set, List, boolean, boolean, Set, boolean)} + * {@link WifiNetworkSelector#getCandidatesFromScan(List, Set, List, boolean, boolean, Set, boolean, int)} * boolean, boolean, boolean)} after filtering out the scan results obtained via DBS scan. */ @Test @@ -5092,12 +5303,14 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { List<WifiNetworkSelector.ClientModeManagerState> cmmStates, boolean untrustedNetworkAllowed, boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed, - Set<Integer> restrictedNetworkAllowedUids, boolean multiInternetNetworkAllowed) + Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck, + int autojoinRestrictionSecurityTypes) throws Exception { capturedScanDetails.addAll(scanDetails); return null; }}).when(mWifiNS).getCandidatesFromScan( - any(), any(), any(), anyBoolean(), eq(true), eq(false), any(), eq(false)); + any(), any(), any(), anyBoolean(), eq(true), eq(false), any(), eq(false), + anyInt()); mWifiConnectivityManager.setTrustedConnectionAllowed(true); mWifiConnectivityManager.setOemPaidConnectionAllowed(true, new WorkSource()); @@ -5151,12 +5364,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { List<WifiNetworkSelector.ClientModeManagerState> cmmStates, boolean untrustedNetworkAllowed, boolean oemPaidNetworkAllowed, boolean oemPrivateNetworkAllowed, - Set<Integer> restrictedNetworkAllowedUids, boolean multiInternetNetworkAllowed) + Set<Integer> restrictedNetworkAllowedUids, boolean skipSufficiencyCheck, + int autojoinRestrictionSecurityTypes) throws Exception { capturedScanDetails.addAll(scanDetails); return null; }}).when(mWifiNS).getCandidatesFromScan( - any(), any(), any(), anyBoolean(), eq(false), eq(true), any(), eq(false)); + any(), any(), any(), anyBoolean(), eq(false), eq(true), any(), eq(false), anyInt()); mWifiConnectivityManager.setTrustedConnectionAllowed(true); mWifiConnectivityManager.setOemPrivateConnectionAllowed(true, new WorkSource()); @@ -5737,11 +5951,14 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { WifiConfiguration network3 = WifiConfigurationTestUtil.createOpenHiddenNetwork(); WifiConfiguration network4 = WifiConfigurationTestUtil.createEapNetwork( WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); + WifiConfiguration network5 = WifiConfigurationTestUtil.createPskNetwork(); + network5.subscriptionId = 2; network4.carrierId = 123; // Assign a valid carrier ID network1.getNetworkSelectionStatus().setHasEverConnected(true); network2.getNetworkSelectionStatus().setHasEverConnected(true); network3.getNetworkSelectionStatus().setHasEverConnected(true); network4.getNetworkSelectionStatus().setHasEverConnected(true); + network5.getNetworkSelectionStatus().setHasEverConnected(true); when(mWifiCarrierInfoManager.isSimReady(anyInt())).thenReturn(true); List<WifiConfiguration> networkList = new ArrayList<>(); @@ -5749,6 +5966,8 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { networkList.add(network2); networkList.add(network3); networkList.add(network4); + networkList.add(network5); + mLruConnectionTracker.addNetwork(network5); mLruConnectionTracker.addNetwork(network4); mLruConnectionTracker.addNetwork(network3); mLruConnectionTracker.addNetwork(network2); @@ -5758,12 +5977,13 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { List<WifiScanner.PnoSettings.PnoNetwork> pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); verify(mWifiNetworkSuggestionsManager).getAllScanOptimizationSuggestionNetworks(); - assertEquals(5, pnoNetworks.size()); + assertEquals(6, pnoNetworks.size()); assertEquals(network1.SSID, pnoNetworks.get(0).ssid); assertEquals(UNTRANSLATED_HEX_SSID, pnoNetworks.get(1).ssid); // Possible untranslated SSID assertEquals(network2.SSID, pnoNetworks.get(2).ssid); assertEquals(network3.SSID, pnoNetworks.get(3).ssid); assertEquals(network4.SSID, pnoNetworks.get(4).ssid); + assertEquals(network5.SSID, pnoNetworks.get(5).ssid); // Now permanently disable |network3|. This should remove network 3 from the list. network3.getNetworkSelectionStatus().setNetworkSelectionStatus( @@ -5773,7 +5993,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // Retrieve the Pno network list & verify. pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(3, pnoNetworks.size()); + assertEquals(4, pnoNetworks.size()); assertEquals(network1.SSID, pnoNetworks.get(0).ssid); assertEquals(UNTRANSLATED_HEX_SSID, pnoNetworks.get(1).ssid); // Possible untranslated SSID assertEquals(network2.SSID, pnoNetworks.get(2).ssid); @@ -5782,7 +6002,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { network1.allowAutojoin = false; // Retrieve the Pno network list & verify. pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); - assertEquals(2, pnoNetworks.size()); + assertEquals(3, pnoNetworks.size()); assertEquals(network2.SSID, pnoNetworks.get(0).ssid); assertEquals(UNTRANSLATED_HEX_SSID, pnoNetworks.get(1).ssid); // Possible untranslated SSID @@ -5790,6 +6010,14 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { // from the list. when(mWifiConfigManager.isNetworkTemporarilyDisabledByUser(network2.SSID)).thenReturn(true); pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); + assertEquals(2, pnoNetworks.size()); + assertEquals(network5.SSID, pnoNetworks.get(0).ssid); + assertEquals(UNTRANSLATED_HEX_SSID, pnoNetworks.get(1).ssid); // Possible untranslated SSID + + // Set carrier offload to disabled. Should remove the last network + when(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(anyInt(), anyBoolean())) + .thenReturn(false); + pnoNetworks = mWifiConnectivityManager.retrievePnoNetworkList(); assertEquals(0, pnoNetworks.size()); } @@ -6109,7 +6337,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { ROLE_CLIENT_SECONDARY_LONG_LIVED)); verify(mWifiNS).getCandidatesFromScan(any(), any(), eq(expectedCmmStates), anyBoolean(), anyBoolean(), anyBoolean(), any(), - eq(false)); + eq(false), anyInt()); } @Test @@ -6141,7 +6369,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mWifiNS).getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), any(), - eq(true)); + eq(true), anyInt()); } @Test @@ -6174,7 +6402,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mWifiNS).getCandidatesFromScan(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean(), any(), - eq(true)); + eq(true), anyInt()); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java index dacf2cc178..5941feeafd 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiCountryCodeTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; +import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_DEFAULT_COUNTRY_CODE; @@ -32,6 +33,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -40,6 +42,7 @@ import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.content.Context; import android.content.pm.PackageManager; import android.net.wifi.ScanResult; +import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.telephony.TelephonyManager; @@ -90,8 +93,9 @@ public class WifiCountryCodeTest extends WifiBaseTest { private boolean mDriverSupportedNl80211RegChangedEvent = false; private boolean mForcedSoftApRestateWhenCountryCodeChanged = false; private boolean mCallingSupported; - @Mock Context mContext; - MockResources mResources = new MockResources(); + @Mock + WifiContext mContext; + private MockResourceCache mResourceCache; @Mock TelephonyManager mTelephonyManager; @Mock PackageManager mPackageManager; @Mock ActiveModeWarden mActiveModeWarden; @@ -150,6 +154,8 @@ public class WifiCountryCodeTest extends WifiBaseTest { when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) .thenReturn(mTelephonyManager); when(mContext.getPackageManager()).thenReturn(mPackageManager); + mResourceCache = new MockResourceCache(mContext); + when(mContext.getResourceCache()).thenReturn(mResourceCache); setCallingSupported(true); @@ -172,16 +178,17 @@ public class WifiCountryCodeTest extends WifiBaseTest { } private void createWifiCountryCode() { - mResources.setBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss, + mResourceCache.setBoolean(R.bool.config_wifi_revert_country_code_on_cellular_loss, mRevertCountryCodeOnCellularLoss); - mResources.setBoolean(R.bool.config_wifiStaDynamicCountryCodeUpdateSupported, + mResourceCache.setBoolean(R.bool.config_wifiStaDynamicCountryCodeUpdateSupported, mStaDynamicCountryCodeUpdateSupported); - mResources.setBoolean(R.bool.config_wifiDriverSupportedNl80211RegChangedEvent, + mResourceCache.setBoolean(R.bool.config_wifiDriverSupportedNl80211RegChangedEvent, mDriverSupportedNl80211RegChangedEvent); - mResources.setBoolean(R.bool.config_wifiForcedSoftApRestartWhenCountryCodeChanged, + mResourceCache.setBoolean(R.bool.config_wifiForcedSoftApRestartWhenCountryCodeChanged, mForcedSoftApRestateWhenCountryCodeChanged); - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, false); - mResources.setString(R.string.config_wifiDriverWorldModeCountryCode, mWorldModeCountryCode); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, false); + mResourceCache.setString(R.string.config_wifiDriverWorldModeCountryCode, + mWorldModeCountryCode); doAnswer((invocation) -> { if (SdkLevel.isAtLeastS()) { mChangeListenerCaptor.getValue() @@ -194,7 +201,6 @@ public class WifiCountryCodeTest extends WifiBaseTest { return true; }).when(mClientModeManager).setCountryCode( mSetCountryCodeCaptor.capture()); - when(mContext.getResources()).thenReturn(mResources); mWifiCountryCode = new WifiCountryCode( mContext, mActiveModeWarden, @@ -284,7 +290,6 @@ public class WifiCountryCodeTest extends WifiBaseTest { assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); } - /** * Test if we receive country code from Telephony after supplicant stop. * @throws Exception @@ -720,18 +725,18 @@ public class WifiCountryCodeTest extends WifiBaseTest { @Test public void testUpdateountryCodeGenericDisabled() { - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, false); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, false); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); } @Test public void testUpdateountryCodeGenericEnabled() { - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(TEST_COUNTRY_CODE, mWifiCountryCode.getCountryCode()); - mResources.setBoolean(R.bool.config_wifiDriverSupportedNl80211RegChangedEvent, false); + mResourceCache.setBoolean(R.bool.config_wifiDriverSupportedNl80211RegChangedEvent, false); mChangeListenerCaptor.getValue().onSetCountryCodeSucceeded(TEST_COUNTRY_CODE_2); mScanDetails = setupScanDetails(TEST_COUNTRY_CODE_2); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); @@ -741,7 +746,7 @@ public class WifiCountryCodeTest extends WifiBaseTest { @Test public void testUpdateCountryCodeGenericWithTelephonyCountryCode() { when(mTelephonyManager.getNetworkCountryIso()).thenReturn(TEST_COUNTRY_CODE_2); - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(TEST_COUNTRY_CODE_2, mWifiCountryCode.getCountryCode()); } @@ -749,14 +754,14 @@ public class WifiCountryCodeTest extends WifiBaseTest { @Test public void testUpdateountryCodeGenericMismatchScanResult() { when(mNetworkDetail2.getCountryCode()).thenReturn(TEST_COUNTRY_CODE_2); - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); } @Test public void testUpdateountryCodeGenericOneGoodScanResult() { - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); mScanResult2.level = WifiCountryCode.MIN_SCAN_RSSI_DBM - 1; mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); @@ -764,11 +769,63 @@ public class WifiCountryCodeTest extends WifiBaseTest { @Test public void testUpdateountryCodeGenericTwoGoodScanResultUs() { - mResources.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); + mResourceCache.setBoolean(R.bool.config_wifiUpdateCountryCodeFromScanResultGeneric, true); mScanDetails = setupScanDetails("US"); mDefaultCountryCode = "CA"; when(mSettingsConfigStore.get(WIFI_DEFAULT_COUNTRY_CODE)).thenReturn(mDefaultCountryCode); mWifiCountryCode.updateCountryCodeFromScanResults(mScanDetails); assertEquals(mDefaultCountryCode, mWifiCountryCode.getCountryCode()); } + + /** + * Test if we receive country code from Telephony after supplicant stop. + */ + @Test + public void testCountryCodeDoesntChangeWhenIfClientModeChanged() { + // Start in scan only mode. + mModeChangeCallbackCaptor.getValue().onActiveModeManagerAdded(mClientModeManager); + assertEquals(mDefaultCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); + // Supplicant starts. + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); + mModeChangeCallbackCaptor.getValue().onActiveModeManagerRoleChanged(mClientModeManager); + assertEquals(mDefaultCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); + verify(mClientModeManager).setCountryCode(mDefaultCountryCode); + assertEquals(mDefaultCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); + + reset(mClientModeManager); + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); + // Wifi is connected and disconnected but there is no CC changed again + mClientModeImplListenerCaptor.getValue().onConnectionStart(mClientModeManager); + mClientModeImplListenerCaptor.getValue().onConnectionEnd(mClientModeManager); + verify(mClientModeManager, never()).setCountryCode(anyString()); + + when(mClientModeManager.setCountryCode(anyString())).thenReturn(false); + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); + // Telephony country code arrives but set country code fail due to mode is being + // changed to scan mode. + mModeChangeCallbackCaptor.getValue().onActiveModeManagerRoleChanged(mClientModeManager); + mWifiCountryCode.setTelephonyCountryCodeAndUpdate(mTelephonyCountryCode); + verify(mClientModeManager).setCountryCode(mTelephonyCountryCode); + assertEquals(mDefaultCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); + + reset(mClientModeManager); + when(mClientModeManager.setCountryCode(anyString())).thenReturn(true); + when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); + doAnswer((invocation) -> { + if (SdkLevel.isAtLeastS()) { + mChangeListenerCaptor.getValue() + .onSetCountryCodeSucceeded(mSetCountryCodeCaptor.getValue()); + } + if (mDriverSupportedNl80211RegChangedEvent) { + mChangeListenerCaptor.getValue() + .onDriverCountryCodeChanged(mSetCountryCodeCaptor.getValue()); + } + return true; + }).when(mClientModeManager).setCountryCode( + mSetCountryCodeCaptor.capture()); + // Mode is added back, country code should update to telephony country code. + mModeChangeCallbackCaptor.getValue().onActiveModeManagerRoleChanged(mClientModeManager); + verify(mClientModeManager).setCountryCode(mTelephonyCountryCode); + assertEquals(mTelephonyCountryCode, mWifiCountryCode.getCurrentDriverCountryCode()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java index 61b6884dc5..592b16c420 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiDataStallTest.java @@ -288,6 +288,23 @@ public class WifiDataStallTest extends WifiBaseTest { WifiDataStall.CELLULAR_DATA_AVAILABLE); } + @Test + public void verifyGetThroughputPredictorSpeeds() throws Exception { + WifiDataStall.Speeds speeds; + + speeds = mWifiDataStall.getThrouhgputPredictorSpeeds(mWifiInfo, mCapabilities); + assertEquals(150_000, speeds.DownstreamKbps); + assertEquals(50_000, speeds.UpstreamKbps); + + speeds = mWifiDataStall.getThrouhgputPredictorSpeeds(null, mCapabilities); + assertEquals(WifiDataStall.INVALID_THROUGHPUT, speeds.DownstreamKbps); + assertEquals(WifiDataStall.INVALID_THROUGHPUT, speeds.UpstreamKbps); + + speeds = mWifiDataStall.getThrouhgputPredictorSpeeds(mWifiInfo, null); + assertEquals(WifiDataStall.INVALID_THROUGHPUT, speeds.DownstreamKbps); + assertEquals(WifiDataStall.INVALID_THROUGHPUT, speeds.UpstreamKbps); + } + /** * Verify throughput when Rx link speed is unavailable. * Also verify the logging of channel utilization and throughput. diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java index dab681fca6..0fefd7ab9e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiGlobalsTest.java @@ -47,6 +47,7 @@ public class WifiGlobalsTest extends WifiBaseTest { private WifiGlobals mWifiGlobals; private MockResources mResources; + private WifiResourceCache mWifiResourceCache; @Mock private WifiContext mContext; @@ -65,7 +66,8 @@ public class WifiGlobalsTest extends WifiBaseTest { new String[] {TEST_SSID}); mResources.setStringArray(R.array.config_wifiAfcServerUrlsForCountry, new String[] {}); when(mContext.getResources()).thenReturn(mResources); - when(mContext.getResourceCache()).thenReturn(new WifiResourceCache(mContext)); + mWifiResourceCache = new WifiResourceCache(mContext); + when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); mWifiGlobals = new WifiGlobals(mContext); } @@ -75,6 +77,7 @@ public class WifiGlobalsTest extends WifiBaseTest { public void testPollRssiIntervalIsSetCorrectly() throws Exception { assertEquals(3000, mWifiGlobals.getPollRssiIntervalMillis()); mResources.setInteger(R.integer.config_wifiPollRssiIntervalMilliseconds, 9000); + mWifiResourceCache.reset(); assertEquals(9000, new WifiGlobals(mContext).getPollRssiIntervalMillis()); } @@ -111,6 +114,7 @@ public class WifiGlobalsTest extends WifiBaseTest { assertFalse(mWifiGlobals.isWpa3SaeH2eSupported()); mResources.setBoolean(R.bool.config_wifiSaeH2eSupported, true); + mWifiResourceCache.reset(); mWifiGlobals = new WifiGlobals(mContext); assertTrue(mWifiGlobals.isWpa3SaeH2eSupported()); } @@ -169,18 +173,21 @@ public class WifiGlobalsTest extends WifiBaseTest { // Test config with too few items don't get added. mResources.setStringArray(R.array.config_wifiEapFailureConfig, new String[] {"1, 2, 3"}); + mWifiResourceCache.reset(); mWifiGlobals = new WifiGlobals(mContext); assertEquals(0, mWifiGlobals.getCarrierSpecificEapFailureConfigMapSize()); // Test config that fail to parse to int don't get added. mResources.setStringArray(R.array.config_wifiEapFailureConfig, new String[] {"1839, bad_config, 1, 1, 1440"}); + mWifiResourceCache.reset(); mWifiGlobals = new WifiGlobals(mContext); assertEquals(0, mWifiGlobals.getCarrierSpecificEapFailureConfigMapSize()); // Test correct config mResources.setStringArray(R.array.config_wifiEapFailureConfig, new String[] {"1839, 1031, 1, 1, 1440"}); + mWifiResourceCache.reset(); mWifiGlobals = new WifiGlobals(mContext); assertEquals(1, mWifiGlobals.getCarrierSpecificEapFailureConfigMapSize()); WifiBlocklistMonitor.CarrierSpecificEapFailureConfig config = @@ -242,8 +249,8 @@ public class WifiGlobalsTest extends WifiBaseTest { String afcServerUS3 = "https://www.android.com/"; mResources.setStringArray(R.array.config_wifiAfcServerUrlsForCountry, new String[] {"US," + afcServerUS1 + "," + afcServerUS2 + "," + afcServerUS3}); + mWifiResourceCache.reset(); mWifiGlobals = new WifiGlobals(mContext); - List<String> afcServersForUS = mWifiGlobals.getAfcServerUrlsForCountry("US"); assertEquals(3, afcServersForUS.size()); assertEquals(afcServerUS1, afcServersForUS.get(0)); @@ -281,7 +288,6 @@ public class WifiGlobalsTest extends WifiBaseTest { @Test public void testSetWepAllowedWhenWepIsNotDeprecated() { mResources.setBoolean(R.bool.config_wifiWepAllowedControlSupported, true); - mWifiGlobals = new WifiGlobals(mContext); assertTrue(mWifiGlobals.isWepSupported()); // Default is not allow assertFalse(mWifiGlobals.isWepAllowed()); @@ -296,7 +302,7 @@ public class WifiGlobalsTest extends WifiBaseTest { // Test WEP allowed control is NOT supported. mResources.setBoolean(R.bool.config_wifiWepAllowedControlSupported, false); - mWifiGlobals = new WifiGlobals(mContext); + mWifiResourceCache.reset(); // Default is not allow, but don't care it since control is not supported. assertFalse(mWifiGlobals.isWepAllowed()); // But we won't consider WEP is allowed since control is NOT supported. @@ -308,10 +314,9 @@ public class WifiGlobalsTest extends WifiBaseTest { @Test public void isSwPnoEnabled() { mResources.setBoolean(R.bool.config_wifiSwPnoEnabled, true); - mWifiGlobals = new WifiGlobals(mContext); assertTrue(mWifiGlobals.isSwPnoEnabled()); mResources.setBoolean(R.bool.config_wifiSwPnoEnabled, false); - mWifiGlobals = new WifiGlobals(mContext); + mWifiResourceCache.reset(); assertFalse(mWifiGlobals.isSwPnoEnabled()); } @@ -319,7 +324,6 @@ public class WifiGlobalsTest extends WifiBaseTest { public void testIsD2dSupportedWhenInfraStaDisabled() { mResources.setBoolean(R.bool.config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled, false); - mWifiGlobals = new WifiGlobals(mContext); mWifiGlobals.setD2dStaConcurrencySupported(true); assertFalse(mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()); mWifiGlobals.setD2dStaConcurrencySupported(false); @@ -327,7 +331,7 @@ public class WifiGlobalsTest extends WifiBaseTest { mResources.setBoolean(R.bool.config_wifiD2dAllowedControlSupportedWhenInfraStaDisabled, true); - mWifiGlobals = new WifiGlobals(mContext); + mWifiResourceCache.reset(); mWifiGlobals.setD2dStaConcurrencySupported(true); assertFalse(mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()); mWifiGlobals.setD2dStaConcurrencySupported(false); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java index 6af6d0c7bb..47065937db 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiLockManagerTest.java @@ -19,6 +19,7 @@ package com.android.server.wifi; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; @@ -69,6 +70,7 @@ import org.mockito.MockitoAnnotations; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Random; @@ -133,6 +135,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); + when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet()); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); when(mClientModeManager2.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); @@ -529,7 +532,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); } @@ -560,7 +563,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -702,7 +705,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -747,7 +750,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_MODE_FULL_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_MODE_FULL_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -1009,7 +1012,7 @@ public class WifiLockManagerTest extends WifiBaseTest { ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); when(mClientModeManager.getSupportedFeatures()) - .thenReturn(WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); @@ -1029,7 +1032,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_TX_POWER_LIMIT); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT)); acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); @@ -1049,7 +1052,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1088,7 +1091,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Fail the call to ClientModeManager when(mClientModeManager.setLowLatencyMode(true)).thenReturn(false); @@ -1118,7 +1121,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Succeed to setLowLatencyMode() when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1147,7 +1150,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1186,7 +1189,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1229,7 +1232,7 @@ public class WifiLockManagerTest extends WifiBaseTest { setScreenState(true); when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1272,7 +1275,7 @@ public class WifiLockManagerTest extends WifiBaseTest { setScreenState(true); when(mFrameworkFacade.isAppForeground(any(), anyInt())).thenReturn(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); // Make sure setLowLatencyMode()/setPowerSave() is successful @@ -1324,7 +1327,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK), anyBoolean())).thenReturn(true); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1359,7 +1362,7 @@ public class WifiLockManagerTest extends WifiBaseTest { anyBoolean())).thenReturn(true); setScreenState(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1400,7 +1403,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1446,7 +1449,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK), anyBoolean())).thenReturn(true); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1475,7 +1478,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK), anyBoolean())).thenReturn(true); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1508,7 +1511,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK), anyBoolean())).thenReturn(true); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1541,7 +1544,7 @@ public class WifiLockManagerTest extends WifiBaseTest { int expectedMode = WifiManager.WIFI_MODE_FULL_HIGH_PERF; when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1699,7 +1702,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -1752,7 +1755,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(anyInt())).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mWifiMetrics); @@ -1899,7 +1902,7 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mClientModeManager.setPowerSave(eq(ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK), anyBoolean())).thenReturn(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1945,12 +1948,13 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_LOW_LATENCY); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); inOrder.verify(testListener).onOwnershipChanged(eq(new int[]{DEFAULT_TEST_UID_1})); inOrder.verify(testListener).onActivatedStateChanged(true); + verify(mWifiMetrics).setLowLatencyState(eq(true)); inOrder.verify(testListener).onActiveUsersChanged(eq(new int[]{DEFAULT_TEST_UID_1})); // Acquire a second lock and check the owners & active users changed. @@ -2032,8 +2036,13 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeManager.getSupportedFeatures()).thenReturn( - ~WifiManager.WIFI_FEATURE_LOW_LATENCY); + + // Disable low latency, but support other arbitrary features + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(WifiManager.WIFI_FEATURE_LOW_LATENCY, false); + supportedFeatures.set(WifiManager.WIFI_FEATURE_DPP, true); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); + acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); inOrder.verify(testListener).onOwnershipChanged(eq(new int[]{DEFAULT_TEST_UID_1})); @@ -2057,8 +2066,8 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_LOW_LATENCY); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); // Acquire the lock should report @@ -2103,8 +2112,8 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_LOW_LATENCY); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); // Acquire the lock should report @@ -2151,8 +2160,8 @@ public class WifiLockManagerTest extends WifiBaseTest { when(mActivityManager.getUidImportance(DEFAULT_TEST_UID_1)).thenReturn( ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); - when(mClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_LOW_LATENCY); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); // Acquire --> reportFullWifiLockAcquiredFromSource diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index 3c4f6c4db1..5f714e191b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java @@ -36,11 +36,37 @@ import static com.android.server.wifi.WifiMetricsTestUtil.buildInt32Count; import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureReasonCount; import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeFailureStaEvent; import static com.android.server.wifi.WifiMetricsTestUtil.buildLinkProbeSuccessStaEvent; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_SIM_INSERTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_SCORING_DISABLED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_OFF; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_UNAVAILABLE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_OTHERS; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONFIG_SAVED; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNKNOWN; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE; import static com.android.server.wifi.proto.nano.WifiMetricsProto.StaEvent.TYPE_LINK_PROBE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__TRUE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__FALSE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FIRMWARE_ALERT; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_IP_REACHABILITY_LOST; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_CONNECTED; +import static com.android.server.wifi.proto.WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -60,12 +86,16 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import static java.lang.StrictMath.toIntExact; import android.app.ActivityManager; import android.content.Context; +import android.net.ConnectivityManager; import android.net.MacAddress; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.wifi.EAPConstants; import android.net.wifi.IOnWifiUsabilityStatsListener; import android.net.wifi.MloLink; @@ -138,6 +168,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry; import com.android.server.wifi.rtt.RttMetrics; import com.android.server.wifi.util.InformationElementUtil; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import org.junit.After; @@ -186,6 +217,8 @@ public class WifiMetricsTest extends WifiBaseTest { private static final String MLO_LINK_STA_MAC_ADDRESS = "12:34:56:78:9a:bc"; private static final String MLO_LINK_AP_MAC_ADDRESS = "bc:9a:78:56:34:12"; private static final int TEST_CHANNEL = 36; + private static final int POLLING_INTERVAL_DEFAULT = 3000; + private static final int POLLING_INTERVAL_NOT_DEFAULT = 6000; private MockitoSession mSession; @Mock Context mContext; @@ -213,6 +246,12 @@ public class WifiMetricsTest extends WifiBaseTest { @Mock WifiMonitor mWifiMonitor; @Mock ActiveModeWarden mActiveModeWarden; @Mock WifiDeviceStateChangeManager mWifiDeviceStateChangeManager; + @Mock ConnectivityManager mConnectivityManager; + @Mock NetworkCapabilities mNetworkCapabilities; + @Mock Network mNetwork; + @Mock WifiInfo mWifiInfo; + @Mock WifiNative.ConnectionCapabilities mCapabilities; + @Mock WifiGlobals mWifiGlobals; @Captor ArgumentCaptor<ActiveModeWarden.ModeChangeCallback> mModeChangeCallbackArgumentCaptor; @Captor ArgumentCaptor<Handler> mHandlerCaptor; @Captor @@ -227,6 +266,13 @@ public class WifiMetricsTest extends WifiBaseTest { mTestLooper = new TestLooper(); mResources = new MockResources(); when(mContext.getResources()).thenReturn(mResources); + when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager); + when(mConnectivityManager.getActiveNetwork()).thenReturn(mNetwork); + when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities); + when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) + .thenReturn(true); + when(mNetworkCapabilities.getLinkDownstreamBandwidthKbps()).thenReturn(-1); + when(mNetworkCapabilities.getLinkUpstreamBandwidthKbps()).thenReturn(-1); mWifiMetrics = new WifiMetrics( mContext, @@ -239,7 +285,8 @@ public class WifiMetricsTest extends WifiBaseTest { mWifiP2pMetrics, mDppMetrics, mWifiMonitor, - mWifiDeviceStateChangeManager); + mWifiDeviceStateChangeManager, + mWifiGlobals); mWifiMetrics.setWifiConfigManager(mWcm); mWifiMetrics.setWifiBlocklistMonitor(mWifiBlocklistMonitor); mWifiMetrics.setPasspointManager(mPpm); @@ -274,7 +321,15 @@ public class WifiMetricsTest extends WifiBaseTest { mSession = ExtendedMockito.mockitoSession() .strictness(Strictness.LENIENT) .mockStatic(WifiStatsLog.class) + .mockStatic(Flags.class, withSettings().lenient()) .startMocking(); + + when(mWifiInfo.getLinkSpeed()).thenReturn(10); + when(mWifiInfo.getRxLinkSpeedMbps()).thenReturn(10); + when(mWifiInfo.getFrequency()).thenReturn(5850); + when(mWifiInfo.getBSSID()).thenReturn("5G_WiFi"); + when(mWifiInfo.getRssi()).thenReturn(-55); + } @After @@ -4456,16 +4511,16 @@ public class WifiMetricsTest extends WifiBaseTest { public void testWifiUsabilityStatsBufferSizeIsCapped() throws Exception { // simulate adding LABEL_GOOD WifiUsabilityStats 1 time over the max limit WifiLinkLayerStats stats = new WifiLinkLayerStats(); - for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_LIST_SIZE_PER_TYPE + 1; j++) { + for (int j = 0; j < WifiMetrics.MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE + 1; j++) { stats = addGoodWifiUsabilityStats(stats); stats = addBadWifiUsabilityStats(stats); stats.timeStampInMs += WifiMetrics.MIN_WIFI_GOOD_USABILITY_STATS_PERIOD_MS; } dumpProtoAndDeserialize(); - assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD, + assertEquals(2 * WifiMetrics.MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE_TO_UPLOAD, mDecodedProto.wifiUsabilityStatsList.length); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_PER_TYPE_TO_UPLOAD; i++) { - assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE, + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_RECORDS_PER_TYPE_TO_UPLOAD; i++) { + assertEquals(WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE, mDecodedProto.wifiUsabilityStatsList[2 * i].stats.length); assertEquals(2, mDecodedProto.wifiUsabilityStatsList[2 * i + 1].stats.length); } @@ -4507,14 +4562,16 @@ public class WifiMetricsTest extends WifiBaseTest { WifiLinkLayerStats stats3 = new WifiLinkLayerStats(); WifiLinkLayerStats stats4 = new WifiLinkLayerStats(); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE - 1; + i++) { mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3); stats3 = nextRandomStats(stats3); } mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3); mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD, WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE - 1; + i++) { mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4); stats4 = nextRandomStats(stats4); } @@ -4546,14 +4603,16 @@ public class WifiMetricsTest extends WifiBaseTest { WifiLinkLayerStats stats3 = new WifiLinkLayerStats(); WifiLinkLayerStats stats4 = new WifiLinkLayerStats(); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE - 1; + i++) { mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3); stats3 = nextRandomStats(stats3); } mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats3); mWifiMetrics.addToWifiUsabilityStatsList(TEST_IFACE_NAME, WifiUsabilityStats.LABEL_BAD, WifiUsabilityStats.TYPE_DATA_STALL_BAD_TX, -1); - for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_LIST_SIZE - 1; i++) { + for (int i = 0; i < WifiMetrics.MAX_WIFI_USABILITY_STATS_ENTRIES_RING_BUFFER_SIZE - 1; + i++) { mWifiMetrics.updateWifiUsabilityStatsEntries(TEST_IFACE_NAME, info, stats4); stats4 = nextRandomStats(stats4); } @@ -7316,4 +7375,479 @@ public class WifiMetricsTest extends WifiBaseTest { eq(true), // mIsEcpsPriorityAccessSupported eq(WifiStatsLog.WIFI_AP_CAPABILITIES_REPORTED__CHANNEL_WIDTH_MHZ__CHANNEL_WIDTH_160MHZ))); // mChannelWidth } + + @Test + public void getDeviceStateForScorer() { + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + mWifiMetrics.getDeviceStateForScorer(false, false, false, false, false)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_SIM_INSERTED, + mWifiMetrics.getDeviceStateForScorer(true, false, false, false, false)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_SCORING_DISABLED, + mWifiMetrics.getDeviceStateForScorer(true, true, false, false, false)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_OFF, + mWifiMetrics.getDeviceStateForScorer(true, true, false, false, true)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_CELLULAR_UNAVAILABLE, + mWifiMetrics.getDeviceStateForScorer(true, true, true, false, true)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_OTHERS, + mWifiMetrics.getDeviceStateForScorer(true, true, true, true, true)); + } + + @Test + public void convertWifiUnusableTypeForScorer() { + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL, + mWifiMetrics.convertWifiUnusableTypeForScorer( + WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL, + mWifiMetrics.convertWifiUnusableTypeForScorer( + WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL, + mWifiMetrics.convertWifiUnusableTypeForScorer( + WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FIRMWARE_ALERT, + mWifiMetrics.convertWifiUnusableTypeForScorer( + WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_IP_REACHABILITY_LOST, + mWifiMetrics.convertWifiUnusableTypeForScorer( + WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST)); + + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + mWifiMetrics.convertWifiUnusableTypeForScorer(WifiIsUnusableEvent.TYPE_UNKNOWN)); + } + + @Test + public void getFrameworkStateForScorer() { + mWifiMetrics.mLastScreenOffTimeMillis = 3000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 1000; + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 4000); + assertEquals( + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_AWAKENING, + mWifiMetrics.getFrameworkStateForScorer(false)); + assertEquals( + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_CONNECTED, + mWifiMetrics.getFrameworkStateForScorer(false)); + assertEquals( + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + mWifiMetrics.getFrameworkStateForScorer(true)); + } + + @Test + public void calcNetworkCapabilitiesSufficient() { + WifiMetrics.Speeds speeds = new WifiMetrics.Speeds(); + WifiMetrics.SpeedSufficient speedSufficient; + + // Invalid / invalid + speeds.DownstreamKbps = WifiMetrics.INVALID_SPEED; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + speedSufficient.Upstream); + + // Low / invalid + speeds.DownstreamKbps = 0; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__FALSE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + speedSufficient.Upstream); + + // Barely bad / invalid + speeds.DownstreamKbps = 999; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__FALSE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + speedSufficient.Upstream); + + // Barely good / invalid + speeds.DownstreamKbps = 1000; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + speedSufficient.Upstream); + + // Good / invalid + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + speedSufficient.Upstream); + + // Good / low + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 0; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__FALSE, + speedSufficient.Upstream); + + // Good / Barely bad + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 999; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__FALSE, + speedSufficient.Upstream); + + // Good / Barely good + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 1000; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__TRUE, + speedSufficient.Upstream); + + // Good / Good + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 2000; + speedSufficient = mWifiMetrics.calcSpeedSufficientNetworkCapabilities(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__TRUE, + speedSufficient.Upstream); + + } + + @Test + public void calcSpeedSufficientThroughputPredictor() { + WifiDataStall.Speeds speeds = new WifiDataStall.Speeds(); + WifiMetrics.SpeedSufficient speedSufficient; + + // Invalid / invalid + speeds.DownstreamKbps = WifiMetrics.INVALID_SPEED; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN, + speedSufficient.Upstream); + + // Low / invalid + speeds.DownstreamKbps = 0; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__FALSE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN, + speedSufficient.Upstream); + + // Barely bad / invalid + speeds.DownstreamKbps = 999; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__FALSE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN, + speedSufficient.Upstream); + + // Barely good / invalid + speeds.DownstreamKbps = 1000; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN, + speedSufficient.Upstream); + + // Good / invalid + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = WifiMetrics.INVALID_SPEED; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN, + speedSufficient.Upstream); + + // Good / low + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 0; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__FALSE, + speedSufficient.Upstream); + + // Good / Barely bad + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 999; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__FALSE, + speedSufficient.Upstream); + + // Good / Barely good + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 1000; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__TRUE, + speedSufficient.Upstream); + + // Good / Good + speeds.DownstreamKbps = 2000; + speeds.UpstreamKbps = 2000; + speedSufficient = mWifiMetrics.calcSpeedSufficientThroughputPredictor(speeds); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__TRUE, + speedSufficient.Downstream); + assertEquals(SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__TRUE, + speedSufficient.Upstream); + + } + + @Test + public void logScorerPredictionResult_withoutExternalScorer() { + when(mWifiDataStall.isThroughputSufficient()).thenReturn(false); + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10000); + + WifiMetrics.ConnectionEvent connectionEvent = mWifiMetrics.new ConnectionEvent(); + WifiMetrics.SessionData currentSession = + new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0); + mWifiMetrics.mCurrentSession = currentSession; + mWifiMetrics.mLastScreenOffTimeMillis = 1000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 3000; + + mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null); + mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE); + + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + false, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + } + + @Test + public void logScorerPredictionResult_withExternalScorer() { + mWifiMetrics.setIsExternalWifiScorerOn(true, TEST_UID); + when(mWifiDataStall.isThroughputSufficient()).thenReturn(false); + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10000); + + WifiMetrics.ConnectionEvent connectionEvent = mWifiMetrics.new ConnectionEvent(); + WifiMetrics.SessionData currentSession = + new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0); + mWifiMetrics.mCurrentSession = currentSession; + mWifiMetrics.mLastScreenOffTimeMillis = 1000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 3000; + + mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null); + mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE); + + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + false, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + TEST_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + false, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + } + + @Test + public void logScorerPredictionResult_notDefaultPollingInterval() { + when(mWifiDataStall.isThroughputSufficient()).thenReturn(false); + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10000); + + WifiMetrics.ConnectionEvent connectionEvent = mWifiMetrics.new ConnectionEvent(); + WifiMetrics.SessionData currentSession = + new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0); + mWifiMetrics.mCurrentSession = currentSession; + mWifiMetrics.mLastScreenOffTimeMillis = 1000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 3000; + + mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null); + mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_NOT_DEFAULT, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE); + + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + false, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_NOT_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + } + + @Test + public void logScorerPredictionResult_withUnusableEvent() { + when(mWifiDataStall.isThroughputSufficient()).thenReturn(false); + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10000); + + WifiMetrics.ConnectionEvent connectionEvent = mWifiMetrics.new ConnectionEvent(); + WifiMetrics.SessionData currentSession = + new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0); + mWifiMetrics.mCurrentSession = currentSession; + mWifiMetrics.mLastScreenOffTimeMillis = 1000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 3000; + + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); + mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null); + mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE); + + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_FRAMEWORK_DATA_STALL, + false, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + } + + @Test + public void logScorerPredictionResult_wifiSufficient() { + when(mWifiDataStall.isThroughputSufficient()).thenReturn(true); + when(mClock.getElapsedSinceBootMillis()).thenReturn((long) 10000); + + WifiMetrics.ConnectionEvent connectionEvent = mWifiMetrics.new ConnectionEvent(); + WifiMetrics.SessionData currentSession = + new WifiMetrics.SessionData(connectionEvent, "", (long) 1000, 0, 0); + mWifiMetrics.mCurrentSession = currentSession; + mWifiMetrics.mLastScreenOffTimeMillis = 1000; + mWifiMetrics.mLastIgnoredPollTimeMillis = 3000; + + mWifiMetrics.updateWiFiEvaluationAndScorerStats(true, null, null); + mWifiMetrics.logScorerPredictionResult(false, false, false, POLLING_INTERVAL_DEFAULT, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE); + + ExtendedMockito.verify(() -> WifiStatsLog.write_non_chained( + SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, null, + WIFI_IS_UNUSABLE_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + SCORER_PREDICTION_RESULT_REPORTED__UNUSABLE_EVENT__EVENT_NONE, + true, + SCORER_PREDICTION_RESULT_REPORTED__DEVICE_STATE__STATE_NO_CELLULAR_MODEM, + POLLING_INTERVAL_DEFAULT, + SCORER_PREDICTION_RESULT_REPORTED__WIFI_FRAMEWORK_STATE__FRAMEWORK_STATE_LINGERING, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_NETWORK_CAPABILITIES_US__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_DS__UNKNOWN, + SCORER_PREDICTION_RESULT_REPORTED__SPEED_SUFFICIENT_THROUGHPUT_PREDICTOR_US__UNKNOWN + )); + } + + @Test + public void resetWifiUnusableEvent() { + long eventTime = 0; + when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); + + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); + assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX, mWifiMetrics.mUnusableEventType); + mWifiMetrics.resetWifiUnusableEvent(); + assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiMetrics.mUnusableEventType); + + eventTime += WifiMetrics.MIN_DATA_STALL_WAIT_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX); + assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_TX_WITHOUT_RX, + mWifiMetrics.mUnusableEventType); + mWifiMetrics.resetWifiUnusableEvent(); + assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiMetrics.mUnusableEventType); + + eventTime += WifiMetrics.MIN_DATA_STALL_WAIT_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH); + assertEquals(WifiIsUnusableEvent.TYPE_DATA_STALL_BOTH, mWifiMetrics.mUnusableEventType); + mWifiMetrics.resetWifiUnusableEvent(); + assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiMetrics.mUnusableEventType); + + eventTime += WifiMetrics.MIN_DATA_STALL_WAIT_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT); + assertEquals(WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT, mWifiMetrics.mUnusableEventType); + mWifiMetrics.resetWifiUnusableEvent(); + assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiMetrics.mUnusableEventType); + + eventTime += WifiMetrics.MIN_DATA_STALL_WAIT_MS; + when(mClock.getElapsedSinceBootMillis()).thenReturn(eventTime); + mWifiMetrics.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST); + assertEquals(WifiIsUnusableEvent.TYPE_IP_REACHABILITY_LOST, mWifiMetrics.mUnusableEventType); + mWifiMetrics.resetWifiUnusableEvent(); + assertEquals(WifiIsUnusableEvent.TYPE_UNKNOWN, mWifiMetrics.mUnusableEventType); + } + + /** Verifies WiFi Scorer new stats collection flag could be set properly */ + @Test + public void verifyWifiScorerNewStatsCollectionFlagTrue() { + when(Flags.wifiScorerNewStatsCollection()).thenReturn(true); + assertEquals(mWifiMetrics.isWiFiScorerNewStatsCollected(), true); + when(Flags.wifiScorerNewStatsCollection()).thenReturn(false); + assertEquals(mWifiMetrics.isWiFiScorerNewStatsCollected(), false); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java index 8464293508..f57f8c43b1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMulticastLockManagerTest.java @@ -22,8 +22,9 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TR import static org.junit.Assert.*; import static org.mockito.Mockito.*; +import android.app.ActivityManager; +import android.content.Context; import android.os.BatteryStatsManager; -import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.WorkSource; @@ -50,6 +51,7 @@ import org.mockito.Spy; public class WifiMulticastLockManagerTest extends WifiBaseTest { private static final String WL_1_TAG = "Wakelock-1"; private static final String WL_2_TAG = "Wakelock-2"; + private static final int TEST_UID = 123; private TestLooper mLooper; @Mock ConcreteClientModeManager mClientModeManager; @@ -58,7 +60,11 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { @Spy FakeFilterController mFilterController2 = new FakeFilterController(); @Mock BatteryStatsManager mBatteryStats; @Mock ActiveModeWarden mActiveModeWarden; + @Mock Context mContext; + @Mock ActivityManager mActivityManager; @Captor ArgumentCaptor<PrimaryClientModeManagerChangedCallback> mPrimaryChangedCallbackCaptor; + @Captor ArgumentCaptor<ActivityManager.OnUidImportanceListener> mUidImportanceListenerCaptor = + ArgumentCaptor.forClass(ActivityManager.OnUidImportanceListener.class); WifiMulticastLockManager mManager; /** @@ -78,11 +84,14 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { when(mClientModeManager2.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); + when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager); mManager = new WifiMulticastLockManager(mActiveModeWarden, mBatteryStats, - mLooper.getLooper()); + mLooper.getLooper(), mContext); verify(mActiveModeWarden).registerPrimaryClientModeManagerChangedCallback( mPrimaryChangedCallbackCaptor.capture()); + verify(mActivityManager).addOnUidImportanceListener( + mUidImportanceListenerCaptor.capture(), anyInt()); } /** @@ -91,7 +100,7 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { @Test public void noLocks() { assertFalse(mManager.isMulticastEnabled()); - mManager.initializeFiltering(); + mManager.startFilteringMulticastPackets(); verify(mFilterController, times(1)).startFilteringMulticastPackets(); } @@ -101,21 +110,21 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { @Test public void oneLock() throws RemoteException { IBinder binder = mock(IBinder.class); - mManager.acquireLock(binder, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); assertTrue(mManager.isMulticastEnabled()); verify(mFilterController).stopFilteringMulticastPackets(); - mManager.initializeFiltering(); + mManager.startFilteringMulticastPackets(); verify(mFilterController, times(0)).startFilteringMulticastPackets(); ArgumentCaptor<WorkSource> wsCaptor = ArgumentCaptor.forClass(WorkSource.class); verify(mBatteryStats).reportWifiMulticastEnabled(wsCaptor.capture()); assertNotNull(wsCaptor.getValue()); - assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid()); + assertEquals(TEST_UID, wsCaptor.getValue().getAttributionUid()); verify(mBatteryStats, times(0)).reportWifiMulticastDisabled(any()); - mManager.releaseLock(WL_1_TAG); + mManager.releaseLock(TEST_UID, binder, WL_1_TAG); verify(mBatteryStats).reportWifiMulticastDisabled(wsCaptor.capture()); assertNotNull(wsCaptor.getValue()); - assertEquals(Binder.getCallingUid(), wsCaptor.getValue().getAttributionUid()); + assertEquals(TEST_UID, wsCaptor.getValue().getAttributionUid()); assertFalse(mManager.isMulticastEnabled()); } @@ -151,7 +160,7 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { assertTrue(mFilterController2.isFilteringStarted()); IBinder binder = mock(IBinder.class); - mManager.acquireLock(binder, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); assertTrue(mManager.isMulticastEnabled()); // CMM1 filtering stopped assertFalse(mFilterController.isFilteringStarted()); @@ -172,7 +181,7 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { // CMM2 filter stopped assertFalse(mFilterController2.isFilteringStarted()); - mManager.releaseLock(WL_1_TAG); + mManager.releaseLock(TEST_UID, binder, WL_1_TAG); assertFalse(mManager.isMulticastEnabled()); // CMM1 filter started assertTrue(mFilterController.isFilteringStarted()); @@ -186,15 +195,15 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { @Test public void oneLock_wrongName() throws RemoteException { IBinder binder = mock(IBinder.class); - mManager.acquireLock(binder, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); assertTrue(mManager.isMulticastEnabled()); verify(mFilterController).stopFilteringMulticastPackets(); - mManager.initializeFiltering(); + mManager.startFilteringMulticastPackets(); verify(mFilterController, never()).startFilteringMulticastPackets(); verify(mBatteryStats).reportWifiMulticastEnabled(any()); verify(mBatteryStats, never()).reportWifiMulticastDisabled(any()); - mManager.releaseLock(WL_2_TAG); + mManager.releaseLock(TEST_UID, binder, WL_2_TAG); verify(mBatteryStats, never()).reportWifiMulticastDisabled(any()); assertTrue(mManager.isMulticastEnabled()); } @@ -209,25 +218,25 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { InOrder inOrderHandler = inOrder(mFilterController); InOrder inOrderBatteryStats = inOrder(mBatteryStats); - mManager.acquireLock(binder, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.acquireLock(binder, WL_2_TAG); + mManager.acquireLock(TEST_UID, binder, WL_2_TAG); inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.initializeFiltering(); + mManager.startFilteringMulticastPackets(); inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets(); - mManager.releaseLock(WL_2_TAG); + mManager.releaseLock(TEST_UID, binder, WL_2_TAG); inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.releaseLock(WL_1_TAG); + mManager.releaseLock(TEST_UID, binder, WL_1_TAG); inOrderHandler.verify(mFilterController).startFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); assertFalse(mManager.isMulticastEnabled()); @@ -243,27 +252,131 @@ public class WifiMulticastLockManagerTest extends WifiBaseTest { InOrder inOrderHandler = inOrder(mFilterController); InOrder inOrderBatteryStats = inOrder(mBatteryStats); - mManager.acquireLock(binder, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.acquireLock(binder, WL_2_TAG); + mManager.acquireLock(TEST_UID, binder, WL_2_TAG); inOrderHandler.verify(mFilterController).stopFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastEnabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.initializeFiltering(); + mManager.startFilteringMulticastPackets(); inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets(); - mManager.releaseLock(WL_1_TAG); + mManager.releaseLock(TEST_UID, binder, WL_1_TAG); inOrderHandler.verify(mFilterController, never()).startFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); assertTrue(mManager.isMulticastEnabled()); - mManager.releaseLock(WL_2_TAG); + mManager.releaseLock(TEST_UID, binder, WL_2_TAG); inOrderHandler.verify(mFilterController).startFilteringMulticastPackets(); inOrderBatteryStats.verify(mBatteryStats).reportWifiMulticastDisabled(any()); assertFalse(mManager.isMulticastEnabled()); } + + /** + * Verify the behavior when two separate locks are created using the same tag. + * + * Since locks are uniquely identified by (binder, tag), we expect that multicast is + * enabled until both locks have been released. + */ + @Test + public void testMultipleLocksWithSameTag() throws RemoteException { + IBinder binder1 = mock(IBinder.class); + IBinder binder2 = mock(IBinder.class); + + // Both acquired locks have the same tag + mManager.acquireLock(TEST_UID, binder1, WL_1_TAG); + mManager.acquireLock(TEST_UID, binder2, WL_1_TAG); + assertTrue(mManager.isMulticastEnabled()); + + mManager.releaseLock(TEST_UID, binder1, WL_1_TAG); + verify(mBatteryStats, times(1)).reportWifiMulticastDisabled(any()); + assertTrue(mManager.isMulticastEnabled()); + + mManager.releaseLock(TEST_UID, binder2, WL_1_TAG); + verify(mBatteryStats, times(2)).reportWifiMulticastDisabled(any()); + assertFalse(mManager.isMulticastEnabled()); + } + + /** + * Test that mulicast filtering is toggled correctly when the owner of + * a single lock transitions between importance levels. + */ + @Test + public void testSingleLockActiveStateChange() { + IBinder binder = mock(IBinder.class); + mManager.acquireLock(TEST_UID, binder, WL_1_TAG); + assertTrue(mManager.isMulticastEnabled()); + verify(mFilterController).stopFilteringMulticastPackets(); + + // Transition UID to low importance + mUidImportanceListenerCaptor.getValue().onUidImportance( + TEST_UID, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); + mLooper.dispatchAll(); + assertFalse(mManager.isMulticastEnabled()); + verify(mFilterController).startFilteringMulticastPackets(); + + // Transition UID to high importance + mUidImportanceListenerCaptor.getValue().onUidImportance( + TEST_UID, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); + mLooper.dispatchAll(); + assertTrue(mManager.isMulticastEnabled()); + verify(mFilterController, times(2)).stopFilteringMulticastPackets(); + + mManager.releaseLock(TEST_UID, binder, WL_1_TAG); + assertFalse(mManager.isMulticastEnabled()); + verify(mFilterController, times(2)).startFilteringMulticastPackets(); + } + + /** + * Test that mulicast filtering is toggled correctly when multiple lock owners + * transition between importance levels. + */ + @Test + public void testMultipleOwnersActiveStateChange() { + int uid1 = TEST_UID; + int uid2 = TEST_UID + 1; + IBinder binder1 = mock(IBinder.class); + IBinder binder2 = mock(IBinder.class); + + mManager.acquireLock(uid1, binder1, WL_1_TAG); + mManager.acquireLock(uid2, binder2, WL_2_TAG); + assertTrue(mManager.isMulticastEnabled()); + verify(mFilterController, times(2)).stopFilteringMulticastPackets(); + + // Transition UID 1 to low importance. Since UID 2 is still active, + // multicast should still be enabled. + mUidImportanceListenerCaptor.getValue().onUidImportance( + uid1, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); + mLooper.dispatchAll(); + assertTrue(mManager.isMulticastEnabled()); + verify(mFilterController, never()).startFilteringMulticastPackets(); + + // Transition UID 2 to low importance. Since no lock owners are active, + // multicast should be disabled. + mUidImportanceListenerCaptor.getValue().onUidImportance( + uid2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); + mLooper.dispatchAll(); + assertFalse(mManager.isMulticastEnabled()); + verify(mFilterController).startFilteringMulticastPackets(); + + // Transition UID 2 back to high importance. Multicast should be re-enabled. + mUidImportanceListenerCaptor.getValue().onUidImportance( + uid2, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); + mLooper.dispatchAll(); + assertTrue(mManager.isMulticastEnabled()); + verify(mFilterController, times(3)).stopFilteringMulticastPackets(); + + // Release the lock held by UID 1. An active lock is still held by UID 2. + mManager.releaseLock(uid1, binder1, WL_1_TAG); + assertTrue(mManager.isMulticastEnabled()); + + // Release the lock held by UID 2. No locks are active. + mManager.releaseLock(uid2, binder2, WL_2_TAG); + assertFalse(mManager.isMulticastEnabled()); + verify(mFilterController, times(2)).startFilteringMulticastPackets(); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java index 0fcc471052..ba5db03818 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java @@ -40,11 +40,13 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import android.app.test.MockAnswerUtil; import android.net.wifi.OuiKeyedData; import android.net.wifi.SoftApConfiguration; import android.net.wifi.WifiContext; +import android.net.wifi.WifiMigration; import android.net.wifi.WifiScanner; import android.net.wifi.nl80211.WifiNl80211Manager; import android.os.Handler; @@ -53,6 +55,7 @@ import android.os.test.TestLooper; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; import com.android.server.wifi.WifiNative.SupplicantDeathEventHandler; @@ -61,6 +64,7 @@ import com.android.server.wifi.hal.WifiNanIface; import com.android.server.wifi.p2p.WifiP2pNative; import com.android.server.wifi.util.NetdWrapper; import com.android.server.wifi.util.NetdWrapper.NetdEventObserver; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import org.junit.After; @@ -70,8 +74,10 @@ import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Set; @@ -84,8 +90,9 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { private static final String IFACE_NAME_0 = "mockWlan0"; private static final String IFACE_NAME_1 = "mockWlan1"; private static final String SELF_RECOVERY_IFACE_NAME = "mockWlan2"; + private static final String IFACE_NAME_AWARE = "MockAware"; private static final WorkSource TEST_WORKSOURCE = new WorkSource(); - private static final long TEST_SUPPORTED_FEATURES = 0; + private static final long[] TEST_SUPPORTED_FEATURES = new long[]{ 0 }; private static final int STA_FAILURE_CODE_START_DAEMON = 1; private static final int STA_FAILURE_CODE_SETUP_INTERFACE = 2; private static final int STA_FAILURE_CODE_WIFICOND_SETUP_INTERFACE = 3; @@ -126,6 +133,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @Mock private SoftApManager mSoftApManager; @Mock private WifiNanIface mActiveWifiNanIface; @Mock DeviceConfigFacade mDeviceConfigFacade; + private MockitoSession mSession; private TestLooper mLooper; private WifiNative.Iface mActiveP2pIface; @@ -180,6 +188,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { new ArrayList<>()); when(mWifiVendorHal.enableStaChannelForPeerNetwork(anyBoolean(), anyBoolean())).thenReturn( true); + when(mWifiVendorHal.getSupportedFeatureSet(anyString())).thenReturn(new BitSet()); when(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); @@ -202,6 +211,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mSupplicantStaIfaceHal.startDaemon()).thenReturn(true); when(mSupplicantStaIfaceHal.setupIface(any())).thenReturn(true); when(mSupplicantStaIfaceHal.teardownIface(any())).thenReturn(true); + when(mSupplicantStaIfaceHal.getAdvancedCapabilities(anyString())).thenReturn(new BitSet()); + when(mSupplicantStaIfaceHal.getWpaDriverFeatureSet(anyString())).thenReturn(new BitSet()); when(mHostapdHal.registerDeathHandler(mHostapdDeathHandlerCaptor.capture())) .thenReturn(true); @@ -231,12 +242,19 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { when(mDeviceConfigFacade.isInterfaceFailureBugreportEnabled()).thenReturn(false); when(mWifiSettingsConfigStore.get( - eq(WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES))) + eq(WifiSettingsConfigStore.WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES))) .thenReturn(TEST_SUPPORTED_FEATURES); when(mWifiSettingsConfigStore.get( eq(WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS))) .thenReturn(TEST_SUPPORTED_BANDS); + mSession = ExtendedMockito.mockitoSession() + .mockStatic(Flags.class, withSettings().lenient()) + .mockStatic(WifiMigration.class, withSettings().lenient()) + .startMocking(); + when(Flags.rsnOverriding()).thenReturn(false); + when(mActiveWifiNanIface.getName()).thenReturn(IFACE_NAME_AWARE); + mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mIfaceEventCallback0, mWifiMetrics, mWifiP2pNative); @@ -259,6 +277,9 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { @After public void tearDown() throws Exception { + if (mSession != null) { + mSession.finishMocking(); + } verifyNoMoreInteractions(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mIfaceEventCallback0, mWifiMetrics); @@ -581,8 +602,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mSupplicantStaIfaceHal).isInitializationStarted(); mInOrder.verify(mSupplicantStaIfaceHal).terminate(); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); } @@ -609,8 +630,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); mInOrder.verify(mWifiVendorHal).enableStaChannelForPeerNetwork(anyBoolean(), anyBoolean()); @@ -622,8 +643,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); } @@ -1377,8 +1398,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mWifiMetrics).incrementNumSetupClientInterfaceFailureDueToSupplicant(); } else { mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); } @@ -1568,6 +1589,30 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { executeAndValidateTeardownNanInterface(false, false, false, false, mActiveNanIface); } + @Test + public void testCreateNanIfaceFailureWhenFailToCreateNan() throws Exception { + when(mHalDeviceManager.createNanIface(any(), any(), any())) + .thenReturn(null); + mActiveNanIface = mWifiNative.createNanIface(mTestInterfaceDestroyedListener, + mCreateIfaceEventHandler, TEST_WORKSOURCE); + validateStartHal(false, true); + assertNull(mActiveNanIface); + validateOnDestroyedNanInterface(false, false, false, false); + } + + @Test + public void testCreateNanIfaceFailureWhenFailToGetNanIfaceName() throws Exception { + when(mHalDeviceManager.createNanIface(any(), any(), any())) + .thenReturn(mActiveWifiNanIface); + // The empty aware iface will cause failure + when(mActiveWifiNanIface.getName()).thenReturn(null); + mActiveNanIface = mWifiNative.createNanIface(mTestInterfaceDestroyedListener, + mCreateIfaceEventHandler, TEST_WORKSOURCE); + validateStartHal(false, true); + assertNull(mActiveNanIface); + validateOnDestroyedNanInterface(false, false, false, false); + } + private void executeAndValidateSetupClientInterface( boolean hasStaIface, boolean hasApIface, String ifaceName, @Mock WifiNative.InterfaceCallback callback, @@ -1829,8 +1874,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); mInOrder.verify(mWifiVendorHal).enableLinkLayerStats(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); mInOrder.verify(mWifiVendorHal).enableStaChannelForPeerNetwork(anyBoolean(), anyBoolean()); @@ -2045,8 +2090,8 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { mInOrder.verify(mNetdWrapper).registerObserver(networkObserverCaptor.capture()); mInOrder.verify(mNetdWrapper).isInterfaceUp(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getAdvancedCapabilities(ifaceName); - mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mSupplicantStaIfaceHal).getWpaDriverFeatureSet(ifaceName); + mInOrder.verify(mWifiVendorHal).getSupportedFeatureSet(ifaceName); mInOrder.verify(mWifiVendorHal).getTwtCapabilities(ifaceName); mInOrder.verify(mWifiVendorHal).getUsableChannels(anyInt(), anyInt(), anyInt()); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java index cff25254dd..28865ca01d 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java @@ -20,6 +20,9 @@ import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ; import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_FEATURES; +import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES; +import static com.android.server.wifi.util.GeneralUtil.bitsetToLong; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -43,6 +46,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import android.net.MacAddress; import android.net.wifi.CoexUnsafeChannel; @@ -52,6 +56,7 @@ import android.net.wifi.WifiAvailableChannel; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; +import android.net.wifi.WifiMigration; import android.net.wifi.WifiScanner; import android.net.wifi.WifiScanner.ScanData; import android.net.wifi.WifiSsid; @@ -70,9 +75,11 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.coex.CoexManager; import com.android.server.wifi.hal.WifiChip; +import com.android.server.wifi.p2p.WifiP2pNative; import com.android.server.wifi.proto.WifiStatsLog; import com.android.server.wifi.util.NativeUtil; import com.android.server.wifi.util.NetdWrapper; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; import org.junit.After; @@ -89,6 +96,7 @@ import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Random; @@ -250,8 +258,8 @@ public class WifiNativeTest extends WifiBaseTest { return result; } - public static final long WIFI_TEST_FEATURE = 0x800000000L; - + private static final BitSet WIFI_TEST_FEATURE = + createCapabilityBitset(WifiManager.WIFI_FEATURE_OWE); private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = new RadioChainInfo(1, -89); private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = new RadioChainInfo(0, -78); private static final WorkSource TEST_WORKSOURCE = new WorkSource(); @@ -283,6 +291,7 @@ public class WifiNativeTest extends WifiBaseTest { @Mock private WifiGlobals mWifiGlobals; @Mock DeviceConfigFacade mDeviceConfigFacade; @Mock WifiChip.AfcChannelAllowance mAfcChannelAllowance; + @Mock private WifiP2pNative mWifiP2pNative; private MockitoSession mSession; ArgumentCaptor<WifiNl80211Manager.ScanEventCallback> mScanCallbackCaptor = @@ -302,6 +311,9 @@ public class WifiNativeTest extends WifiBaseTest { .thenReturn(WIFI_IFACE_NAME); when(mWifiVendorHal.createApIface(any(), any(), anyInt(), anyBoolean(), any(), anyList())) .thenReturn(WIFI_IFACE_NAME); + when(mWifiVendorHal.getSupportedFeatureSet(anyString())).thenReturn(new BitSet()); + when(mWifiVendorHal.replaceStaIfaceRequestorWs(WIFI_IFACE_NAME, TEST_WORKSOURCE)) + .thenReturn(true); when(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); @@ -316,6 +328,8 @@ public class WifiNativeTest extends WifiBaseTest { when(mStaIfaceHal.initialize()).thenReturn(true); when(mStaIfaceHal.startDaemon()).thenReturn(true); when(mStaIfaceHal.setupIface(any())).thenReturn(true); + when(mStaIfaceHal.getAdvancedCapabilities(anyString())).thenReturn(new BitSet()); + when(mStaIfaceHal.getWpaDriverFeatureSet(anyString())).thenReturn(new BitSet()); when(mHostapdHal.isInitializationStarted()).thenReturn(true); when(mHostapdHal.startDaemon()).thenReturn(true); @@ -329,11 +343,12 @@ public class WifiNativeTest extends WifiBaseTest { when(mWifiInjector.getContext()).thenReturn(mContext); when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); + when(mWifiInjector.getWifiP2pNative()).thenReturn(mWifiP2pNative); mResources = getMockResources(); mResources.setBoolean(R.bool.config_wifiNetworkCentricQosPolicyFeatureEnabled, false); when(mContext.getResources()).thenReturn(mResources); - when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES))) - .thenReturn(WIFI_TEST_FEATURE); + when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES))) + .thenReturn(WIFI_TEST_FEATURE.toLongArray()); when(mSsidTranslator.getTranslatedSsidAndRecordBssidCharset(any(), any())) .thenAnswer((Answer<WifiSsid>) invocation -> getTranslatedSsid(invocation.getArgument(0))); @@ -344,8 +359,12 @@ public class WifiNativeTest extends WifiBaseTest { mSession = ExtendedMockito.mockitoSession() .strictness(Strictness.LENIENT) .mockStatic(WifiStatsLog.class) + .mockStatic(Flags.class, withSettings().lenient()) + .mockStatic(WifiMigration.class, withSettings().lenient()) .startMocking(); + when(Flags.rsnOverriding()).thenReturn(true); + mWifiNative = new WifiNative( mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl, mWifiMonitor, mPropertyService, mWifiMetrics, @@ -712,6 +731,51 @@ public class WifiNativeTest extends WifiBaseTest { } /** + * Verifies valules of ScanResultWithSameFreq in getWifiLinkLayerStats() call + * + */ + @Test + public void testGetWifiLinkLayerStatsForScanResultWithSameFreq() { + WifiLinkLayerStats testWifiLinkLayerStats = new WifiLinkLayerStats(); + testWifiLinkLayerStats.links = new WifiLinkLayerStats.LinkSpecificStats[2]; + // Define 2 test WiFi links, whose frequencyMhz are 0, 1, respectively + for (int i = 0; i < 2; ++i) { + testWifiLinkLayerStats.links[i] = new WifiLinkLayerStats.LinkSpecificStats(); + testWifiLinkLayerStats.links[i].frequencyMhz = i; + } + when(mWifiVendorHal.getWifiLinkLayerStats(WIFI_IFACE_NAME)) + .thenReturn(testWifiLinkLayerStats); + + // Define 6 test WiFi scan results with unique BSSID + // Their frequency are 0, 1, 2, 0, 1, 2, respectively + ScanResult[] scanResults = new ScanResult[6]; + for (int i = 0; i < 6; i++) { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = Integer.toString(i); + scanResult.frequency = i < 3 ? i : (i - 3); + // Make sure the timestamp is valid + scanResult.timestamp = Long.MAX_VALUE; + scanResults[i] = scanResult; + } + ScanData testScanData = new ScanData(0, 0, + 0, WifiScanner.WIFI_BAND_UNSPECIFIED, scanResults); + when(mWifiVendorHal.getCachedScanData(WIFI_IFACE_NAME)).thenReturn(testScanData); + mWifiNative.setLocationModeEnabled(true); + + WifiLinkLayerStats resultWifiLinkLayerStats = + mWifiNative.getWifiLinkLayerStats(WIFI_IFACE_NAME); + assertEquals(2, resultWifiLinkLayerStats.links.length); + // WiFi link 0's frequency is 0, scan results 0 and 3 have the same frequency + assertEquals(2, resultWifiLinkLayerStats.links[0].scan_results_same_freq.size()); + assertEquals("0", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(0).bssid); + assertEquals("3", resultWifiLinkLayerStats.links[0].scan_results_same_freq.get(1).bssid); + // WiFi link 1's frequency is 1, scan results 1 and 4 have the same frequency + assertEquals(2, resultWifiLinkLayerStats.links[1].scan_results_same_freq.size()); + assertEquals("1", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(0).bssid); + assertEquals("4", resultWifiLinkLayerStats.links[1].scan_results_same_freq.get(1).bssid); + } + + /** * Verifies client mode + scan success. */ @Test @@ -1586,13 +1650,34 @@ public class WifiNativeTest extends WifiBaseTest { /** * Tests that getSupportedFeatureSet() guaranteed to include the feature set stored in config - * store even when interface doesn't exist. - * + * store even when interface doesn't exist. If both legacy and extended features are stored in + * the config store, then the extended features should be returned. + */ + @Test + public void testGetExtendedFeaturesWhenInterfaceDoesntExist() throws Exception { + long legacyFeatures = 0x321; + when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES))) + .thenReturn(legacyFeatures); + when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES))) + .thenReturn(WIFI_TEST_FEATURE.toLongArray()); + BitSet featureSet = mWifiNative.getSupportedFeatureSet(null); + assertTrue(featureSet.equals(WIFI_TEST_FEATURE)); + } + + /** + * Tests that getSupportedFeatureSet() guaranteed to include the feature set stored in config + * store even when interface doesn't exist. If only legacy features are stored in the + * config store, then they should be returned. */ @Test - public void testGetSupportedFeatureSetWhenInterfaceDoesntExist() throws Exception { - long featureSet = mWifiNative.getSupportedFeatureSet(null); - assertEquals(featureSet, WIFI_TEST_FEATURE); + public void testGetLegacyFeaturesWhenInterfaceDoesntExist() throws Exception { + long legacyFeatures = bitsetToLong(WIFI_TEST_FEATURE); + when(mSettingsConfigStore.get(eq(WIFI_NATIVE_SUPPORTED_FEATURES))) + .thenReturn(legacyFeatures); + when(mSettingsConfigStore.get(eq(WIFI_NATIVE_EXTENDED_SUPPORTED_FEATURES))) + .thenReturn(new long[0]); // no extended features + BitSet featureSet = mWifiNative.getSupportedFeatureSet(null); + assertTrue(featureSet.equals(WIFI_TEST_FEATURE)); } /** @@ -1633,8 +1718,8 @@ public class WifiNativeTest extends WifiBaseTest { mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, mConcreteClientModeManager); mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); - verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ); - verify(mWificondControl).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ); + verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_24_GHZ); + verify(mWificondControl, times(2)).getChannelsMhzForBand(WifiScanner.WIFI_BAND_5_GHZ); assertEquals(3, mWifiNative.getSupportedBandsForSta(WIFI_IFACE_NAME)); } @@ -1820,4 +1905,49 @@ public class WifiNativeTest extends WifiBaseTest { WifiManager.ROAMING_MODE_NORMAL)); verify(mWifiVendorHal).setRoamingMode(WIFI_IFACE_NAME, WifiManager.ROAMING_MODE_NORMAL); } + + @Test + public void testRsnOverridingFeatureSupportOnOlderHals() throws Exception { + when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(false); + + /* RSN Overriding feature is enabled when overlay config item is set to true */ + mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + assertTrue(mWifiNative.mIsRsnOverridingSupported); + mWifiNative.teardownAllInterfaces(); + + /* RSN Overriding feature is disabled when overlay config item is set to false */ + mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + assertFalse(mWifiNative.mIsRsnOverridingSupported); + mWifiNative.teardownAllInterfaces(); + } + + @Test + public void testRsnOverridingFeatureSupportOnNewerHals() throws Exception { + when(mStaIfaceHal.isAidlServiceVersionAtLeast(4)).thenReturn(true); + + /* RSN Overriding feature is enabled based on chip capability */ + mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, false); + when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(true); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + assertTrue(mWifiNative.mIsRsnOverridingSupported); + mWifiNative.teardownAllInterfaces(); + + /* Overlay config has no effect on newer HALs */ + mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true); + + when(mStaIfaceHal.isRsnOverridingSupported(WIFI_IFACE_NAME)).thenReturn(false); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + mWifiNative.switchClientInterfaceToConnectivityMode(WIFI_IFACE_NAME, TEST_WORKSOURCE); + assertFalse(mWifiNative.mIsRsnOverridingSupported); + mWifiNative.teardownAllInterfaces(); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index 87dce767a5..0a8fccac7c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -18,9 +18,11 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_AUTHENTICATION; import static android.net.wifi.WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_IP_PROVISIONING; +import static android.net.wifi.WifiManager.STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.server.wifi.WifiNetworkFactory.PERIODIC_SCAN_INTERVAL_MS; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; import static org.junit.Assert.assertArrayEquals; @@ -105,6 +107,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.util.ActionListenerWrapper; import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.WifiPermissionsUtil; +import com.android.wifi.flags.FeatureFlags; import com.android.wifi.resources.R; import org.junit.After; @@ -154,6 +157,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { private static final String TEST_BSSID_1_2_OUI = "12:34:23:00:00:00"; private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00"; private static final String TEST_WPA_PRESHARED_KEY = "\"password123\""; + private static final int TEST_PREFERRED_CHANNEL_FREQ = 5260; @Mock WifiContext mContext; @Mock Resources mResources; @@ -187,6 +191,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { private @Mock ClientModeManager mPrimaryClientModeManager; private @Mock WifiGlobals mWifiGlobals; @Mock WifiDeviceStateChangeManager mWifiDeviceStateChangeManager; + @Mock FeatureFlags mFeatureFlags; + @Mock DeviceConfigFacade mDeviceConfigFacade; private MockitoSession mStaticMockSession = null; NetworkCapabilities mNetworkCapabilities; TestLooper mLooper; @@ -264,11 +270,13 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { when(mPackageManager.getApplicationLabel(any())).thenReturn(TEST_APP_NAME); mockPackageImportance(TEST_PACKAGE_NAME_1, true, false); mockPackageImportance(TEST_PACKAGE_NAME_2, true, false); + when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags); when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); when(mWifiInjector.getActiveModeWarden()).thenReturn(mActiveModeWarden); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiInjector.getWifiDeviceStateChangeManager()) .thenReturn(mWifiDeviceStateChangeManager); + when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), anyString(), eq(false))) @@ -292,7 +300,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { new WorkSource(Process.SYSTEM_UID, "system-service")); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); mWifiNetworkFactory = new WifiNetworkFactory(mLooper.getLooper(), mContext, mNetworkCapabilities, mActivityManager, mAlarmManager, mAppOpsManager, @@ -712,7 +721,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifier() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0], false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, + new int[]{TEST_PREFERRED_CHANNEL_FREQ}, false); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify UI start. @@ -721,7 +731,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Verify scan settings. verify(mWifiScanner).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null, new int[0]); + validateScanSettings(null, new int[]{TEST_PREFERRED_CHANNEL_FREQ}); verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); } @@ -764,7 +774,8 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testHandleNetworkRequestWithSpecifierForHiddenNetwork() { - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, new int[0], false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, + new int[]{TEST_PREFERRED_CHANNEL_FREQ}, false); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify UI start. @@ -775,7 +786,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { mWorkSourceArgumentCaptor.capture()); validateScanSettings( ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath(), new int[0]); + .ssidPatternMatcher.getPath(), new int[]{TEST_PREFERRED_CHANNEL_FREQ}); verify(mWifiMetrics).incrementNetworkRequestApiNumRequest(); } @@ -789,25 +800,27 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { @Test public void testHandleNetworkRequestWithSpecifierAfterPreviousHiddenNetworkRequest() { // Hidden request 1. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, new int[0], false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, true, + new int[]{TEST_PREFERRED_CHANNEL_FREQ}, false); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify scan settings. verify(mWifiScanner, times(1)).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); validateScanSettings( ((WifiNetworkSpecifier) mNetworkCapabilities.getNetworkSpecifier()) - .ssidPatternMatcher.getPath(), new int[0]); + .ssidPatternMatcher.getPath(), new int[]{TEST_PREFERRED_CHANNEL_FREQ}); // Release request 1. mWifiNetworkFactory.releaseNetworkFor(mNetworkRequest); // Regular request 2. - attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, new int[0], false); + attachDefaultWifiNetworkSpecifierAndAppInfo(TEST_UID_1, false, + new int[]{TEST_PREFERRED_CHANNEL_FREQ}, false); mWifiNetworkFactory.needNetworkFor(mNetworkRequest); // Verify scan settings. verify(mWifiScanner, times(2)).startScan(mScanSettingsArgumentCaptor.capture(), any(), any(), mWorkSourceArgumentCaptor.capture()); - validateScanSettings(null, new int[0]); + validateScanSettings(null, new int[]{TEST_PREFERRED_CHANNEL_FREQ}); verify(mWifiMetrics, times(2)).incrementNetworkRequestApiNumRequest(); } @@ -1682,8 +1695,10 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { */ @Test public void testNetworkSpecifierHandleUserSelectionReject() throws Exception { + when(mFeatureFlags.localOnlyConnectionOptimization()).thenReturn(true); sendNetworkRequestAndSetupForUserSelection(); - + mWifiNetworkFactory.addLocalOnlyConnectionStatusListener(mLocalOnlyConnectionStatusListener, + TEST_PACKAGE_NAME_1, null); INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = mNetworkRequestUserSelectionCallback.getValue(); assertNotNull(networkRequestUserSelectionCallback); @@ -1698,6 +1713,9 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { verify(mConnectivityManager).declareNetworkRequestUnfulfillable(eq(mNetworkRequest)); verify(mWifiMetrics).incrementNetworkRequestApiNumUserReject(); + verify(mLocalOnlyConnectionStatusListener).onConnectionStatus( + eq((WifiNetworkSpecifier) mNetworkRequest.getNetworkSpecifier()), + eq(STATUS_LOCAL_ONLY_CONNECTION_FAILURE_USER_REJECT)); // Verify we did not attempt to trigger a connection. verifyNoMoreInteractions(mClientModeManager, mWifiConfigManager); @@ -4047,7 +4065,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { private void validateScanSettings(@Nullable String hiddenSsid, int[] channels) { ScanSettings scanSettings = mScanSettingsArgumentCaptor.getValue(); assertNotNull(scanSettings); - assertEquals(WifiScanner.WIFI_BAND_ALL, scanSettings.band); + assertEquals(WifiScanner.WIFI_BAND_UNSPECIFIED, scanSettings.band); assertEquals(WifiScanner.SCAN_TYPE_HIGH_ACCURACY, scanSettings.type); assertEquals(WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, scanSettings.reportEvents); if (hiddenSsid == null) { diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java index d5e102383b..e966f51f9a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java @@ -28,6 +28,7 @@ import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_SAE; import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_WEP; import static com.android.server.wifi.WifiNetworkSelector.experimentIdFromIdentifier; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -72,6 +73,7 @@ import org.mockito.Spy; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -157,6 +159,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiGlobals.getWifiLowConnectedScoreThresholdToTriggerScanForMbb()).thenReturn( ConnectedScore.WIFI_TRANSITION_SCORE); + when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet()); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mClientModeManager); if (WifiNetworkSelector.PRESET_CANDIDATE_SCORER_NAME.equals( mThroughputScorer.getIdentifier())) { @@ -555,7 +558,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); @@ -589,7 +592,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); assertTrue(mWifiNetworkSelector.getConnectableScanDetails().isEmpty()); @@ -626,7 +629,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertNotNull(candidate); @@ -638,7 +641,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); assertNull("Expect null configuration", candidate); @@ -680,7 +683,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate); @@ -692,7 +695,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); @@ -732,7 +735,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); when(mWifiInfo.getNetworkId()).thenReturn(0); @@ -750,7 +753,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); @@ -792,7 +795,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); when(mWifiInfo.getNetworkId()).thenReturn(0); @@ -818,7 +821,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); @@ -854,7 +857,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(0); @@ -895,7 +898,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics).incrementNetworkSelectionFilteredBssidCount(1); assertEquals("Expect null configuration", null, candidate); @@ -935,7 +938,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } @@ -973,7 +976,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } @@ -1013,7 +1016,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } @@ -1056,7 +1059,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } @@ -1105,7 +1108,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); } @@ -1139,7 +1142,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } @@ -1174,12 +1177,47 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect null configuration", null, candidate); } /** + * Autojoin restricted security type network is filtered out for network selection. + * + * ClientModeImpl is disconnected. + * scanDetails contains a network which is Autojoin restricted security type. + * + * Expected behavior: no network recommended by Network Selector + */ + @Test + public void filterOutAutojoinRestrictionSecurityTypeBssid() { + String[] ssids = {"\"test1\""}; + String[] bssids = {"6c:f3:7f:ae:8c:f3"}; + int[] freqs = {5180}; + String[] caps = {"[WEP][ESS]"}; + int[] levels = {mThresholdQualifiedRssi5G + 8}; + int[] securities = {SECURITY_WEP}; + when(WifiInfo.convertWifiConfigurationSecurityType( + WifiConfiguration.SECURITY_TYPE_WEP)).thenReturn(WifiInfo.SECURITY_TYPE_WEP); + + ScanDetailsAndWifiConfigs scanDetailsAndConfigs = + WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids, + freqs, caps, levels, securities, mWifiConfigManager, mClock); + List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails(); + HashSet<String> blocklist = new HashSet<String>(); + + List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( + scanDetails, blocklist, + Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, + false, ROLE_CLIENT_PRIMARY)), + false, true, true, Collections.emptySet(), false, + (0x1 << WifiInfo.SECURITY_TYPE_WEP)); + WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); + assertNull("Expect null configuration", candidate); + } + + /** * Unsupported security type WPA-Personal should not filter WPA/WPA2 networks. * * ClientModeImpl is disconnected. @@ -1209,7 +1247,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals(ssids[0], candidate.SSID); } @@ -1243,7 +1281,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED); @@ -1269,7 +1307,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); // The second network selection is skipped since current connected network is @@ -1308,7 +1346,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfiguration[] configs = scanDetailsAndConfigs.getWifiConfigs(); @@ -1339,7 +1377,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); assertEquals(100, candidates.get(0).getPredictedThroughputMbps()); } @@ -1379,7 +1417,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); @@ -1405,7 +1443,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics, atLeastOnce()).setNominatorForNetwork(eq(candidate.networkId), @@ -1458,7 +1496,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); @@ -1473,7 +1511,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate); } @@ -1514,7 +1552,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); @@ -1527,7 +1565,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); // Should now select the non user choice network. @@ -1569,7 +1607,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(userChoice, candidate); @@ -1580,7 +1618,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); WifiConfigurationTestUtil.assertConfigurationEqual(networkSelectorChoice, candidate); } @@ -1615,7 +1653,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertFalse(candidates.isEmpty()); for (WifiCandidates.Candidate candidate: candidates) { @@ -1632,7 +1670,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertFalse(candidates.isEmpty()); for (WifiCandidates.Candidate candidate: candidates) { @@ -1682,7 +1720,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); ArgumentCaptor<Integer> nominatorIdCaptor = ArgumentCaptor.forClass(int.class); @@ -1898,7 +1936,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); //WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals(1, candidates.size()); assertTrue(candidates.get(0).getLastSelectionWeight() > 0); @@ -1910,7 +1948,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); //WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals(1, candidates.size()); assertEquals(0, candidates.get(0).getLastSelectionWeight(), 0); @@ -2026,7 +2064,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - true, true, true, Collections.emptySet(), false); + true, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertNotNull("Result should be not null", candidate); WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager, @@ -2068,7 +2106,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, true, false, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - true, true, true, Collections.emptySet(), false); + true, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); // PlaceholderNominator always return the first network in the scan results @@ -2106,7 +2144,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); @@ -2141,7 +2179,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { unSavedScanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertEquals("Expect open unsaved networks", unSavedScanDetails, @@ -2156,7 +2194,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { savedScanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); candidate = mWifiNetworkSelector.selectNetwork(candidates); // Saved networks are filtered out. assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); @@ -2186,7 +2224,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); @@ -2218,7 +2256,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); assertTrue(mWifiNetworkSelector.getFilteredScanDetailsForOpenUnsavedNetworks().isEmpty()); } @@ -2250,7 +2288,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP, mThresholdMinimumRssi2G + RSSI_BUMP}; mPlaceholderNominator.setNominatorToSelectCandidate(false); - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WIFI_FEATURE_OWE)); List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( ssids, bssids, freqs, caps, levels, mClock); @@ -2260,7 +2299,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); @@ -2286,7 +2325,10 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { int[] levels = {mThresholdMinimumRssi2G, mThresholdMinimumRssi5G + RSSI_BUMP, mThresholdMinimumRssi2G + RSSI_BUMP}; mPlaceholderNominator.setNominatorToSelectCandidate(false); - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_OWE); + + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(WIFI_FEATURE_OWE, false); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails( ssids, bssids, freqs, caps, levels, mClock); @@ -2296,7 +2338,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); List<ScanDetail> expectedOpenUnsavedNetworks = new ArrayList<>(); expectedOpenUnsavedNetworks.add(scanDetails.get(1)); @@ -2327,7 +2369,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { EMPTY_BLOCKLIST, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - true, true, true, Collections.emptySet(), false); + true, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mCandidateScorer, atLeastOnce()).scoreCandidates(any()); @@ -2465,7 +2507,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - true, true, true, Collections.emptySet(), false); + true, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); // Check if the wifiConfig is updated with the latest verify(mWifiConfigManager).addOrUpdateNetwork(existingConfig, @@ -2496,7 +2538,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // Expect one privileged and one regular candidate. assertEquals(2, candidates.size()); boolean foundCarrierOrPrivilegedAppCandidate = false; @@ -2546,7 +2588,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); verify(mWifiMetrics, times(1)) .incrementNetworkSelectionFilteredBssidCountDueToMboAssocDisallowInd(); @@ -2673,7 +2715,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { new ClientModeManagerState( TEST_IFACE_NAME_SECONDARY, true, false, mSecondaryWifiInfo, false, ROLE_CLIENT_SECONDARY_LONG_LIVED)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates); ScanResult chosenScanResult = scanDetails.get(0).getScanResult(); @@ -2743,7 +2785,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { // Do network selection. List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan( scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(), - false); + false, 0); assertNull(candidates); // Mock that the primary connection has a user connect choice pointing something @@ -2757,7 +2799,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { primaryConfig); candidates = mWifiNetworkSelector.getCandidatesFromScan( scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(), - false); + false, 0); // Candidate should not be null assertNotNull(candidates); @@ -2766,7 +2808,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { R.bool.config_wifi_framework_enable_associated_network_selection); assertNull(mWifiNetworkSelector.getCandidatesFromScan( scanDetails, blocklist, cmmStates, false, true, true, Collections.emptySet(), - false)); + false, 0)); } private void runNetworkSelectionWith(ScanDetailsAndWifiConfigs scanDetailsAndConfigs) { @@ -2778,7 +2820,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { true, // untrustedNetworkAllowed true, // oemPaid true, // oemPrivate - Collections.emptySet(), false); + Collections.emptySet(), false, 0); WifiConfiguration wifiConfiguration = mWifiNetworkSelector.selectNetwork(candidates); assertNotNull(wifiConfiguration); } @@ -2817,7 +2859,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testSaeAutoUpgradeWithPskNetworkWhenAutoUpgradeEnabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); @@ -2834,7 +2877,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that SAE network is selected if offload is supported. @@ -2872,7 +2915,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testSaeAutoUpgradeWithPskNetworkWhenPskTypeIsDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); @@ -2890,7 +2934,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // PSK type is disabled, PSK network is not matched. assertEquals(1, candidates.size()); @@ -2907,7 +2951,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testSaeNoAutoUpgradeWithPskNetworkWhenAutoUpgradeDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(false); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(false); @@ -2924,7 +2969,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that PSK network is selected. @@ -2940,7 +2985,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testSaeNoAutoUpgradeWithPskNetworkWhenSaeNotSupported() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(0L); + when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet()); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); @@ -2957,7 +3002,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // The SAE-only network should be filtered. assertEquals(1, candidates.size()); @@ -2976,7 +3021,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweAutoUpgradeWithOpenNetworkWhenAutoUpgradeEnabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -2992,7 +3038,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that OWE network is selected (assume offload is not supported.). @@ -3018,7 +3064,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweAutoUpgradeWithOpenNetworkWhenOpenTypeIsDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -3036,7 +3083,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // OPEN type is disabled, OPEN network is not matched. assertEquals(1, candidates.size()); @@ -3053,7 +3100,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweNoAutoUpgradeWithOpenNetworkWhenAutoUpgradeDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(false); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -3069,7 +3117,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that OPEN network is selected. @@ -3085,7 +3133,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweNoAutoUpgradeWithOweNetworkWhenOweNotSupported() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(0L); + when(mClientModeManager.getSupportedFeatures()).thenReturn(new BitSet()); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -3102,7 +3150,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // The OWE-only network should be filtered. assertEquals(1, candidates.size()); @@ -3135,7 +3183,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that WPA2 Enterprise network is selected (assume offload is not supported.). @@ -3179,7 +3227,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); // WPA2 Enterprise type is disabled, WPA2 Enterprise network is not matched. assertEquals(1, candidates.size()); @@ -3194,7 +3242,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScan() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); setupMultiConfigAndSingleScanAndVerify("[RSN-SAE-CCMP][ESS][MFPR]", SECURITY_PSK | SECURITY_SAE, WifiConfiguration.SECURITY_TYPE_SAE); @@ -3202,14 +3251,17 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScanNegative() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_WPA3_SAE); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(WIFI_FEATURE_WPA3_SAE, false); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); setupMultiConfigAndSingleScanAndVerify("[RSN-SAE-CCMP][ESS][MFPR]", SECURITY_PSK | SECURITY_SAE, -1); } @Test public void verifySecurityParamsSelectionForOpenOweConfigAndOweScan() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn( + createCapabilityBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]", SECURITY_NONE | SECURITY_OWE, WifiConfiguration.SECURITY_TYPE_OWE); @@ -3217,7 +3269,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForOpenOweConfigAndOweScanNegative() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_OWE); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(WIFI_FEATURE_OWE, false); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]", SECURITY_NONE | SECURITY_OWE, -1); } @@ -3251,7 +3305,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertNotNull(candidates); if (expectedSecurityParamType == -1) { assertEquals(0, candidates.size()); @@ -3271,7 +3325,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testPskWithPskOnlyForPskSaeTransitionNetworks() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); @@ -3290,7 +3345,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, new HashSet<>(), Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); assertEquals(2, candidates.size()); // Verify that PSK network is still selected if offload is not supported @@ -3308,7 +3363,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testNetworkSelectionForUserSelectedNetwork() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(createCapabilityBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); ScanDetailsAndWifiConfigs scanDetailsAndConfigs = setupAutoUpgradeNetworks( @@ -3398,7 +3454,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { scanDetails, blocklist, Arrays.asList(new ClientModeManagerState(TEST_IFACE_NAME, false, true, mWifiInfo, false, ROLE_CLIENT_PRIMARY)), - false, true, true, Collections.emptySet(), false); + false, true, true, Collections.emptySet(), false, 0); return candidates; } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java index 59e62ca16b..77c98097e9 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTestUtil.java @@ -46,6 +46,7 @@ import com.android.server.wifi.util.InformationElementUtil; import com.android.server.wifi.util.NativeUtil; import java.util.ArrayList; +import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -57,7 +58,7 @@ import java.util.Set; */ public class WifiNetworkSelectorTestUtil { private static final String TAG = "WifiNetworkSelectorTestUtil"; - private static final long SUPPORTED_FEATURES_ALL = Long.MAX_VALUE; + /** * A class that holds a list of scanDetail and their associated WifiConfiguration. */ @@ -273,6 +274,9 @@ public class WifiNetworkSelectorTestUtil { throw new IllegalArgumentException(); } + BitSet supportedFeaturesAll = new BitSet(); + supportedFeaturesAll.set(0, 63); // mark all features as supported + Map<String, Integer> netIdMap = new HashMap<>(); int netId = 0; @@ -292,7 +296,7 @@ public class WifiNetworkSelectorTestUtil { || (securities[index] & SECURITY_WAPI_PSK) != 0) { configs[index].preSharedKey = "\"PA55W0RD\""; // needed to validate with PSK } - if (!WifiConfigurationUtil.validate(configs[index], SUPPORTED_FEATURES_ALL, true)) { + if (!WifiConfigurationUtil.validate(configs[index], supportedFeaturesAll, true)) { throw new IllegalArgumentException("Invalid generated config: " + configs[index]); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index 131f7de508..00aa72a519 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -31,6 +31,7 @@ import static com.android.server.wifi.WifiNetworkSuggestionsManager.DEFAULT_LING import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_ALLOWED_APP_INTENT_ACTION; import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISALLOWED_APP_INTENT_ACTION; import static com.android.server.wifi.WifiNetworkSuggestionsManager.NOTIFICATION_USER_DISMISSED_INTENT_ACTION; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -89,6 +90,7 @@ import android.os.UserHandle; import android.os.test.TestLooper; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.LocalLog; import android.view.LayoutInflater; @@ -156,7 +158,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { private static final String TEST_IMSI = "123456*"; private static final int DEFAULT_PRIORITY_GROUP = 0; private static final int TEST_PRIORITY_GROUP = 1; - private static final String TEST_ANONYMOUS_IDENTITY = "AnonymousIdentity"; + private static final String TEST_ANONYMOUS_IDENTITY_1 = "AnonymousIdentity1"; + private static final String TEST_ANONYMOUS_IDENTITY_2 = "AnonymousIdentity2"; private static final String USER_CONNECT_CHOICE = "SomeNetworkProfileId"; private static final int TEST_RSSI = -50; private static final ParcelUuid GROUP_UUID = ParcelUuid @@ -263,7 +266,8 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { .thenReturn(true); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE); + createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mSsidTranslator.getAllPossibleOriginalSsids(any())).thenAnswer( @@ -750,7 +754,7 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { config.ephemeral = true; config.creatorName = TEST_PACKAGE_1; config.creatorUid = TEST_UID_1; - config.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY); + config.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_1); WifiConfigManager.OnNetworkUpdateListener listener = mNetworkListenerCaptor.getValue(); listener.onConnectChoiceSet(List.of(config), USER_CONNECT_CHOICE, TEST_RSSI); mWifiNetworkSuggestionsManager.setAnonymousIdentity(config); @@ -786,7 +790,7 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { // As user changes the auto-join, will keep the user choice. assertFalse(matchedSuggestion.isAutojoinEnabled); // Verify user connect choice and Anonymous Identity are preserved during the modify. - assertEquals(TEST_ANONYMOUS_IDENTITY, matchedSuggestion.anonymousIdentity); + assertEquals(TEST_ANONYMOUS_IDENTITY_1, matchedSuggestion.anonymousIdentity); assertEquals(USER_CONNECT_CHOICE, matchedSuggestion.connectChoice); assertEquals(TEST_RSSI, matchedSuggestion.connectChoiceRssi); @@ -4722,7 +4726,7 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { .thenReturn(true); WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createWpa2Wpa3EnterpriseNetwork( WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); - eapSimConfig.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY); + eapSimConfig.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_1); WifiNetworkSuggestion networkSuggestion = createWifiNetworkSuggestion( new WifiConfiguration(eapSimConfig), null, false, false, true, true, DEFAULT_PRIORITY_GROUP); @@ -4738,25 +4742,26 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { configuration.ephemeral = true; configuration.creatorName = TEST_PACKAGE_1; configuration.creatorUid = TEST_UID_1; - configuration.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY); + configuration.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_1); Set<ExtendedWifiNetworkSuggestion> matchedSuggestions = mWifiNetworkSuggestionsManager .getNetworkSuggestionsForWifiConfiguration(configuration, TEST_BSSID); for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { assertNull(ewns.anonymousIdentity); - assertEquals(TEST_ANONYMOUS_IDENTITY, + assertEquals(TEST_ANONYMOUS_IDENTITY_1, ewns.createInternalWifiConfiguration(mWifiCarrierInfoManager) .enterpriseConfig.getAnonymousIdentity()); } + configuration.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_2); mWifiNetworkSuggestionsManager.setAnonymousIdentity(configuration); matchedSuggestions = mWifiNetworkSuggestionsManager .getNetworkSuggestionsForWifiConfiguration(configuration, TEST_BSSID); for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { - assertEquals(TEST_ANONYMOUS_IDENTITY, ewns.anonymousIdentity); + assertEquals(TEST_ANONYMOUS_IDENTITY_2, ewns.anonymousIdentity); } // Reset SIM network suggestion, Anonymous Identity should gone. @@ -4766,7 +4771,7 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { TEST_BSSID); for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { assertEquals(null, ewns.anonymousIdentity); - assertEquals(TEST_ANONYMOUS_IDENTITY, + assertEquals(TEST_ANONYMOUS_IDENTITY_1, ewns.createInternalWifiConfiguration(mWifiCarrierInfoManager) .enterpriseConfig.getAnonymousIdentity()); } @@ -4774,6 +4779,68 @@ public class WifiNetworkSuggestionsManagerTest extends WifiBaseTest { } @Test + public void testSetAnonymousIdentityNullOnSuggestionNetwork() { + when(mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(TEST_UID_1)) + .thenReturn(true); + WifiConfiguration eapSimConfig = WifiConfigurationTestUtil.createWpa2Wpa3EnterpriseNetwork( + WifiEnterpriseConfig.Eap.SIM, WifiEnterpriseConfig.Phase2.NONE); + eapSimConfig.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_1); + WifiNetworkSuggestion networkSuggestion = createWifiNetworkSuggestion( + new WifiConfiguration(eapSimConfig), null, false, false, true, true, + DEFAULT_PRIORITY_GROUP); + List<WifiNetworkSuggestion> networkSuggestionList = List.of(networkSuggestion); + assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, + mWifiNetworkSuggestionsManager.add(networkSuggestionList, TEST_UID_1, + TEST_PACKAGE_1, TEST_FEATURE)); + WifiConfiguration configuration = + new WifiConfiguration(eapSimConfig); + configuration.fromWifiNetworkSuggestion = true; + configuration.shared = false; + configuration.ephemeral = true; + configuration.creatorName = TEST_PACKAGE_1; + configuration.creatorUid = TEST_UID_1; + configuration.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_1); + + Set<ExtendedWifiNetworkSuggestion> matchedSuggestions = mWifiNetworkSuggestionsManager + .getNetworkSuggestionsForWifiConfiguration(configuration, + TEST_BSSID); + for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { + assertNull(ewns.anonymousIdentity); + assertEquals(TEST_ANONYMOUS_IDENTITY_1, + ewns.createInternalWifiConfiguration(mWifiCarrierInfoManager) + .enterpriseConfig.getAnonymousIdentity()); + } + + configuration.enterpriseConfig.setAnonymousIdentity(TEST_ANONYMOUS_IDENTITY_2); + mWifiNetworkSuggestionsManager.setAnonymousIdentity(configuration); + + matchedSuggestions = mWifiNetworkSuggestionsManager + .getNetworkSuggestionsForWifiConfiguration(configuration, + TEST_BSSID); + for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { + assertEquals(TEST_ANONYMOUS_IDENTITY_2, ewns.anonymousIdentity); + } + + when(mWifiConfigManager.getConfiguredNetwork(anyString())).thenReturn(configuration); + when(mWifiConfigManager.addOrUpdateNetwork(any(), eq(TEST_UID_1), eq(TEST_PACKAGE_1), + eq(false))).thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); + configuration.enterpriseConfig.setAnonymousIdentity(null); + mWifiNetworkSuggestionsManager.setAnonymousIdentity(configuration); + matchedSuggestions = mWifiNetworkSuggestionsManager + .getNetworkSuggestionsForWifiConfiguration(configuration, + TEST_BSSID); + for (ExtendedWifiNetworkSuggestion ewns : matchedSuggestions) { + assertTrue(TextUtils.isEmpty(ewns.anonymousIdentity)); + assertEquals(TEST_ANONYMOUS_IDENTITY_1, + ewns.createInternalWifiConfiguration(mWifiCarrierInfoManager) + .enterpriseConfig.getAnonymousIdentity()); + } + verify(mWifiConfigManager).addOrUpdateNetwork(any(), eq(TEST_UID_1), eq(TEST_PACKAGE_1), + eq(false)); + verify(mWifiConfigManager, times(3)).saveToStore(); + } + + @Test public void testSetUserConnectChoice() { WifiConfigManager.OnNetworkUpdateListener listener = mNetworkListenerCaptor.getValue(); WifiConfiguration config = WifiConfigurationTestUtil.createOpenOweNetwork(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java index adaddf5bb3..276bbcaf8b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiPulledAtomLoggerTest.java @@ -184,12 +184,13 @@ public class WifiPulledAtomLoggerTest extends WifiBaseTest { when(mWifiInjector.getWakeupController()).thenReturn(mock(WakeupController.class)); when(mWifiInjector.getOpenNetworkNotifier()).thenReturn(mock(OpenNetworkNotifier.class)); when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mock(WifiPermissionsUtil.class)); + when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mock(DeviceConfigFacade.class)); - // Verify that all 8 settings were retrieved. + // Verify that all settings were retrieved. List<StatsEvent> data = new ArrayList<>(); assertEquals(StatsManager.PULL_SUCCESS, mPullAtomCallbackArgumentCaptor.getValue() .onPullAtom(WifiStatsLog.WIFI_SETTING_INFO, data)); - assertEquals(8, data.size()); + assertEquals(9, data.size()); } @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiRoamingConfigStoreTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiRoamingConfigStoreTest.java index bba85549bc..000cb52693 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiRoamingConfigStoreTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiRoamingConfigStoreTest.java @@ -18,7 +18,6 @@ package com.android.server.wifi; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; @@ -30,7 +29,6 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; -import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.util.XmlUtil; import org.junit.After; @@ -78,7 +76,6 @@ public class WifiRoamingConfigStoreTest extends WifiBaseTest { @Test public void testRoamingModeByDeviceAdmin() { - assumeTrue(SdkLevel.isAtLeastV()); assertTrue(mWifiRoamingConfigStore.getRoamingMode(TEST_SSID) == TEST_DEFAULT_ROAMING_MODE); mWifiRoamingConfigStore.addRoamingMode(TEST_SSID, TEST_ROAMING_MODE, true); assertTrue(mWifiRoamingConfigStore.getRoamingMode(TEST_SSID) == TEST_ROAMING_MODE); @@ -95,7 +92,6 @@ public class WifiRoamingConfigStoreTest extends WifiBaseTest { @Test public void testRoamingModeByNonAdmin() { - assumeTrue(SdkLevel.isAtLeastV()); assertTrue(mWifiRoamingConfigStore.getRoamingMode(TEST_SSID) == TEST_DEFAULT_ROAMING_MODE); mWifiRoamingConfigStore.addRoamingMode(TEST_SSID, TEST_ROAMING_MODE, false); assertTrue(mWifiRoamingConfigStore.getRoamingMode(TEST_SSID) == TEST_ROAMING_MODE); @@ -112,7 +108,6 @@ public class WifiRoamingConfigStoreTest extends WifiBaseTest { @Test public void testSaveAndLoadFromStore() throws Exception { - assumeTrue(SdkLevel.isAtLeastV()); ArgumentCaptor<WifiConfigStore.StoreData> storeDataCaptor = ArgumentCaptor.forClass( WifiConfigStore.StoreData.class); verify(mWifiConfigStore).registerStoreData(storeDataCaptor.capture()); @@ -140,7 +135,6 @@ public class WifiRoamingConfigStoreTest extends WifiBaseTest { private XmlPullParser createRoamingPolicyTestXmlForParsing(String ssid, Integer roamingMode, boolean isDeviceOwner) throws Exception { - assumeTrue(SdkLevel.isAtLeastV()); Map<String, Integer> roamingPolicies = new ArrayMap<>(); // Serialize roamingPolicies.put(ssid, roamingMode); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java index 4f5aaf7e21..1459a43717 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java @@ -40,6 +40,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.MacAddress; import android.net.Network; @@ -61,6 +62,7 @@ import android.os.test.TestLooper; import androidx.test.filters.SmallTest; import com.android.modules.utils.build.SdkLevel; +import com.android.server.wifi.proto.WifiStatsLog; import com.android.wifi.resources.R; import org.junit.After; @@ -112,6 +114,8 @@ public class WifiScoreReportTest extends WifiBaseTest { public static final boolean TEST_USER_SELECTED = true; public static final int TEST_NETWORK_SWITCH_DIALOG_DISABLED_MS = 300_000; private static final int TEST_UID = 435546654; + private static final String EXTERNAL_SCORER_PKG_NAME = "com.google.android.carrier.carrierwifi"; + private static final String DRY_RUN_SCORER_PKG_NAME = "com.example.xxx"; FakeClock mClock; WifiScoreReport mWifiScoreReport; @@ -120,6 +124,7 @@ public class WifiScoreReportTest extends WifiBaseTest { @Mock WifiNetworkAgent mNetworkAgent; WifiThreadRunner mWifiThreadRunner; @Mock Context mContext; + @Mock PackageManager mMockPackageManager; @Mock Resources mResources; @Mock WifiMetrics mWifiMetrics; @Mock PrintWriter mPrintWriter; @@ -245,6 +250,10 @@ public class WifiScoreReportTest extends WifiBaseTest { when(mResources.getInteger( R.integer.config_wifiNetworkSwitchDialogDisabledMsWhenMarkedUsable)) .thenReturn(TEST_NETWORK_SWITCH_DIALOG_DISABLED_MS); + when(mContext.getPackageManager()).thenReturn(mMockPackageManager); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{EXTERNAL_SCORER_PKG_NAME}); + when(mDeviceConfigFacade.getDryRunScorerPkgName()).thenReturn(DRY_RUN_SCORER_PKG_NAME); when(mNetwork.getNetId()).thenReturn(0); when(mNetworkAgent.getNetwork()).thenReturn(mNetwork); when(mNetworkAgent.getCurrentNetworkCapabilities()).thenReturn( @@ -347,10 +356,18 @@ public class WifiScoreReportTest extends WifiBaseTest { verifySentAnyNetworkScore(); mWifiInfo.setRssi(-77); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); mWifiScoreReport.calculateAndReportScore(); // called again after calculateAndReportScore() verifySentAnyNetworkScore(times(2)); verify(mWifiMetrics).incrementWifiScoreCount(eq(TEST_IFACE_NAME), anyInt()); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); } @Test @@ -417,7 +434,7 @@ public class WifiScoreReportTest extends WifiBaseTest { { NetworkScore networkScore = networkScoreCaptor.getValue(); assertEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); - assertFalse(networkScore.isExiting()); + assertTrue(networkScore.isExiting()); assertFalse(networkScore.isTransportPrimary()); assertEquals(NetworkScore.KEEP_CONNECTED_NONE, networkScore.getKeepConnectedReason()); } @@ -473,7 +490,7 @@ public class WifiScoreReportTest extends WifiBaseTest { { NetworkScore networkScore = networkScoreCaptor.getValue(); assertEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); - assertFalse(networkScore.isExiting()); + assertTrue(networkScore.isExiting()); assertFalse(networkScore.isTransportPrimary()); } // upon lingering, send session end to client. @@ -962,19 +979,28 @@ public class WifiScoreReportTest extends WifiBaseTest { mWifiScoreReport.enableVerboseLogging(true); mWifiInfo.setFrequency(5220); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); // Reduce RSSI value to fall below the transition score for (int rssi = -60; rssi >= -83; rssi -= 1) { mWifiInfo.setRssi(rssi); mWifiScoreReport.calculateAndReportScore(); } assertTrue(mWifiInfo.getScore() < getTransitionScore()); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNUSABLE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); // Then, set high RSSI value to exceed the transition score mWifiInfo.setRssi(-50); // Reset the internal timer so that no need to wait for 9 seconds mWifiScoreReport.reset(); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); + mWifiScoreReport.calculateAndReportScore(); assertTrue(mWifiInfo.getScore() > getTransitionScore()); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + mWifiScoreReport.getAospScorerPredictionStatusForEvaluation()); } /** @@ -1187,6 +1213,120 @@ public class WifiScoreReportTest extends WifiBaseTest { } } + @Test + public void frameworkIgnoreTriggerUpdateOfWifiUsabilityStatsForDryRunScorer() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{DRY_RUN_SCORER_PKG_NAME}); + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + // Register Client for verification. + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl, TEST_UID); + verify(mExternalScoreUpdateObserverProxy).registerCallback( + mExternalScoreUpdateObserverCbCaptor.capture()); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + //mClock.mStepMillis = 0; + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + + //mClock.mWallClockMillis = 5001; + mExternalScoreUpdateObserverCbCaptor.getValue() + .triggerUpdateOfWifiUsabilityStats(scorerImpl.mSessionId); + mLooper.dispatchAll(); + verify(mWifiNative, never()).getWifiLinkLayerStats(TEST_IFACE_NAME); + verify(mWifiNative, never()).signalPoll(TEST_IFACE_NAME); + } + + /** + * Verify that WifiScoreReport gets updated score when notifyScoreUpdate() is called by apps. + */ + @Test + public void frameworkIgnoreNotifyScoreUpdateFromDryRunScorer() throws Exception { + assertEquals(ConnectedScore.WIFI_INITIAL_SCORE, mWifiScoreReport.getLegacyIntScore()); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{DRY_RUN_SCORER_PKG_NAME}); + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl, TEST_UID); + verify(mExternalScoreUpdateObserverProxy).registerCallback( + mExternalScoreUpdateObserverCbCaptor.capture()); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + assertEquals(TEST_SESSION_ID, scorerImpl.mSessionId); + + mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( + scorerImpl.mSessionId, ConnectedScore.WIFI_INITIAL_SCORE - 1); + mLooper.dispatchAll(); + + assertEquals(ConnectedScore.WIFI_INITIAL_SCORE, mWifiScoreReport.getLegacyIntScore()); + } + + @Test + public void frameworkIgnoreNotifyStatusUpdateFromDryRunScorer() throws Exception { + assertEquals(ConnectedScore.WIFI_INITIAL_SCORE, mWifiScoreReport.getLegacyIntScore()); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{DRY_RUN_SCORER_PKG_NAME}); + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl, TEST_UID); + verify(mExternalScoreUpdateObserverProxy).registerCallback( + mExternalScoreUpdateObserverCbCaptor.capture()); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + assertEquals(TEST_SESSION_ID, scorerImpl.mSessionId); + + mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( + scorerImpl.mSessionId, true); + mLooper.dispatchAll(); + assertTrue(mWifiInfo.isUsable()); + mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( + scorerImpl.mSessionId, false); + mLooper.dispatchAll(); + assertTrue(mWifiInfo.isUsable()); + } + + /** + * Verify that WifiScoreReport gets NUD request only once when requestNudOperation() is called + * by apps. + */ + @Test + public void frameworkIgnoreRequestNudOperationForDryRunScorer() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{DRY_RUN_SCORER_PKG_NAME}); + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + // Register Client for verification. + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl, TEST_UID); + verify(mExternalScoreUpdateObserverProxy).registerCallback( + mExternalScoreUpdateObserverCbCaptor.capture()); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mClock.mStepMillis = 0; + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + + mClock.mWallClockMillis = 5001; + mExternalScoreUpdateObserverCbCaptor.getValue().requestNudOperation(scorerImpl.mSessionId); + mLooper.dispatchAll(); + assertFalse(mWifiScoreReport.shouldCheckIpLayer()); + assertEquals(0, mWifiScoreReport.getNudYes()); + } + + @Test + public void frameworkIgnoreBlocklistCurrentBssidForDryRunScorer() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + when(mMockPackageManager.getPackagesForUid(anyInt())) + .thenReturn(new String[]{DRY_RUN_SCORER_PKG_NAME}); + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + // Register Client for verification. + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl, TEST_UID); + verify(mExternalScoreUpdateObserverProxy).registerCallback( + mExternalScoreUpdateObserverCbCaptor.capture()); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mClock.mStepMillis = 0; + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + + mClock.mWallClockMillis = 5001; + mExternalScoreUpdateObserverCbCaptor.getValue().requestNudOperation(scorerImpl.mSessionId); + mLooper.dispatchAll(); + verify(mWifiBlocklistMonitor, never()) + .handleBssidConnectionFailure(any(), any(), anyInt(), anyInt()); + } + /** * Verify that WifiScoreReport triggers an update of WifiUsabilityStatsEntry. */ @@ -1721,9 +1861,13 @@ public class WifiScoreReportTest extends WifiBaseTest { when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_NONE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( scorerImpl.mSessionId, true); mLooper.dispatchAll(); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); { ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); @@ -1738,6 +1882,8 @@ public class WifiScoreReportTest extends WifiBaseTest { mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( scorerImpl.mSessionId, false); mLooper.dispatchAll(); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_UNUSABLE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); { ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); @@ -1753,6 +1899,8 @@ public class WifiScoreReportTest extends WifiBaseTest { mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( scorerImpl.mSessionId, true); mLooper.dispatchAll(); + assertEquals(WifiStatsLog.SCORER_PREDICTION_RESULT_REPORTED__WIFI_PREDICTED_USABILITY_STATE__WIFI_USABILITY_PREDICTED_USABLE, + mWifiScoreReport.getExternalScorerPredictionStatusForEvaluation()); verify(mWifiConnectivityManager).disableNetworkSwitchDialog( TEST_NETWORK_SWITCH_DIALOG_DISABLED_MS); } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java index 1e25a458c0..6d6f6f77d1 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -73,6 +73,7 @@ import static com.android.server.wifi.WifiSettingsConfigStore.SHOW_DIALOG_WHEN_T import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_WEP_ALLOWED; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static com.google.common.truth.Truth.assertThat; @@ -103,8 +104,8 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.ignoreStubs; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; @@ -244,9 +245,11 @@ import androidx.test.filters.SmallTest; import com.android.internal.os.PowerProfile; import com.android.modules.utils.ParceledListSlice; +import com.android.modules.utils.StringParceledListSlice; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.WifiServiceImpl.LocalOnlyRequestorCallback; import com.android.server.wifi.WifiServiceImpl.SoftApCallbackInternal; +import com.android.server.wifi.WifiServiceImpl.UwbAdapterStateListener; import com.android.server.wifi.b2b.WifiRoamingModeManager; import com.android.server.wifi.coex.CoexManager; import com.android.server.wifi.entitlement.PseudonymInfo; @@ -283,6 +286,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -505,7 +509,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Captor ArgumentCaptor<Intent> mIntentCaptor; @Captor ArgumentCaptor<List> mListCaptor; @Mock TwtManager mTwtManager; - @Mock WifiResourceCache mWifiResourceCache; + @Mock WifiResourceCache mResourceCache; @Rule // For frameworks @@ -528,8 +532,7 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper = new TestLooper(); mApplicationInfo = new ApplicationInfo(); mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; - when(mResources.getInteger( - eq(R.integer.config_wifiHardwareSoftapMaxClientCount))) + when(mResourceCache.getInteger(R.integer.config_wifiHardwareSoftapMaxClientCount)) .thenReturn(10); WifiInjector.sWifiInjector = mWifiInjector; when(mRequestInfo.getPid()).thenReturn(mPid); @@ -566,7 +569,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mHandlerThread.getThreadHandler()).thenReturn(new Handler(mLooper.getLooper())); when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper()); when(mContext.getResources()).thenReturn(mResources); - when(mContext.getResourceCache()).thenReturn(mWifiResourceCache); + when(mContext.getResourceCache()).thenReturn(mResourceCache); when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo); @@ -676,6 +679,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mWifiInjector.getSarManager()).thenReturn(mSarManager); mClientModeManagers = Arrays.asList(mClientModeManager, mock(ClientModeManager.class)); when(mActiveModeWarden.getClientModeManagers()).thenReturn(mClientModeManagers); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet()); when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager); when(mUserManager.getUserRestrictions()).thenReturn(mBundle); @@ -861,7 +865,7 @@ public class WifiServiceImplTest extends WifiBaseTest { WifiDiagnostics.REPORT_REASON_USER_ACTION); verify(mWifiDiagnostics).dump(any(), any(), any()); verify(mPasspointNetworkNominateHelper).dump(any()); - verify(mWifiResourceCache).dump(any()); + verify(mResourceCache).dump(any()); } @Test @@ -1191,7 +1195,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testSetWifiEnabledDialogForThirdPartyAppsTargetingBelowQSdk() throws Exception { - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_showConfirmationDialogForThirdPartyAppsEnablingWifi)) .thenReturn(true); doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) @@ -1357,7 +1361,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testSetWifiEnabledNoDialogForNonThirdPartyAppsTargetingBelowQSdk() { - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_showConfirmationDialogForThirdPartyAppsEnablingWifi)) .thenReturn(true); doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) @@ -1639,13 +1643,14 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testRegisterSubsystemRestartThrowsSecurityExceptionOnMissingPermissions() { assumeTrue(SdkLevel.isAtLeastS()); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.registerSubsystemRestartCallback(null)); + doThrow(new SecurityException()).when(mContext) .enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), eq("WifiService")); - try { - mWifiServiceImpl.registerSubsystemRestartCallback(mSubsystemRestartCallback); - fail("expected SecurityException"); - } catch (SecurityException expected) { } + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.registerSubsystemRestartCallback(mSubsystemRestartCallback)); } /** @@ -1655,13 +1660,15 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testUnregisterSubsystemRestartThrowsSecurityExceptionOnMissingPermissions() { assumeTrue(SdkLevel.isAtLeastS()); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.unregisterSubsystemRestartCallback(null)); + doThrow(new SecurityException()).when(mContext) .enforceCallingOrSelfPermission(eq(ACCESS_WIFI_STATE), eq("WifiService")); - try { - mWifiServiceImpl.unregisterSubsystemRestartCallback(mSubsystemRestartCallback); - fail("expected SecurityException"); - } catch (SecurityException expected) { } + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.unregisterSubsystemRestartCallback( + mSubsystemRestartCallback)); } @@ -2079,7 +2086,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testSetCoexUnsafeChannelsDefaultAlgorithmDisabled() { assumeTrue(SdkLevel.isAtLeastS()); - when(mResources.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) + when(mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) .thenReturn(false); List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>(); unsafeChannels.addAll(Arrays.asList(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6), @@ -2098,7 +2105,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testSetCoexUnsafeChannelsDefaultAlgorithmEnabled() { assumeTrue(SdkLevel.isAtLeastS()); - when(mResources.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) + when(mResourceCache.getBoolean(R.bool.config_wifiDefaultCoexAlgorithmEnabled)) .thenReturn(true); List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>(); unsafeChannels.add(new CoexUnsafeChannel(WIFI_BAND_24_GHZ, 6)); @@ -2456,7 +2463,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported24gWithOverride() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); assertTrue(mWifiServiceImpl.is24GHzBandSupported()); verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } @@ -2466,7 +2473,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported5gWithOverride() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); assertTrue(mWifiServiceImpl.is5GHzBandSupported()); verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } @@ -2476,7 +2483,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported6gWithOverride() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); assertTrue(mWifiServiceImpl.is6GHzBandSupported()); verify(mActiveModeWarden, never()).isBandSupportedForSta(anyInt()); } @@ -2486,7 +2493,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported24gNoOverrideNoChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_24_GHZ)).thenReturn(false); assertFalse(mWifiServiceImpl.is24GHzBandSupported()); verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); @@ -2497,7 +2504,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported5gNoOverrideNoChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_5_GHZ)).thenReturn(false); assertFalse(mWifiServiceImpl.is5GHzBandSupported()); verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); @@ -2508,7 +2515,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported24gNoOverrideWithChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_24_GHZ)).thenReturn(true); assertTrue(mWifiServiceImpl.is24GHzBandSupported()); verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ); @@ -2519,7 +2526,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported5gNoOverrideWithChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WIFI_BAND_5_GHZ)).thenReturn(true); assertTrue(mWifiServiceImpl.is5GHzBandSupported()); verify(mActiveModeWarden).isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ); @@ -2530,7 +2537,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported6gNoOverrideNoChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn( false); assertFalse(mWifiServiceImpl.is6GHzBandSupported()); @@ -2542,7 +2549,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testIsWifiBandSupported6gNoOverrideWithChannels() throws Exception { - when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)).thenReturn( true); assertTrue(mWifiServiceImpl.is6GHzBandSupported()); @@ -2550,56 +2557,56 @@ public class WifiServiceImplTest extends WifiBaseTest { } private void setup24GhzSupported() { - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true); } private void setup24GhzUnsupported(boolean isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ)) .thenReturn(false); } } private void setup5GhzSupported() { - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(true); } private void setup5GhzUnsupported(boolean isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap5ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ)) .thenReturn(false); } } private void setup6GhzSupported() { - when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(true); } private void setup6GhzUnsupported(boolean isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi6ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)) .thenReturn(false); } } private void setup60GhzSupported() { - when(mResources.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(true); - when(mResources.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(true); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(true); } private void setup60GhzUnsupported(boolean isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap60ghzSupported)).thenReturn(false); if (!isOnlyUnsupportedSoftAp) { - when(mResources.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifi60ghzSupport)).thenReturn(false); when(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_60_GHZ)) .thenReturn(false); } @@ -3467,7 +3474,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, null, packageName, featureId); + new ParceledListSlice<>(matchingSuggestions), + new ParceledListSlice<>(null), packageName, featureId); mLooper.stopAutoDispatchAndIgnoreExceptions(); ScanTestUtil.assertScanResultsEquals(scanResults, @@ -3498,7 +3506,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, scanResultList, packageName, featureId); + new ParceledListSlice<>(matchingSuggestions), + new ParceledListSlice<>(scanResultList), packageName, featureId); mLooper.stopAutoDispatchAndIgnoreExceptions(); ScanTestUtil.assertScanResultsEquals(scanResults, @@ -3532,7 +3541,7 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); Map<WifiNetworkSuggestion, List<ScanResult>> retrievedScanResults = mWifiServiceImpl.getMatchingScanResults( - matchingSuggestions, null, packageName, featureId); + new ParceledListSlice<>(matchingSuggestions), null, packageName, featureId); mLooper.stopAutoDispatchAndIgnoreExceptions(); assertTrue(retrievedScanResults.isEmpty()); @@ -4846,7 +4855,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test(expected = SecurityException.class) public void testGetAllMatchingPasspointProfilesForScanResultsWithoutPermissions() { - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>()); + mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults( + new ParceledListSlice<>(Collections.emptyList())); } /** @@ -4859,7 +4869,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mLooper.startAutoDispatch(); - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(createScanResultList()); + mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults( + new ParceledListSlice<>(createScanResultList())); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mPasspointManager).getAllMatchingPasspointProfilesForScanResults(any()); } @@ -4874,7 +4885,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mLooper.startAutoDispatch(); - mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults(new ArrayList<>()); + mWifiServiceImpl.getAllMatchingPasspointProfilesForScanResults( + new ParceledListSlice<>(Collections.emptyList())); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mPasspointManager, never()).getAllMatchingPasspointProfilesForScanResults(any()); } @@ -4886,7 +4898,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test(expected = SecurityException.class) public void testGetWifiConfigsForPasspointProfilesWithoutPermissions() { - mWifiServiceImpl.getWifiConfigsForPasspointProfiles(new ArrayList<>()); + mWifiServiceImpl.getWifiConfigsForPasspointProfiles( + new StringParceledListSlice(Collections.emptyList())); } /** @@ -4896,7 +4909,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test(expected = SecurityException.class) public void testGetMatchingOsuProvidersWithoutPermissions() { - mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>()); + mWifiServiceImpl.getMatchingOsuProviders(new ParceledListSlice<>(Collections.emptyList())); } /** @@ -4909,7 +4922,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mLooper.startAutoDispatch(); - mWifiServiceImpl.getMatchingOsuProviders(createScanResultList()); + mWifiServiceImpl.getMatchingOsuProviders(new ParceledListSlice<>(createScanResultList())); mLooper.stopAutoDispatch(); verify(mPasspointManager).getMatchingOsuProviders(any()); } @@ -4922,7 +4935,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testGetMatchingOsuProvidersWithInvalidScanResult() { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.getMatchingOsuProviders(new ArrayList<>()); + mWifiServiceImpl.getMatchingOsuProviders(new ParceledListSlice<>(Collections.emptyList())); mLooper.dispatchAll(); verify(mPasspointManager, never()).getMatchingOsuProviders(any()); } @@ -4934,7 +4947,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test(expected = SecurityException.class) public void testGetMatchingPasspointConfigsForOsuProvidersWithoutPermissions() { - mWifiServiceImpl.getMatchingPasspointConfigsForOsuProviders(new ArrayList<>()); + mWifiServiceImpl.getMatchingPasspointConfigsForOsuProviders( + new ParceledListSlice<>(Collections.emptyList())); } /** @@ -5039,14 +5053,15 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) .thenReturn(expectedConfigs); mLooper.startAutoDispatch(); - assertEquals(expectedConfigs, mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE)); + assertEquals(expectedConfigs, + mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE).getList()); mLooper.stopAutoDispatchAndIgnoreExceptions(); reset(mPasspointManager); when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean())) .thenReturn(new ArrayList<PasspointConfiguration>()); mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE).isEmpty()); + assertTrue(mWifiServiceImpl.getPasspointConfigurations(TEST_PACKAGE).getList().isEmpty()); mLooper.stopAutoDispatchAndIgnoreExceptions(); } @@ -5099,7 +5114,7 @@ public class WifiServiceImplTest extends WifiBaseTest { private void testRestoreNetworkConfiguration(int configNum, int batchNum, boolean allowOverride) { List<WifiConfiguration> configurations = new ArrayList<>(); - when(mResources.getInteger( + when(mResourceCache.getInteger( eq(R.integer.config_wifiConfigurationRestoreNetworksBatchNum))) .thenReturn(batchNum); WifiConfiguration config = new WifiConfiguration(); @@ -6846,6 +6861,31 @@ public class WifiServiceImplTest extends WifiBaseTest { } /** + * Verify that add or update networks is allowed for apps targeting below Q SDK. + */ + @Test + public void testAddOrUpdateNetworkWithBssidAllowListIsNotAllowedForAppsNotPrivileged() + throws Exception { + doReturn(AppOpsManager.MODE_ALLOWED).when(mAppOpsManager) + .noteOp(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, Process.myUid(), TEST_PACKAGE_NAME); + when(mWifiConfigManager.addOrUpdateNetwork(any(), anyInt(), any(), eq(false))).thenReturn( + new NetworkUpdateResult(0)); + when(mWifiPermissionsUtil.isTargetSdkLessThan(anyString(), + eq(Build.VERSION_CODES.Q), anyInt())).thenReturn(true); + + WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); + config.setBssidAllowlist(Collections.emptyList()); + mLooper.startAutoDispatch(); + assertEquals(-1, + mWifiServiceImpl.addOrUpdateNetwork(config, TEST_PACKAGE_NAME, mAttribution)); + mLooper.stopAutoDispatchAndIgnoreExceptions(); + + verifyCheckChangePermission(TEST_PACKAGE_NAME); + verify(mWifiConfigManager, never()).addOrUpdateNetwork(any(), anyInt(), any(), eq(false)); + verify(mWifiMetrics, never()).incrementNumAddOrUpdateNetworkCalls(); + } + + /** * Verify that add or update networks is not allowed for apps targeting below Q SDK * when DISALLOW_ADD_WIFI_CONFIG user restriction is set. */ @@ -7278,8 +7318,8 @@ public class WifiServiceImplTest extends WifiBaseTest { nullable(String.class))).thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); when(mWifiNetworkSuggestionsManager.add(any(), anyInt(), anyString(), @@ -7287,8 +7327,8 @@ public class WifiServiceImplTest extends WifiBaseTest { WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE); mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, times(2)).add( @@ -7311,8 +7351,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager).add( @@ -7335,8 +7375,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager).add( @@ -7358,8 +7398,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager).add( @@ -7381,8 +7421,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager).add( @@ -7403,8 +7443,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_RESTRICTED_BY_ADMIN, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, never()).add(any(), eq(Binder.getCallingUid()), @@ -7421,8 +7461,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiServiceImpl.addNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - TEST_FEATURE_ID)); + mWifiServiceImpl.addNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, TEST_FEATURE_ID)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, never()).add(any(), eq(Binder.getCallingUid()), @@ -7439,8 +7479,8 @@ public class WifiServiceImplTest extends WifiBaseTest { .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID); mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - ACTION_REMOVE_SUGGESTION_DISCONNECT)); + mWifiServiceImpl.removeNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, ACTION_REMOVE_SUGGESTION_DISCONNECT)); mLooper.stopAutoDispatchAndIgnoreExceptions(); when(mWifiNetworkSuggestionsManager.remove(any(), anyInt(), anyString(), @@ -7448,8 +7488,8 @@ public class WifiServiceImplTest extends WifiBaseTest { .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS); mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - ACTION_REMOVE_SUGGESTION_DISCONNECT)); + mWifiServiceImpl.removeNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, ACTION_REMOVE_SUGGESTION_DISCONNECT)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, times(2)).remove(any(), anyInt(), @@ -7466,8 +7506,8 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, - ACTION_REMOVE_SUGGESTION_DISCONNECT)); + mWifiServiceImpl.removeNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, ACTION_REMOVE_SUGGESTION_DISCONNECT)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, never()).remove(any(), anyInt(), @@ -7482,7 +7522,8 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testRemoveNetworkSuggestionsFailureWithInvalidAction() { mLooper.startAutoDispatch(); assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID, - mWifiServiceImpl.removeNetworkSuggestions(mock(List.class), TEST_PACKAGE_NAME, 0)); + mWifiServiceImpl.removeNetworkSuggestions(mock(ParceledListSlice.class), + TEST_PACKAGE_NAME, 0)); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, never()).remove(any(), anyInt(), eq(TEST_PACKAGE_NAME), anyInt()); @@ -7522,7 +7563,7 @@ public class WifiServiceImplTest extends WifiBaseTest { List<WifiNetworkSuggestion> testList = new ArrayList<>(); when(mWifiNetworkSuggestionsManager.get(anyString(), anyInt())).thenReturn(testList); mLooper.startAutoDispatch(); - assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME)); + assertEquals(testList, mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).getList()); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager).get(eq(TEST_PACKAGE_NAME), anyInt()); @@ -7537,7 +7578,7 @@ public class WifiServiceImplTest extends WifiBaseTest { mWifiServiceImpl = makeWifiServiceImplWithMockRunnerWhichTimesOut(); mLooper.startAutoDispatch(); - assertTrue(mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).isEmpty()); + assertTrue(mWifiServiceImpl.getNetworkSuggestions(TEST_PACKAGE_NAME).getList().isEmpty()); mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWifiNetworkSuggestionsManager, never()).get(eq(TEST_PACKAGE_NAME), anyInt()); @@ -7551,7 +7592,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testDisableEphemeralNetworkWithNetworkSettingsPerm() throws Exception { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); - mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME); + mWifiServiceImpl.disableEphemeralNetwork("", TEST_PACKAGE_NAME); mLooper.dispatchAll(); verify(mWifiConfigManager).userTemporarilyDisabledNetwork(anyString(), anyInt()); } @@ -7564,7 +7605,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testDisableEphemeralNetworkWithoutNetworkSettingsPerm() throws Exception { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_DENIED); - mWifiServiceImpl.disableEphemeralNetwork(new String(), TEST_PACKAGE_NAME); + mWifiServiceImpl.disableEphemeralNetwork("", TEST_PACKAGE_NAME); mLooper.dispatchAll(); verify(mWifiConfigManager, never()).userTemporarilyDisabledNetwork(anyString(), anyInt()); } @@ -8395,7 +8436,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mWifiSettingsConfigStore.get( eq(SHOW_DIALOG_WHEN_THIRD_PARTY_APPS_ENABLE_WIFI_SET_BY_API))) .thenReturn(false); - when(mResources.getBoolean( + when(mResourceCache.getBoolean( R.bool.config_showConfirmationDialogForThirdPartyAppsEnablingWifi)) .thenReturn(false); assertFalse(mWifiServiceImpl.isThirdPartyAppEnablingWifiConfirmationDialogEnabled()); @@ -8528,7 +8569,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testSetSsidsDoNotBlocklist_NoPermission() throws Exception { // by default no permissions are given so the call should fail. mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, - Collections.EMPTY_LIST); + new ParceledListSlice<>(Collections.emptyList())); } @Test @@ -8537,14 +8578,15 @@ public class WifiServiceImplTest extends WifiBaseTest { // verify setting an empty list mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, - Collections.EMPTY_LIST); + new ParceledListSlice<>(Collections.emptyList())); mLooper.dispatchAll(); - verify(mWifiBlocklistMonitor).setSsidsAllowlist(Collections.EMPTY_LIST); + verify(mWifiBlocklistMonitor).setSsidsAllowlist(Collections.emptyList()); // verify setting a list of valid SSIDs List<WifiSsid> expectedSsids = new ArrayList<>(); expectedSsids.add(WifiSsid.fromString(TEST_SSID_WITH_QUOTES)); - mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, expectedSsids); + mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, + new ParceledListSlice<>(expectedSsids)); mLooper.dispatchAll(); verify(mWifiBlocklistMonitor).setSsidsAllowlist(expectedSsids); } @@ -8558,7 +8600,8 @@ public class WifiServiceImplTest extends WifiBaseTest { List<WifiSsid> expectedSsids = new ArrayList<>(); expectedSsids.add(WifiSsid.fromString(TEST_SSID_WITH_QUOTES)); - mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, expectedSsids); + mWifiServiceImpl.setSsidsAllowlist(TEST_PACKAGE_NAME, + new ParceledListSlice<>(expectedSsids)); mLooper.dispatchAll(); verify(mWifiBlocklistMonitor).setSsidsAllowlist(expectedSsids); } @@ -8920,7 +8963,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void getWifiActivityEnergyInfoAsyncFeatureUnsupported() throws Exception { - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet()); mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener); verify(mOnWifiActivityEnergyInfoListener).onWifiActivityEnergyInfo(null); @@ -8932,7 +8975,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void getWifiActivityEnergyInfoAsyncSuccess() throws Exception { - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(Long.MAX_VALUE); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); setupReportActivityInfo(); mWifiServiceImpl.getWifiActivityEnergyInfoAsync(mOnWifiActivityEnergyInfoListener); mLooper.dispatchAll(); @@ -9002,7 +9046,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test(expected = SecurityException.class) public void testGetWifiConfigsForMatchedNetworkSuggestionsWithoutPermissions() { - mWifiServiceImpl.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()); + mWifiServiceImpl.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(Collections.emptyList())); } /** @@ -9016,7 +9061,8 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mLooper.startAutoDispatch(); mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList()); + .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(createScanResultList())); mLooper.stopAutoDispatch(); verify(mWifiNetworkSuggestionsManager) .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); @@ -9033,7 +9079,8 @@ public class WifiServiceImplTest extends WifiBaseTest { anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mLooper.startAutoDispatch(); mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(createScanResultList()); + .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(createScanResultList())); mLooper.stopAutoDispatch(); verify(mWifiNetworkSuggestionsManager) .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); @@ -9044,7 +9091,8 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); mWifiServiceImpl - .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()); + .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(Collections.emptyList())); mLooper.dispatchAll(); verify(mWifiNetworkSuggestionsManager, never()) .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()); @@ -9133,7 +9181,7 @@ public class WifiServiceImplTest extends WifiBaseTest { .thenReturn(PackageManager.PERMISSION_DENIED); try { mWifiServiceImpl.addCustomDhcpOptions(WifiSsid.fromString(TEST_SSID_WITH_QUOTES), - TEST_OUI, new ArrayList<DhcpOption>()); + TEST_OUI, new ParceledListSlice<>(Collections.emptyList())); fail("expected SecurityException"); } catch (SecurityException expected) { } @@ -9166,7 +9214,7 @@ public class WifiServiceImplTest extends WifiBaseTest { public void testAddCustomDhcpOptionsAndVerify() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); mWifiServiceImpl.addCustomDhcpOptions(WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_OUI, - new ArrayList<DhcpOption>()); + new ParceledListSlice<>(Collections.emptyList())); mLooper.dispatchAll(); verify(mWifiConfigManager).addCustomDhcpOptions( WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_OUI, new ArrayList<DhcpOption>()); @@ -9186,18 +9234,20 @@ public class WifiServiceImplTest extends WifiBaseTest { } @Test - public void getSupportedFeaturesVerboseLoggingThrottled() { + public void supportedFeaturesVerboseLoggingThrottled() { mWifiServiceImpl.enableVerboseLogging( WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED); // this logs when(mClock.getElapsedSinceBootMillis()).thenReturn(1000L); - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0x110L); - mWifiServiceImpl.getSupportedFeatures(); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_P2P)); + mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P); when(mClock.getElapsedSinceBootMillis()).thenReturn(1001L); - mWifiServiceImpl.getSupportedFeatures(); // should not log + mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P); // should not log when(mClock.getElapsedSinceBootMillis()).thenReturn(5000L); - mWifiServiceImpl.getSupportedFeatures(); - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0x100L); - mWifiServiceImpl.getSupportedFeatures(); + mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(createCapabilityBitset( + WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_PASSPOINT)); + mWifiServiceImpl.isFeatureSupported(WifiManager.WIFI_FEATURE_P2P); verify(mLog, times(4)).info(any()); } @@ -9437,7 +9487,7 @@ public class WifiServiceImplTest extends WifiBaseTest { mLooper.stopAutoDispatchAndIgnoreExceptions(); verify(mWakeupController).dump(any(), any(), any()); verify(mPasspointNetworkNominateHelper).dump(any()); - verify(mWifiResourceCache).dump(any()); + verify(mResourceCache).dump(any()); } /** @@ -10131,7 +10181,7 @@ public class WifiServiceImplTest extends WifiBaseTest { } private List<WifiConfiguration> setupMultiTypeConfigs( - long featureFlags, boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) { + BitSet featureFlags, boolean saeAutoUpgradeEnabled, boolean oweAutoUpgradeEnabled) { when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(featureFlags); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(saeAutoUpgradeEnabled); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(oweAutoUpgradeEnabled); @@ -10204,7 +10254,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testGetConfiguredNetworksForMultiTypeConfigs() { - long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE; + BitSet featureFlags = createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE); List<WifiConfiguration> testConfigs = setupMultiTypeConfigs( featureFlags, true, true); when(mWifiConfigManager.getSavedNetworks(anyInt())) @@ -10236,7 +10287,8 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testGetConfiguredNetworksForMultiTypeConfigsWithoutAutoUpgradeEnabled() { - long featureFlags = WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE; + BitSet featureFlags = createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE); List<WifiConfiguration> testConfigs = setupMultiTypeConfigs( featureFlags, false, false); when(mWifiConfigManager.getSavedNetworks(anyInt())) @@ -10268,7 +10320,7 @@ public class WifiServiceImplTest extends WifiBaseTest { */ @Test public void testGetConfiguredNetworksForMultiTypeConfigsWithoutHwSupport() { - long featureFlags = 0L; + BitSet featureFlags = new BitSet(); List<WifiConfiguration> testConfigs = setupMultiTypeConfigs( featureFlags, true, true); when(mWifiConfigManager.getSavedNetworks(anyInt())) @@ -10496,7 +10548,7 @@ public class WifiServiceImplTest extends WifiBaseTest { assumeTrue(SdkLevel.isAtLeastT()); when(mWifiGlobals.isBackgroundScanSupported()).thenReturn(true); when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_PNO); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_PNO)); when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission( anyInt())).thenReturn(true); when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest( @@ -10516,7 +10568,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testSetExternalPnoScanRequest_PnoNotSupported() throws Exception { assumeTrue(SdkLevel.isAtLeastT()); - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet()); when(mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission( anyInt())).thenReturn(true); when(mWifiPermissionsUtil.checkCallersLocationPermissionInManifest( @@ -10726,7 +10778,7 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testFailureCallbacksTriggeredWhenSoftApFailsBecauseNonSupportedConfiguration() throws Exception { - when(mResources.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false); + when(mResourceCache.getBoolean(R.bool.config_wifiSoftap6ghzSupported)).thenReturn(false); setupForCustomLohs(); SoftApConfiguration lohsConfig = createValidSoftApConfiguration(); SoftApConfiguration customizedConfig = new SoftApConfiguration.Builder(lohsConfig) @@ -11291,7 +11343,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST, - Arrays.asList(WifiSsid.fromUtf8Text("SSID"))); + new ParceledListSlice<>(List.of(WifiSsid.fromUtf8Text("SSID")))); mLooper.dispatchAll(); verify(mClientModeManager).disconnect(); @@ -11319,7 +11371,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST, - Arrays.asList(WifiSsid.fromUtf8Text(TEST_SSID))); + new ParceledListSlice<>(List.of(WifiSsid.fromUtf8Text(TEST_SSID)))); mLooper.dispatchAll(); verify(mClientModeManager).disconnect(); @@ -11344,7 +11396,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_ALLOWLIST, - Arrays.asList(WifiSsid.fromUtf8Text("SSID"))); + new ParceledListSlice<>(List.of(WifiSsid.fromUtf8Text("SSID")))); mLooper.dispatchAll(); verify(mClientModeManager, never()).disconnect(); @@ -11373,7 +11425,7 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mClientModeManager.getConnectionInfo()).thenReturn(wifiInfo); mWifiServiceImpl.notifyWifiSsidPolicyChanged(WifiSsidPolicy.WIFI_SSID_POLICY_TYPE_DENYLIST, - Arrays.asList(WifiSsid.fromUtf8Text(TEST_SSID))); + new ParceledListSlice<>(List.of(WifiSsid.fromUtf8Text("SSID")))); mLooper.dispatchAll(); verify(mClientModeManager, never()).disconnect(); @@ -11862,13 +11914,15 @@ public class WifiServiceImplTest extends WifiBaseTest { List<QosPolicyParams> paramsList = createDownlinkQosPolicyParamsList(5, true); IBinder binder = mock(IBinder.class); IListListener listener = mock(IListListener.class); - mWifiServiceImpl.addQosPolicies(paramsList, binder, TEST_PACKAGE_NAME, listener); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(paramsList), binder, + TEST_PACKAGE_NAME, listener); int expectedNumCalls = 1; if (SdkLevel.isAtLeastV()) { // Uplink policies are supported on SDK >= V paramsList = createUplinkQosPolicyParamsList(5); - mWifiServiceImpl.addQosPolicies(paramsList, binder, TEST_PACKAGE_NAME, listener); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(paramsList), binder, + TEST_PACKAGE_NAME, listener); expectedNumCalls += 1; } @@ -11891,7 +11945,8 @@ public class WifiServiceImplTest extends WifiBaseTest { // Feature disabled when(mApplicationQosPolicyRequestHandler.isFeatureEnabled()).thenReturn(false); - mWifiServiceImpl.addQosPolicies(paramsList, binder, TEST_PACKAGE_NAME, listener); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(paramsList), binder, + TEST_PACKAGE_NAME, listener); enableQosPolicyFeature(); verify(listener).onResult(mListCaptor.capture()); @@ -11902,11 +11957,14 @@ public class WifiServiceImplTest extends WifiBaseTest { // Null argument assertThrows(NullPointerException.class, () -> - mWifiServiceImpl.addQosPolicies(null, binder, TEST_PACKAGE_NAME, listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(null), binder, + TEST_PACKAGE_NAME, listener)); assertThrows(NullPointerException.class, () -> - mWifiServiceImpl.addQosPolicies(paramsList, null, TEST_PACKAGE_NAME, listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(paramsList), null, + TEST_PACKAGE_NAME, listener)); assertThrows(NullPointerException.class, () -> - mWifiServiceImpl.addQosPolicies(paramsList, binder, TEST_PACKAGE_NAME, null)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(paramsList), binder, + TEST_PACKAGE_NAME, null)); // Invalid QoS policy params list List<QosPolicyParams> emptyList = createDownlinkQosPolicyParamsList(0, true); @@ -11914,14 +11972,14 @@ public class WifiServiceImplTest extends WifiBaseTest { WifiManager.getMaxNumberOfPoliciesPerQosRequest() + 1, true); List<QosPolicyParams> duplicatePolicyList = createDownlinkQosPolicyParamsList(5, false); assertThrows(IllegalArgumentException.class, () -> - mWifiServiceImpl.addQosPolicies(emptyList, binder, TEST_PACKAGE_NAME, - listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(emptyList), binder, + TEST_PACKAGE_NAME, listener)); assertThrows(IllegalArgumentException.class, () -> - mWifiServiceImpl.addQosPolicies(largeList, binder, TEST_PACKAGE_NAME, - listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(largeList), binder, + TEST_PACKAGE_NAME, listener)); assertThrows(IllegalArgumentException.class, () -> - mWifiServiceImpl.addQosPolicies( - duplicatePolicyList, binder, TEST_PACKAGE_NAME, listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(duplicatePolicyList), + binder, TEST_PACKAGE_NAME, listener)); if (SdkLevel.isAtLeastV()) { List<QosPolicyParams> mixedDirectionList = createDownlinkQosPolicyParamsList(1, true); @@ -11932,8 +11990,8 @@ public class WifiServiceImplTest extends WifiBaseTest { .setQosCharacteristics(mockQosCharacteristics) .build()); assertThrows(IllegalArgumentException.class, () -> - mWifiServiceImpl.addQosPolicies( - mixedDirectionList, binder, TEST_PACKAGE_NAME, listener)); + mWifiServiceImpl.addQosPolicies(new ParceledListSlice<>(mixedDirectionList), + binder, TEST_PACKAGE_NAME, listener)); } } @@ -12444,8 +12502,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testSetPerSsidRoamingModeByDeviceAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); assertThrows(SecurityException.class, () -> mWifiServiceImpl.setPerSsidRoamingMode( WifiSsid.fromString(TEST_SSID_WITH_QUOTES), @@ -12467,8 +12525,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testSetPerSsidRoamingModeByNonAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); assertThrows(SecurityException.class, () -> mWifiServiceImpl.setPerSsidRoamingMode( WifiSsid.fromString(TEST_SSID_WITH_QUOTES), @@ -12490,8 +12548,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testRemovePerSsidRoamingModeByDeviceAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); assertThrows(SecurityException.class, () -> mWifiServiceImpl.removePerSsidRoamingMode( WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_PACKAGE_NAME)); @@ -12508,8 +12566,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testRemovePerSsidRoamingModeByNonAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); assertThrows(SecurityException.class, () -> mWifiServiceImpl.removePerSsidRoamingMode( WifiSsid.fromString(TEST_SSID_WITH_QUOTES), TEST_PACKAGE_NAME)); @@ -12525,8 +12583,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testGetPerSsidRoamingModesByDeviceAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); IMapListener listener = mock(IMapListener.class); InOrder inOrder = inOrder(listener); assertThrows(SecurityException.class, @@ -12553,8 +12611,8 @@ public class WifiServiceImplTest extends WifiBaseTest { @Test public void testGetPerSsidRoamingModesByNonAdmin() throws RemoteException { assumeTrue(SdkLevel.isAtLeastV()); - when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn( + createCapabilityBitset(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); IMapListener listener = mock(IMapListener.class); InOrder inOrder = inOrder(listener); assertThrows(SecurityException.class, @@ -12584,9 +12642,9 @@ public class WifiServiceImplTest extends WifiBaseTest { when(mWifiGlobals.isSwPnoEnabled()).thenReturn(isSwPnoEnabled); if (isPnoFeatureSet) { when(mActiveModeWarden.getSupportedFeatureSet()) - .thenReturn(WifiManager.WIFI_FEATURE_PNO); + .thenReturn(createCapabilityBitset(WifiManager.WIFI_FEATURE_PNO)); } else { - when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(0L); + when(mActiveModeWarden.getSupportedFeatureSet()).thenReturn(new BitSet()); } assertEquals(mWifiServiceImpl.isPnoSupported(), (isBackgroundScanSupported && isPnoFeatureSet) || isSwPnoEnabled); @@ -12829,4 +12887,104 @@ public class WifiServiceImplTest extends WifiBaseTest { // Only WEP disconnect verify(cmmWep).disconnect(); } + + @Test + public void testGetWifiConfigForMatchedNetworkSuggestionsSharedWithUserForMultiTypeConfigs() { + BitSet featureFlags = createCapabilityBitset( + WifiManager.WIFI_FEATURE_WPA3_SAE, WifiManager.WIFI_FEATURE_OWE); + List<WifiConfiguration> testConfigs = setupMultiTypeConfigs(featureFlags, true, true); + when(mWifiNetworkSuggestionsManager + .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(anyList())) + .thenReturn(testConfigs); + when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS), + anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); + ScanResult[] scanResults = + ScanTestUtil.createScanDatas(new int[][]{{2417, 2427, 5180, 5170}})[0] + .getResults(); + List<ScanResult> scanResultList = + new ArrayList<>(Arrays.asList(scanResults)); + + mLooper.startAutoDispatch(); + ParceledListSlice<WifiConfiguration> configs = + mWifiServiceImpl.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + new ParceledListSlice<>(scanResultList)); + mLooper.stopAutoDispatchAndIgnoreExceptions(); + + List<WifiConfiguration> expectedConfigs = generateExpectedConfigs( + testConfigs, true, true); + WifiConfigurationTestUtil.assertConfigurationsEqualForBackup( + expectedConfigs, configs.getList()); + } + + @Test + public void testSetAutojoinDisallowedSecurityTypesWithPermission() throws RemoteException { + assumeTrue(SdkLevel.isAtLeastT()); + // No permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); + when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt())) + .thenReturn(false); + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(0/*restrict none*/, + mExtras)); + // Has permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); + // Null argument + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(0/*restrict none*/, + null)); + // Invalid argument + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes( + 0x1 << WifiInfo.SECURITY_TYPE_OWE, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes( + 0x1 << WifiInfo.SECURITY_TYPE_SAE, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinDisallowedSecurityTypes( + 0x1 << WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE, mExtras)); + // Valid argument + int restrictions = (0x1 << WifiInfo.SECURITY_TYPE_OPEN) + | (0x1 << WifiInfo.SECURITY_TYPE_OWE) | (0x1 << WifiInfo.SECURITY_TYPE_WEP); + mWifiServiceImpl.setAutojoinDisallowedSecurityTypes(restrictions, mExtras); + mLooper.dispatchAll(); + verify(mWifiConnectivityManager).setAutojoinDisallowedSecurityTypes(eq(restrictions)); + } + + @Test + public void testGetAutojoinDisallowedSecurityTypesWithPermission() throws RemoteException { + assumeTrue(SdkLevel.isAtLeastT()); + // Mock listener. + IIntegerListener listener = mock(IIntegerListener.class); + InOrder inOrder = inOrder(listener); + // No permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(false); + when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt())) + .thenReturn(false); + assertThrows(SecurityException.class, + () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, mExtras)); + // Null arguments + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(null, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, null)); + // has permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); + when(mWifiConnectivityManager.getAutojoinDisallowedSecurityTypes()).thenReturn(7); + mWifiServiceImpl.getAutojoinDisallowedSecurityTypes(listener, mExtras); + mLooper.dispatchAll(); + inOrder.verify(listener).onResult(7); + } + /** + * Verify UwbManager.AdapterStateCallback onStateChanged could update mLastUwbState in + * WifiMetrics properly + */ + @Test + public void testServiceImplAdapterStateCallback() { + assumeTrue(SdkLevel.isAtLeastT()); + UwbAdapterStateListener uwbAdapterStateListener = + mWifiServiceImpl.new UwbAdapterStateListener(); + + uwbAdapterStateListener.onStateChanged(2, 1); + verify(mWifiMetrics).setLastUwbState(2); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java index 9252aa8f41..a63c4d47b2 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiShellCommandTest.java @@ -23,6 +23,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_DISCONNECT; import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; +import static android.net.wifi.WifiManager.ROAMING_MODE_NONE; +import static android.net.wifi.WifiManager.ROAMING_MODE_NORMAL; +import static android.net.wifi.WifiManager.ROAMING_MODE_AGGRESSIVE; import static com.android.server.wifi.WifiShellCommand.SHELL_PACKAGE_NAME; @@ -57,6 +60,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiNetworkSpecifier; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; +import android.net.wifi.WifiSsid; import android.os.Binder; import android.os.Handler; import android.os.PatternMatcher; @@ -65,6 +69,7 @@ import android.os.test.TestLooper; import androidx.test.filters.SmallTest; +import com.android.modules.utils.ParceledListSlice; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.coex.CoexManager; @@ -78,6 +83,7 @@ import org.mockito.MockitoAnnotations; import java.io.FileDescriptor; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** * Unit tests for {@link com.android.server.wifi.WifiShellCommand}. @@ -190,7 +196,7 @@ public class WifiShellCommandTest extends WifiBaseTest { mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"set-poll-rssi-interval-msecs", "5"}); - verify(mWifiGlobals, never()).setPollRssiIntervalMillis(anyInt()); + verify(mPrimaryClientModeManager, never()).setLinkLayerStatsPollingInterval(anyInt()); assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); BinderUtil.setUid(Process.ROOT_UID); @@ -198,13 +204,38 @@ public class WifiShellCommandTest extends WifiBaseTest { mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"set-poll-rssi-interval-msecs", "5"}); - verify(mWifiGlobals).setPollRssiIntervalMillis(5); + verify(mPrimaryClientModeManager).setLinkLayerStatsPollingInterval(5); // invalid arg mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"set-poll-rssi-interval-msecs", "0"}); verifyNoMoreInteractions(mWifiGlobals); + verifyNoMoreInteractions(mPrimaryClientModeManager); + assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); + + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-poll-rssi-interval-msecs", "4", "8"}); + verify(mWifiGlobals).setPollRssiShortIntervalMillis(4); + verify(mWifiGlobals).setPollRssiLongIntervalMillis(8); + verify(mWifiGlobals).setPollRssiIntervalMillis(4); + verify(mPrimaryClientModeManager).setLinkLayerStatsPollingInterval(0); + + // invalid arg + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-poll-rssi-interval-msecs", "8", "4"}); + verifyNoMoreInteractions(mWifiGlobals); + verifyNoMoreInteractions(mPrimaryClientModeManager); + assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); + + // invalid arg + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-poll-rssi-interval-msecs", "4", "8", "12"}); + verifyNoMoreInteractions(mWifiGlobals); + verifyNoMoreInteractions(mPrimaryClientModeManager); assertFalse(mWifiShellCommand.getErrPrintWriter().toString().isEmpty()); } @@ -604,9 +635,9 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"add-suggestion", "ssid1234", "open", "-u"}); verify(mWifiService).addNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isUntrusted()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isUntrusted()); }), eq(SHELL_PACKAGE_NAME), any()); verify(mConnectivityManager).requestNetwork(argThat(nR -> { return (nR.hasTransport(TRANSPORT_WIFI)) @@ -614,18 +645,18 @@ public class WifiShellCommandTest extends WifiBaseTest { }), any(ConnectivityManager.NetworkCallback.class)); when(mWifiService.getNetworkSuggestions(any())) - .thenReturn(Arrays.asList( + .thenReturn(new ParceledListSlice<>(List.of( new WifiNetworkSuggestion.Builder() .setSsid("ssid1234") .setUntrusted(true) - .build())); + .build()))); mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"remove-suggestion", "ssid1234"}); verify(mWifiService).removeNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isUntrusted()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isUntrusted()); }), eq(SHELL_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_DISCONNECT)); verify(mConnectivityManager).unregisterNetworkCallback( any(ConnectivityManager.NetworkCallback.class)); @@ -639,9 +670,9 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"add-suggestion", "ssid1234", "open", "-o"}); verify(mWifiService).addNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isOemPaid()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isOemPaid()); }), eq(SHELL_PACKAGE_NAME), any()); verify(mConnectivityManager).requestNetwork(argThat(nR -> { return (nR.hasTransport(TRANSPORT_WIFI)) @@ -649,18 +680,18 @@ public class WifiShellCommandTest extends WifiBaseTest { }), any(ConnectivityManager.NetworkCallback.class)); when(mWifiService.getNetworkSuggestions(any())) - .thenReturn(Arrays.asList( + .thenReturn(new ParceledListSlice<>(List.of( new WifiNetworkSuggestion.Builder() .setSsid("ssid1234") .setOemPaid(true) - .build())); + .build()))); mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"remove-suggestion", "ssid1234"}); verify(mWifiService).removeNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isOemPaid()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isOemPaid()); }), eq(SHELL_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_DISCONNECT)); verify(mConnectivityManager).unregisterNetworkCallback( any(ConnectivityManager.NetworkCallback.class)); @@ -674,9 +705,9 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"add-suggestion", "ssid1234", "open", "-p"}); verify(mWifiService).addNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isOemPrivate()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isOemPrivate()); }), eq(SHELL_PACKAGE_NAME), any()); verify(mConnectivityManager).requestNetwork(argThat(nR -> { return (nR.hasTransport(TRANSPORT_WIFI)) @@ -684,18 +715,18 @@ public class WifiShellCommandTest extends WifiBaseTest { }), any(ConnectivityManager.NetworkCallback.class)); when(mWifiService.getNetworkSuggestions(any())) - .thenReturn(Arrays.asList( + .thenReturn(new ParceledListSlice<>(List.of( new WifiNetworkSuggestion.Builder() .setSsid("ssid1234") .setOemPrivate(true) - .build())); + .build()))); mWifiShellCommand.exec( new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"remove-suggestion", "ssid1234"}); verify(mWifiService).removeNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).isOemPrivate()); + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).isOemPrivate()); }), eq(SHELL_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_DISCONNECT)); verify(mConnectivityManager).unregisterNetworkCallback( any(ConnectivityManager.NetworkCallback.class)); @@ -708,9 +739,9 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"add-suggestion", "ssid1234", "open"}); verify(mWifiService).addNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).getWifiConfiguration().macRandomizationSetting + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).getWifiConfiguration().macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT); }), eq(SHELL_PACKAGE_NAME), any()); @@ -720,9 +751,9 @@ public class WifiShellCommandTest extends WifiBaseTest { new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), new String[]{"add-suggestion", "ssid1234", "open", "-r"}); verify(mWifiService).addNetworkSuggestions(argThat(sL -> { - return (sL.size() == 1) - && (sL.get(0).getSsid().equals("ssid1234")) - && (sL.get(0).getWifiConfiguration().macRandomizationSetting + return (sL.getList().size() == 1) + && (sL.getList().get(0).getSsid().equals("ssid1234")) + && (sL.getList().get(0).getWifiConfiguration().macRandomizationSetting == WifiConfiguration.RANDOMIZATION_NON_PERSISTENT); }), eq(SHELL_PACKAGE_NAME), any()); } @@ -1042,4 +1073,51 @@ public class WifiShellCommandTest extends WifiBaseTest { anyInt(), eq(WifiAvailableChannel.FILTER_REGULATORY), eq(SHELL_PACKAGE_NAME), any()); } + + @Test + public void testSetSsidRoamingMode() { + BinderUtil.setUid(Process.ROOT_UID); + final String testSsid = "testssid"; + final String hexSsid = "68656c6c6f20776f726c64"; + ArgumentCaptor<WifiSsid> wifiSsidCaptor = ArgumentCaptor.forClass( + WifiSsid.class); + + // Unsupported mode + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-ssid-roaming-mode", testSsid, "abcd"}); + verify(mWifiService, never()).setPerSsidRoamingMode(any(), anyInt(), anyString()); + + // None mode + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-ssid-roaming-mode", testSsid, "none"}); + verify(mWifiService).setPerSsidRoamingMode( + wifiSsidCaptor.capture(), eq(ROAMING_MODE_NONE), eq(SHELL_PACKAGE_NAME)); + assertEquals("\"" + testSsid + "\"", wifiSsidCaptor.getValue().toString()); + + // Normal mode + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-ssid-roaming-mode", testSsid, "normal"}); + verify(mWifiService).setPerSsidRoamingMode( + wifiSsidCaptor.capture(), eq(ROAMING_MODE_NORMAL), eq(SHELL_PACKAGE_NAME)); + assertEquals("\"" + testSsid + "\"", wifiSsidCaptor.getValue().toString()); + + // Aggressive mode + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-ssid-roaming-mode", testSsid, "aggressive"}); + verify(mWifiService).setPerSsidRoamingMode( + wifiSsidCaptor.capture(), eq(ROAMING_MODE_AGGRESSIVE), eq(SHELL_PACKAGE_NAME)); + assertEquals("\"" + testSsid + "\"", wifiSsidCaptor.getValue().toString()); + + // Test with "hello world" SSID encoded in hexadecimal UTF-8 + mWifiShellCommand.exec( + new Binder(), new FileDescriptor(), new FileDescriptor(), new FileDescriptor(), + new String[]{"set-ssid-roaming-mode", hexSsid, "aggressive", "-x"}); + verify(mWifiService, times(2)).setPerSsidRoamingMode( + wifiSsidCaptor.capture(), eq(ROAMING_MODE_AGGRESSIVE), eq(SHELL_PACKAGE_NAME)); + assertEquals("\"hello world\"", wifiSsidCaptor.getValue().toString()); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java index c958fc1a3a..b1ba78ec3c 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -31,7 +32,6 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.anyObject; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.eq; @@ -86,6 +86,7 @@ import org.mockito.stubbing.Answer; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Random; @@ -173,7 +174,7 @@ public class WifiVendorHalTest extends WifiBaseTest { }).when(mHalDeviceManager).stop(); when(mHalDeviceManager.createStaIface(any(), any(), any(), eq(mConcreteClientModeManager))) .thenReturn(mWifiStaIface); - when(mHalDeviceManager.createApIface(anyLong(), any(), any(), any(), anyBoolean(), + when(mHalDeviceManager.createApIface(any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList())) .thenReturn(mWifiApIface); when(mHalDeviceManager.removeIface(any())).thenReturn(true); @@ -254,7 +255,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); } /** @@ -278,7 +279,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager, never()).createStaIface(any(), any(), any(), eq(mConcreteClientModeManager)); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); verify(mWifiStaIface, never()) .registerFrameworkCallback(any(WifiStaIface.Callback.class)); @@ -301,7 +302,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).stop(); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); verify(mWifiStaIface, never()) .registerFrameworkCallback(any(WifiStaIface.Callback.class)); @@ -325,7 +326,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mWifiStaIface).registerFrameworkCallback(any(WifiStaIface.Callback.class)); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); } /** @@ -347,7 +348,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager, never()).getChip(any(WifiHal.WifiInterface.class)); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); } /** @@ -370,7 +371,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mWifiChip).registerCallback(any(WifiChip.Callback.class)); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); } /** @@ -394,7 +395,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager, times(2)).isStarted(); verify(mHalDeviceManager, never()).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); } /** @@ -415,7 +416,7 @@ public class WifiVendorHalTest extends WifiBaseTest { verify(mHalDeviceManager).start(); verify(mHalDeviceManager).stop(); verify(mHalDeviceManager).createApIface( - anyLong(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); + any(), any(), any(), any(), anyBoolean(), eq(mSoftApManager), anyList()); verify(mHalDeviceManager).getChip(eq(mWifiApIface)); verify(mHalDeviceManager, times(2)).isReady(); verify(mHalDeviceManager, times(2)).isStarted(); @@ -473,7 +474,7 @@ public class WifiVendorHalTest extends WifiBaseTest { assertTrue(mWifiVendorHal.isHalStarted()); verify(mHalDeviceManager).start(); - verify(mHalDeviceManager).createApIface(anyLong(), + verify(mHalDeviceManager).createApIface(any(), internalListenerCaptor.capture(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager), anyList()); verify(mHalDeviceManager).getChip(eq(mWifiApIface)); @@ -553,10 +554,10 @@ public class WifiVendorHalTest extends WifiBaseTest { */ @Test public void testGetSupportedFeatures() throws Exception { - long staIfaceCaps = - WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; - long chipCaps = WifiManager.WIFI_FEATURE_TX_POWER_LIMIT; - WifiChip.Response<Long> chipCapsResponse = new WifiChip.Response<>(chipCaps); + BitSet staIfaceCaps = createCapabilityBitset( + WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + BitSet chipCaps = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT); + WifiChip.Response<BitSet> chipCapsResponse = new WifiChip.Response<>(chipCaps); chipCapsResponse.setStatusCode(WifiHal.WIFI_STATUS_SUCCESS); when(mWifiStaIface.getCapabilities()).thenReturn(staIfaceCaps); when(mWifiChip.getCapabilitiesAfterIfacesExist()).thenReturn(chipCapsResponse); @@ -568,17 +569,16 @@ public class WifiVendorHalTest extends WifiBaseTest { when(mWifiGlobals.isWpa3SaeH2eSupported()).thenReturn(true); when(mHalDeviceManager.is24g5gDbsSupported(any())).thenReturn(true); - long expectedFeatureSet = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS - | WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_INFRA - | WifiManager.WIFI_FEATURE_P2P - | WifiManager.WIFI_FEATURE_SAE_H2E - | WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS - ); + BitSet expectedFeatureSet = createCapabilityBitset(WifiManager.WIFI_FEATURE_SCANNER, + WifiManager.WIFI_FEATURE_LINK_LAYER_STATS, + WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, + WifiManager.WIFI_FEATURE_INFRA, + WifiManager.WIFI_FEATURE_P2P, + WifiManager.WIFI_FEATURE_SAE_H2E, + WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS); assertTrue(mWifiVendorHal.startVendorHalSta(mConcreteClientModeManager)); - assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); + assertTrue(expectedFeatureSet.equals( + mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME))); } /** @@ -603,12 +603,10 @@ public class WifiVendorHalTest extends WifiBaseTest { when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_WIFI_AWARE))) .thenReturn(true); - long expectedFeatureSet = ( - WifiManager.WIFI_FEATURE_INFRA - | WifiManager.WIFI_FEATURE_P2P - | WifiManager.WIFI_FEATURE_AWARE - ); - assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); + BitSet expectedFeatureSet = createCapabilityBitset(WifiManager.WIFI_FEATURE_INFRA, + WifiManager.WIFI_FEATURE_P2P, WifiManager.WIFI_FEATURE_AWARE); + assertTrue(expectedFeatureSet.equals( + mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME))); } /** @@ -1464,7 +1462,7 @@ public class WifiVendorHalTest extends WifiBaseTest { null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager, new ArrayList<>())); verify(mHalDeviceManager).createApIface( - anyLong(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager), + any(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager), anyList()); } @@ -1493,7 +1491,7 @@ public class WifiVendorHalTest extends WifiBaseTest { null, TEST_WORKSOURCE, SoftApConfiguration.BAND_2GHZ, false, mSoftApManager, new ArrayList<>()); verify(mHalDeviceManager).createApIface( - anyLong(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager), + any(), any(), any(), eq(TEST_WORKSOURCE), eq(false), eq(mSoftApManager), anyList()); assertEquals(TEST_IFACE_NAME, ifaceName); assertTrue(mWifiVendorHal.removeApIface(ifaceName)); diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java index 9741a2c8c2..1c8264a1f6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiVoipDetectorTest.java @@ -66,6 +66,7 @@ public class WifiVoipDetectorTest extends WifiBaseTest { @Mock private TelephonyManager mTelephonyManager; @Mock private WifiNative mWifiNative; @Mock private WifiCarrierInfoManager mWifiCarrierInfoManager; + @Mock private WifiMetrics mWifiMetrics; private WifiVoipDetector mWifiVoipDetector; private TestLooper mLooper; @@ -84,13 +85,15 @@ public class WifiVoipDetectorTest extends WifiBaseTest { when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager); when(mContext.getSystemService(AudioManager.class)).thenReturn(mAudioManager); when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); + when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); when(mWifiNative.setVoipMode(anyInt())).thenReturn(true); mWifiVoipDetector = new WifiVoipDetector(mContext, new Handler(mLooper.getLooper()), mWifiInjector, mWifiCarrierInfoManager); } - private void resetWifiNativeAndReSetupforMock() { + private void resetWifiNativeAndWifiMetricsAndReSetupforMock() { reset(mWifiNative); + reset(mWifiMetrics); when(mWifiNative.setVoipMode(anyInt())).thenReturn(true); } @@ -111,38 +114,46 @@ public class WifiVoipDetectorTest extends WifiBaseTest { when(mWifiCarrierInfoManager.isWifiCallingAvailable()).thenReturn(true); mWifiVoipDetector.notifyWifiConnected(true, true, TEST_PRIMARY_INTERFACE_NAME); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); // Test VoWifi call off -> switch to VoLte mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_LTE_CALL_ATT); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Test VoWifi Call mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_VOWIFI_CALL_ATT); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Test VoWifi call off -> switch to VoLte mTelephonyCallbackCaptor.getValue().onCallAttributesChanged(TEST_LTE_CALL_ATT); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Test MODE_IN_COMMUNICATION to trigger voice mode mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_IN_COMMUNICATION); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Test MODE_NORMAL off WifiChip.WIFI_VOIP_MODE_OFF mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_NORMAL); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Test MODE_COMMUNICATION_REDIRECT to trigger voice mode mAudioModeChangedListeneCaptor.getValue().onModeChanged( AudioManager.MODE_COMMUNICATION_REDIRECT); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); - resetWifiNativeAndReSetupforMock(); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); // Do nothing when mode change between two OTT modes. mAudioModeChangedListeneCaptor.getValue().onModeChanged(AudioManager.MODE_IN_COMMUNICATION); verify(mWifiNative, never()).setVoipMode(anyInt()); mWifiVoipDetector.notifyWifiConnected(false, true, TEST_PRIMARY_INTERFACE_NAME); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_OFF); // Test OTT on when wifi is disconnected, should do nothing since it doesn't relate to wifi. - resetWifiNativeAndReSetupforMock(); + resetWifiNativeAndWifiMetricsAndReSetupforMock(); mAudioModeChangedListeneCaptor.getValue().onModeChanged( AudioManager.MODE_COMMUNICATION_REDIRECT); verify(mWifiNative, never()).setVoipMode(anyInt()); @@ -150,6 +161,7 @@ public class WifiVoipDetectorTest extends WifiBaseTest { when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_COMMUNICATION_REDIRECT); mWifiVoipDetector.notifyWifiConnected(true, true, TEST_PRIMARY_INTERFACE_NAME); verify(mWifiNative).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); + verify(mWifiInjector.getWifiMetrics()).setVoipMode(WifiChip.WIFI_VOIP_MODE_VOICE); } @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/PairingConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/PairingConfigManagerTest.java new file mode 100644 index 0000000000..95656604c7 --- /dev/null +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/PairingConfigManagerTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2024 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 com.android.server.wifi.aware; + +import static com.android.server.wifi.aware.PairingConfigManager.NIR; +import static com.android.server.wifi.aware.PairingConfigManager.TAG_SIZE_IN_BYTE; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.net.MacAddress; +import android.net.wifi.aware.Characteristics; + +import com.android.server.wifi.WifiBaseTest; + +import org.junit.Before; +import org.junit.Test; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.List; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/** + * Unit test harness for PairingConfigManager. + */ +public class PairingConfigManagerTest extends WifiBaseTest { + private PairingConfigManager mPairingConfigManager; + private final String mPackageName = "some.package"; + private final String mPackageName1 = "another.package"; + private final String mAlias = "alias"; + private final byte[] mNouce = "nounce".getBytes(); + private final String mMac = "fa:45:23:23:12:12"; + + @Before + public void setup() { + mPairingConfigManager = new PairingConfigManager(); + } + + /** + * Test get new NIK for the App + */ + @Test + public void testCallingPackageNik() { + byte[] nik = mPairingConfigManager.getNikForCallingPackage(mPackageName); + assertFalse(Arrays.equals(nik, + mPairingConfigManager.getNikForCallingPackage(mPackageName1))); + mPairingConfigManager.removePackage(mPackageName); + assertFalse(Arrays.equals(nik, + mPairingConfigManager.getNikForCallingPackage(mPackageName))); + } + + /** + * Test add paired device and match + */ + @Test + public void testAddPairedPeerDevice() { + byte[] localNik = mPairingConfigManager.getNikForCallingPackage(mPackageName); + byte[] peerNik = mPairingConfigManager.getNikForCallingPackage(mPackageName1); + PairingConfigManager.PairingSecurityAssociationInfo pairingInfo = + new PairingConfigManager.PairingSecurityAssociationInfo(peerNik, localNik, + new byte[16], WifiAwareStateManager.NAN_PAIRING_AKM_PASN, + Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); + mPairingConfigManager.addPairedDeviceSecurityAssociation(mPackageName, mAlias, pairingInfo); + byte[] mac = MacAddress.fromString(mMac).toByteArray(); + byte[] peerTag = generateTag(peerNik, mNouce, mac); + String peerAlias = mPairingConfigManager.getPairedDeviceAlias(mPackageName, mNouce, peerTag, + mac); + assertEquals(mAlias, peerAlias); + assertEquals(pairingInfo, mPairingConfigManager.getSecurityInfoPairedDevice(peerAlias)); + mPairingConfigManager.removePairedDevice(mPackageName, mAlias); + assertNull(mPairingConfigManager.getPairedDeviceAlias(mPackageName, mNouce, peerTag, + mac)); + } + + /** + * Test remove App will clear the paired device + */ + @Test + public void testRemovePackages() { + byte[] localNik = mPairingConfigManager.getNikForCallingPackage(mPackageName); + byte[] peerNik = mPairingConfigManager.getNikForCallingPackage(mPackageName1); + PairingConfigManager.PairingSecurityAssociationInfo pairingInfo = + new PairingConfigManager.PairingSecurityAssociationInfo(peerNik, localNik, + new byte[16], WifiAwareStateManager.NAN_PAIRING_AKM_PASN, + Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); + mPairingConfigManager.addPairedDeviceSecurityAssociation(mPackageName, mAlias, pairingInfo); + List<String> allAlias = mPairingConfigManager.getAllPairedDevices(mPackageName); + assertEquals(1, allAlias.size()); + assertEquals(mAlias, allAlias.get(0)); + mPairingConfigManager.removePackage(mPackageName1); + allAlias = mPairingConfigManager.getAllPairedDevices(mPackageName); + assertEquals(1, allAlias.size()); + assertEquals(mAlias, allAlias.get(0)); + mPairingConfigManager.removePackage(mPackageName); + allAlias = mPairingConfigManager.getAllPairedDevices(mPackageName); + assertTrue(allAlias.isEmpty()); + } + + private byte[] generateTag(byte[] nik, byte[] nonce, byte[] mac) { + SecretKeySpec spec = new SecretKeySpec(nik, "HmacSHA256"); + try { + Mac hash = Mac.getInstance("HmacSHA256"); + hash.init(spec); + hash.update(NIR); + hash.update(mac); + hash.update(nonce); + return Arrays.copyOf(hash.doFinal(), TAG_SIZE_IN_BYTE); + } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalStateException e) { + return null; + } + } +} diff --git a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java index 51537dccda..38a60f56ed 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java @@ -34,6 +34,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyByte; @@ -215,9 +216,11 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { MockitoAnnotations.initMocks(this); mSession = ExtendedMockito.mockitoSession() .strictness(Strictness.LENIENT) + .mockStatic(WifiInjector.class) .mockStatic(WifiStatsLog.class) .startMocking(); + when(WifiInjector.getInstance()).thenReturn(mWifiInjector); mAlarmManager = new TestAlarmManager(); when(mMockContext.getSystemService(Context.ALARM_SERVICE)) .thenReturn(mAlarmManager.getAlarmManager()); @@ -288,14 +291,20 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { callbackArgumentCaptor.capture()); mActiveCountryCodeChangedCallback = callbackArgumentCaptor.getValue(); } - verify(mMockContext, times(3)) + verify(mMockContext) + .registerReceiverForAllUsers( + bcastRxCaptor.capture(), + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + isNull(), + any(Handler.class)); + verify(mMockContext, times(2)) .registerReceiver( bcastRxCaptor.capture(), any(IntentFilter.class), isNull(), any(Handler.class)); - mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0); - mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1); + mLocationModeReceiver = bcastRxCaptor.getAllValues().get(0); + mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(1); mWifiStateChangedReceiver = bcastRxCaptor.getAllValues().get(2); verify(mWifiSettingsConfigStore).registerChangeListener( eq(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED), @@ -761,7 +770,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); ArgumentCaptor<Short> transactionIdCapture = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative); + InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative, mMockNativeManager); mDut.enableUsage(); mMockLooper.dispatchAll(); @@ -827,7 +836,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -3826,95 +3836,6 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { } /** - * Validate aware enable/disable during doze transitions. - */ - @Test - public void testEnableDisableOnDoze() throws Exception { - final int clientId = 188; - final int uid = 1000; - final int pid = 2000; - final String callingPackage = "com.google.somePackage"; - final String callingFeature = "com.google.someFeature"; - - setSettableParam(WifiAwareStateManager.PARAM_ON_IDLE_DISABLE_AWARE, Integer.toString(1), - true); - - ConfigRequest configRequest = new ConfigRequest.Builder().build(); - - ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); - IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); - InOrder inOrder = inOrder(mMockContext, mMockNativeManager, mMockNative, mockCallback); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).start(any(Handler.class)); - inOrder.verify(mMockNativeManager).tryToGetAware(new WorkSource(Process.WIFI_UID)); - inOrder.verify(mMockNativeManager).releaseAware(); - - mDut.enableUsage(); - mMockLooper.dispatchAll(); - - // (1) connect - mDut.connect(clientId, uid, pid, callingPackage, callingFeature, mockCallback, - configRequest, false, mExtras, false); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).tryToGetAware(new WorkSource(uid, callingPackage)); - inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), - eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false), eq(false), - anyInt(), anyInt()); - mDut.onConfigSuccessResponse(transactionId.getValue()); - mMockLooper.dispatchAll(); - assertTrue(mDut.isDeviceAttached()); - inOrder.verify(mockCallback).onConnectSuccess(clientId); - - // (2) set the App to isIgnoringBatteryOptimizations to true and power state change: DOZE - when(mMockPowerManager.isIgnoringBatteryOptimizations(callingPackage)).thenReturn(true); - simulatePowerStateChangeDoze(true); - mMockLooper.dispatchAll(); - assertTrue(mDut.isUsageEnabled()); - inOrder.verify(mockCallback, never()).onAttachTerminate(); - - // (3) set the App to isIgnoringBatteryOptimizations to false and power state change: DOZE - when(mMockPowerManager.isIgnoringBatteryOptimizations(callingPackage)).thenReturn(false); - simulatePowerStateChangeDoze(true); - mMockLooper.dispatchAll(); - collector.checkThat("usage disabled", mDut.isUsageEnabled(), equalTo(false)); - inOrder.verify(mockCallback).onAttachTerminate(); - validateCorrectAwareStatusChangeBroadcast(inOrder); - inOrder.verify(mMockNative).disable(transactionId.capture()); - assertFalse(mDut.isDeviceAttached()); - mDut.onDisableResponse(transactionId.getValue(), NanStatusCode.SUCCESS); - mMockLooper.dispatchAll(); - inOrder.verify(mMockNativeManager).releaseAware(); - - // (4) power state change: SCREEN ON (but DOZE still on - fakish but expect no changes) - simulatePowerStateChangeInteractive(false); - mMockLooper.dispatchAll(); - - // and same for other gating changes -> no changes - simulateLocationModeChange(false); - simulateWifiStateChange(false); - mMockLooper.dispatchAll(); - - // and same for other gating changes -> no changes - simulateD2dAllowedChange(false); - mMockLooper.dispatchAll(); - simulateD2dAllowedChange(true); - mMockLooper.dispatchAll(); - - // and same for other gating changes -> no changes - simulateLocationModeChange(true); - simulateWifiStateChange(true); - mMockLooper.dispatchAll(); - - // (5) power state change: DOZE OFF - simulatePowerStateChangeDoze(false); - mMockLooper.dispatchAll(); - collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); - validateCorrectAwareStatusChangeBroadcast(inOrder); - - verifyNoMoreInteractions(mMockNativeManager, mMockNative, mockCallback); - } - - /** * Validate aware enable/disable during LOCATION MODE transitions on pre-T, Aware should be * disabled. */ @@ -4182,6 +4103,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockCallback).onAttachTerminate(); collector.checkThat("usage enabled", mDut.isUsageEnabled(), equalTo(true)); assertFalse(mDut.isDeviceAttached()); + mMockLooper.dispatchAll(); validateCorrectAwareStatusChangeBroadcast(inOrder); // (3) try reconnect client @@ -4679,7 +4601,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String alias = "alias"; AwarePairingConfig pairingConfig = new AwarePairingConfig(true, true, true, - AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN); + AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); ConfigRequest configRequest = new ConfigRequest.Builder().build(); PublishConfig publishConfig = new PublishConfig.Builder() .setPairingConfig(pairingConfig).build(); @@ -4813,7 +4736,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String alias = "alias"; AwarePairingConfig pairingConfig = new AwarePairingConfig(true, true, true, - AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN); + AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); ConfigRequest configRequest = new ConfigRequest.Builder().build(); PublishConfig publishConfig = new PublishConfig.Builder() .setPairingConfig(pairingConfig).build(); @@ -4941,7 +4865,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String alias = "alias"; AwarePairingConfig pairingConfig = new AwarePairingConfig(true, true, true, - AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN); + AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); ConfigRequest configRequest = new ConfigRequest.Builder().build(); SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() @@ -5072,7 +4997,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String alias = "alias"; AwarePairingConfig pairingConfig = new AwarePairingConfig(true, true, true, - AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN); + AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); ConfigRequest configRequest = new ConfigRequest.Builder().build(); SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() @@ -5196,7 +5122,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { final String alias = "alias"; AwarePairingConfig pairingConfig = new AwarePairingConfig(true, true, true, - AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN); + AwarePairingConfig.PAIRING_BOOTSTRAPPING_QR_SCAN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128); ConfigRequest configRequest = new ConfigRequest.Builder().build(); SubscribeConfig subscribeConfig = new SubscribeConfig.Builder() @@ -5880,7 +5807,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); ArgumentCaptor<Short> transactionIdCapture = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative); + InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative, mMockNativeManager); mDut.enableUsage(); mMockLooper.dispatchAll(); @@ -5919,7 +5846,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -5948,7 +5876,7 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { IWifiAwareEventCallback mockCallback1 = mock(IWifiAwareEventCallback.class); IWifiAwareEventCallback mockCallback2 = mock(IWifiAwareEventCallback.class); ArgumentCaptor<Short> transactionIdCapture = ArgumentCaptor.forClass(Short.class); - InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative); + InOrder inOrder = inOrder(mockCallback1, mockCallback2, mMockNative, mMockNativeManager); mDut.enableUsage(); mMockLooper.dispatchAll(); @@ -5999,7 +5927,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -6060,7 +5989,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { inOrder.verify(mockCallback1).onAttachTerminate(); validateInternalClientInfoCleanedUp(clientId1); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mMockNative); } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/b2b/WifiRoamingModeManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/b2b/WifiRoamingModeManagerTest.java index f4b7bfc212..89a6f32b49 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/b2b/WifiRoamingModeManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/b2b/WifiRoamingModeManagerTest.java @@ -16,7 +16,6 @@ package com.android.server.wifi.b2b; -import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; @@ -29,7 +28,6 @@ import android.net.wifi.WifiSsid; import androidx.test.filters.SmallTest; -import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.ActiveModeWarden; import com.android.server.wifi.ClientModeManager; import com.android.server.wifi.WifiBaseTest; @@ -71,7 +69,6 @@ public class WifiRoamingModeManagerTest extends WifiBaseTest { @Test public void testSetPerSsidRoamingMode() { - assumeTrue(SdkLevel.isAtLeastV()); when(mWifiRoamingConfigStore.getRoamingMode(CURRENT_SSID)).thenReturn( TEST_ROAMING_MODE); mWifiRoamingModeManager.setPerSsidRoamingMode(WifiSsid.fromString(CURRENT_SSID), @@ -84,7 +81,6 @@ public class WifiRoamingModeManagerTest extends WifiBaseTest { @Test public void testRemovePerSsidRoamingMode() { - assumeTrue(SdkLevel.isAtLeastV()); mWifiRoamingModeManager.removePerSsidRoamingMode(WifiSsid.fromString(TEST_SSID), false); verify(mWifiRoamingConfigStore).removeRoamingMode(TEST_SSID, false); verify(mActiveModeWarden).getConnectionInfo(); @@ -94,7 +90,6 @@ public class WifiRoamingModeManagerTest extends WifiBaseTest { @Test public void testGetPerSsidRoamingMode() { - assumeTrue(SdkLevel.isAtLeastV()); mWifiRoamingModeManager.getPerSsidRoamingModes(false); verify(mWifiRoamingConfigStore).getPerSsidRoamingModes(false); verify(mActiveModeWarden, never()).getConnectionInfo(); diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java index 8e65ef6ef9..f4104ab87f 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipAidlImplTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi.hal; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -65,6 +66,7 @@ import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Random; @@ -123,12 +125,9 @@ public class WifiChipAidlImplTest extends WifiBaseTest { | android.hardware.wifi.IWifiChip.FeatureSetMask.D2D_RTT | android.hardware.wifi.IWifiChip.FeatureSetMask.D2AP_RTT ); - long expected = ( - WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_D2D_RTT - | WifiManager.WIFI_FEATURE_D2AP_RTT - ); - assertEquals(expected, mDut.halToFrameworkChipFeatureSet(halFeatures)); + BitSet expected = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, + WifiManager.WIFI_FEATURE_D2D_RTT, WifiManager.WIFI_FEATURE_D2AP_RTT); + assertTrue(expected.equals(mDut.halToFrameworkChipFeatureSet(halFeatures))); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java index 26bcca3b18..52d505ca89 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiChipHidlImplTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi.hal; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -63,6 +65,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Random; @@ -153,12 +156,9 @@ public class WifiChipHidlImplTest extends WifiBaseTest { | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT ); - long expected = ( - WifiManager.WIFI_FEATURE_TX_POWER_LIMIT - | WifiManager.WIFI_FEATURE_D2D_RTT - | WifiManager.WIFI_FEATURE_D2AP_RTT - ); - assertEquals(expected, mDut.wifiFeatureMaskFromChipCapabilities(caps)); + BitSet expected = createCapabilityBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT, + WifiManager.WIFI_FEATURE_D2D_RTT, WifiManager.WIFI_FEATURE_D2AP_RTT); + assertTrue(expected.equals(mDut.wifiFeatureMaskFromChipCapabilities(caps))); } /** @@ -170,11 +170,9 @@ public class WifiChipHidlImplTest extends WifiBaseTest { android.hardware.wifi.V1_3.IWifiChip.ChipCapabilityMask.SET_LATENCY_MODE | android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT ); - long expected = ( - WifiManager.WIFI_FEATURE_LOW_LATENCY - | WifiManager.WIFI_FEATURE_D2D_RTT - ); - assertEquals(expected, mDut.wifiFeatureMaskFromChipCapabilities_1_3(caps)); + BitSet expected = createCapabilityBitset( + WifiManager.WIFI_FEATURE_LOW_LATENCY, WifiManager.WIFI_FEATURE_D2D_RTT); + assertTrue(expected.equals(mDut.wifiFeatureMaskFromChipCapabilities_1_3(caps))); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceAidlImplTest.java index 192c97ac8f..d633b57b8e 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiNanIfaceAidlImplTest.java @@ -18,9 +18,14 @@ package com.android.server.wifi.hal; import static android.hardware.wifi.V1_0.NanCipherSuiteType.SHARED_KEY_128_MASK; import static android.hardware.wifi.V1_0.NanCipherSuiteType.SHARED_KEY_256_MASK; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128; +import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_256; +import static com.android.server.wifi.aware.WifiAwareStateManager.NAN_PAIRING_AKM_PASN; +import static com.android.server.wifi.aware.WifiAwareStateManager.NAN_PAIRING_AKM_SAE; + import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -33,10 +38,12 @@ import android.hardware.wifi.IWifiNanIface; import android.hardware.wifi.NanBandIndex; import android.hardware.wifi.NanBootstrappingRequest; import android.hardware.wifi.NanBootstrappingResponse; +import android.hardware.wifi.NanCipherSuiteType; import android.hardware.wifi.NanConfigRequest; import android.hardware.wifi.NanConfigRequestSupplemental; import android.hardware.wifi.NanDataPathSecurityType; import android.hardware.wifi.NanEnableRequest; +import android.hardware.wifi.NanPairingAkm; import android.hardware.wifi.NanPairingRequest; import android.hardware.wifi.NanPairingRequestType; import android.hardware.wifi.NanPairingSecurityType; @@ -506,7 +513,8 @@ public class WifiNanIfaceAidlImplTest extends WifiBaseTest { ArgumentCaptor<NanRespondToPairingIndicationRequest> reqCaptor = ArgumentCaptor.forClass( NanRespondToPairingIndicationRequest.class); assertTrue(mDut.respondToPairingRequest(tid, 1, true, null, true, - NanPairingRequestType.NAN_PAIRING_SETUP, null, null , 0, 0)); + NanPairingRequestType.NAN_PAIRING_SETUP, null, null , NAN_PAIRING_AKM_PASN, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_256)); verify(mIWifiNanIfaceMock).respondToPairingIndicationRequest(eq((char) tid), reqCaptor.capture()); NanRespondToPairingIndicationRequest request = reqCaptor.getValue(); @@ -518,6 +526,9 @@ public class WifiNanIfaceAidlImplTest extends WifiBaseTest { assertArrayEquals(new byte[0], request.securityConfig.passphrase); assertTrue(request.enablePairingCache); assertArrayEquals(new byte[16], request.pairingIdentityKey); + assertEquals(NanCipherSuiteType.PUBLIC_KEY_PASN_256_MASK, + request.securityConfig.cipherType); + assertEquals(NanPairingAkm.PASN, request.securityConfig.akm); } @Test @@ -527,17 +538,21 @@ public class WifiNanIfaceAidlImplTest extends WifiBaseTest { ArgumentCaptor<NanPairingRequest> reqCaptor = ArgumentCaptor.forClass( NanPairingRequest.class); assertTrue(mDut.initiateNanPairingRequest(tid, 1, peer, null, true, - NanPairingRequestType.NAN_PAIRING_SETUP, null, null , 0, 0)); + NanPairingRequestType.NAN_PAIRING_SETUP, null, "PASSWORD", NAN_PAIRING_AKM_SAE, + WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128)); verify(mIWifiNanIfaceMock).initiatePairingRequest(eq((char) tid), reqCaptor.capture()); NanPairingRequest request = reqCaptor.getValue(); assertEquals(NanPairingRequestType.NAN_PAIRING_SETUP, request.requestType); assertEquals(1, request.peerId); - assertEquals(NanPairingSecurityType.OPPORTUNISTIC, request.securityConfig.securityType); + assertEquals(NanPairingSecurityType.PASSPHRASE, request.securityConfig.securityType); assertArrayEquals(new byte[32], request.securityConfig.pmk); - assertArrayEquals(new byte[0], request.securityConfig.passphrase); + assertArrayEquals("PASSWORD".getBytes(), request.securityConfig.passphrase); assertTrue(request.enablePairingCache); assertArrayEquals(new byte[16], request.pairingIdentityKey); + assertEquals(NanCipherSuiteType.PUBLIC_KEY_PASN_128_MASK, + request.securityConfig.cipherType); + assertEquals(NanPairingAkm.SAE, request.securityConfig.akm); } @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerAidlImplTest.java index 6b541a7bd3..199b0e3313 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiRttControllerAidlImplTest.java @@ -131,7 +131,7 @@ public class WifiRttControllerAidlImplTest extends WifiBaseTest { @Test public void testRangeRequest() throws Exception { int cmdId = 55; - RangingRequest request = RttTestUtils.getDummyRangingRequest((byte) 0); + RangingRequest request = RttTestUtils.getDummyRangingRequestWith11az((byte) 0); // (1) issue range request mDut.rangeRequest(cmdId, request); @@ -175,6 +175,22 @@ public class WifiRttControllerAidlImplTest extends WifiBaseTest { collector.checkThat("entry 2: rtt burst size", rttConfig.numFramesPerBurst, equalTo(RangingRequest.getMaxRttBurstSize())); + rttConfig = halRequest[3]; + collector.checkThat("entry 0: MAC", rttConfig.addr, + equalTo(MacAddress.fromString("00:11:22:33:44:00").toByteArray())); + collector.checkThat("entry 0: rtt type", rttConfig.type, + equalTo(RttType.TWO_SIDED_11AZ_NTB)); + collector.checkThat("entry 0: peer type", rttConfig.peer, equalTo(RttPeerType.AP)); + collector.checkThat("entry 0: lci", rttConfig.mustRequestLci, equalTo(true)); + collector.checkThat("entry 0: lcr", rttConfig.mustRequestLcr, equalTo(true)); + collector.checkThat("entry 0: rtt burst size", rttConfig.numFramesPerBurst, + equalTo(RangingRequest.getMaxRttBurstSize())); + // ntbMinMeasurementTime in units of 100 us + // DEFAULT_NTB_MIN_TIME_BETWEEN_MEASUREMENTS_MICROS = 250000 --> 2500 * 100 us + collector.checkThat("", rttConfig.ntbMinMeasurementTime, equalTo(2500L)); + // ntbMaxMeasurementTime in units of 10 ms + // DEFAULT_NTB_MAX_TIME_BETWEEN_MEASUREMENTS_MICROS = 15000000 --> 1500 * 10 ms + collector.checkThat("", rttConfig.ntbMaxMeasurementTime, equalTo(1500L)); verifyNoMoreInteractions(mIWifiRttControllerMock); } @@ -350,6 +366,63 @@ public class WifiRttControllerAidlImplTest extends WifiBaseTest { } /** + * Validate correct 11az NTB result conversion from HAL to framework. + */ + @Test + public void test11azNtbRangeResults() throws Exception { + int cmdId = 55; + RttResult[] results = new RttResult[1]; + RttResult res = createRttResult(); + res.type = RttType.TWO_SIDED_11AZ_NTB; + res.addr = MacAddress.byteAddrFromStringAddr("05:06:07:08:09:0A"); + res.ntbMaxMeasurementTime = 10; // 10 * 10000 us = 100000 us + res.ntbMinMeasurementTime = 100; // 100 * 100 us = 10000 us + res.numRxSpatialStreams = 2; + res.numTxSpatialStreams = 3; + res.i2rTxLtfRepetitionCount = 3; + res.r2iTxLtfRepetitionCount = 2; + res.status = RttStatus.SUCCESS; + res.distanceInMm = 1500; + res.timeStampInUs = 6000; + res.packetBw = RttBw.BW_80MHZ; + results[0] = res; + + // (1) have the HAL call us with results + mEventCallbackCaptor.getValue().onResults(cmdId, results); + + // (2) verify call to framework + verify(mRangingResultsCallbackMock).onRangingResults(eq(cmdId), mRttResultCaptor.capture()); + + // verify contents of the framework results + List<RangingResult> rttR = mRttResultCaptor.getValue(); + + collector.checkThat("number of entries", rttR.size(), equalTo(1)); + + RangingResult rttResult = rttR.get(0); + collector.checkThat("Type", rttResult.is80211azNtbMeasurement(), equalTo(true)); + collector.checkThat("status", rttResult.getStatus(), + equalTo(WifiRttController.FRAMEWORK_RTT_STATUS_SUCCESS)); + collector.checkThat("mac", rttResult.getMacAddress().toByteArray(), + equalTo(MacAddress.fromString("05:06:07:08:09:0A").toByteArray())); + collector.checkThat("ntbMaxMeasurementTime", + rttResult.getMaxTimeBetweenNtbMeasurementsMicros(), equalTo(100000L)); + collector.checkThat("ntbMinMeasurementTime", + rttResult.getMinTimeBetweenNtbMeasurementsMicros(), equalTo(10000L)); + collector.checkThat("numRxSpatialStreams", rttResult.get80211azNumberOfRxSpatialStreams(), + equalTo(2)); + collector.checkThat("numTxSpatialStreams", rttResult.get80211azNumberOfTxSpatialStreams(), + equalTo(3)); + collector.checkThat("i2rTxLtfRepetitionCount", + rttResult.get80211azInitiatorTxLtfRepetitionsCount(), equalTo(3)); + collector.checkThat("r2iTxLtfRepetitionCount", + rttResult.get80211azResponderTxLtfRepetitionsCount(), equalTo(2)); + collector.checkThat("distanceCm", rttResult.getDistanceMm(), equalTo(1500)); + collector.checkThat("timestamp", rttResult.getRangingTimestampMillis(), equalTo(6L)); + collector.checkThat("channelBw", rttResult.getMeasurementBandwidth(), + equalTo(ScanResult.CHANNEL_WIDTH_80MHZ)); + verifyNoMoreInteractions(mIWifiRttControllerMock); + } + /** * Validate correct cleanup when a null array of results is provided by HAL. */ @Test @@ -428,11 +501,14 @@ public class WifiRttControllerAidlImplTest extends WifiBaseTest { cap.lciSupported = true; cap.lcrSupported = true; cap.responderSupported = true; // unused + cap.ntbInitiatorSupported = true; cap.preambleSupport = RttPreamble.LEGACY | RttPreamble.HT | RttPreamble.VHT | RttPreamble.HE; + cap.azPreambleSupport = cap.preambleSupport; cap.bwSupport = RttBw.BW_5MHZ | RttBw.BW_10MHZ | RttBw.BW_20MHZ | RttBw.BW_40MHZ | RttBw.BW_80MHZ | RttBw.BW_160MHZ; + cap.azBwSupport = cap.bwSupport; cap.mcVersion = 1; // unused return cap; diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java index 668e105e53..28c2d3d7c7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceAidlImplTest.java @@ -16,9 +16,12 @@ package com.android.server.wifi.hal; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -68,6 +71,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.nio.charset.StandardCharsets; +import java.util.BitSet; import java.util.List; import java.util.Random; @@ -96,10 +100,9 @@ public class WifiStaIfaceAidlImplTest extends WifiBaseTest { IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN | IWifiStaIface.FeatureSetMask.LINK_LAYER_STATS ); - long expected = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mDut.halToFrameworkStaFeatureSet(halFeatures)); + BitSet expected = createCapabilityBitset( + WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + assertTrue(expected.equals(mDut.halToFrameworkStaFeatureSet(halFeatures))); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java index d41ba3af2e..21e8c844f7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hal/WifiStaIfaceHidlImplTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi.hal; +import static com.android.server.wifi.TestUtil.createCapabilityBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -68,6 +70,7 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.Collections; import java.util.List; import java.util.Random; @@ -143,10 +146,9 @@ public class WifiStaIfaceHidlImplTest extends WifiBaseTest { IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS ); - long expected = ( - WifiManager.WIFI_FEATURE_SCANNER - | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mDut.halToFrameworkStaIfaceCapability(caps)); + BitSet expected = createCapabilityBitset( + WifiManager.WIFI_FEATURE_SCANNER, WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + assertTrue(expected.equals(mDut.halToFrameworkStaIfaceCapability(caps))); } /** diff --git a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java index 4e59dda89b..a77c3db361 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkNominateHelperTest.java @@ -266,8 +266,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { assertEquals(RANDOMIZATION_NONE, addedConfig.getValue().macRandomizationSetting); verify(mWifiConfigManager).enableNetwork( eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); verify(mWifiConfigManager).updateScanDetailForNetwork( eq(TEST_NETWORK_ID), any(ScanDetail.class)); @@ -320,8 +318,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { assertTrue(addedConfig.getValue().isHomeProviderNetwork); verify(mWifiConfigManager).enableNetwork( eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); verify(mWifiConfigManager).updateScanDetailForNetwork( eq(TEST_NETWORK_ID), any(ScanDetail.class)); } @@ -363,8 +359,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { assertFalse(addedConfig.getValue().isHomeProviderNetwork); verify(mWifiConfigManager).enableNetwork( eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); verify(mWifiConfigManager).updateScanDetailForNetwork( eq(TEST_NETWORK_ID), any(ScanDetail.class)); } @@ -465,13 +459,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { .getPasspointNetworkCandidates(scanDetails); assertEquals(1, candidates.size()); - - // Verify network candidate information is updated. - ArgumentCaptor<ScanResult> updatedCandidateScanResult = - ArgumentCaptor.forClass(ScanResult.class); - verify(mWifiConfigManager).setNetworkCandidateScanResult(eq(TEST_NETWORK_ID), - updatedCandidateScanResult.capture(), anyInt(), any()); - assertEquals(TEST_BSSID2, updatedCandidateScanResult.getValue().BSSID); ArgumentCaptor<ScanDetail> updatedCandidateScanDetail = ArgumentCaptor.forClass(ScanDetail.class); verify(mWifiConfigManager).updateScanDetailForNetwork(eq(TEST_NETWORK_ID), @@ -864,8 +851,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { assertTrue(addedConfig.getValue().isHomeProviderNetwork); verify(mWifiConfigManager).enableNetwork( eq(TEST_NETWORK_ID), eq(false), eq(TEST_UID), any()); - verify(mWifiConfigManager).setNetworkCandidateScanResult( - eq(TEST_NETWORK_ID), any(ScanResult.class), anyInt(), any()); verify(mWifiConfigManager).updateScanDetailForNetwork( eq(TEST_NETWORK_ID), any(ScanDetail.class)); @@ -934,10 +919,6 @@ public class PasspointNetworkNominateHelperTest extends WifiBaseTest { verify(mWifiConfigManager) .enableNetwork(eq(TEST_NETWORK_ID2), eq(false), anyInt(), any()); verify(mWifiConfigManager) - .setNetworkCandidateScanResult(eq(TEST_NETWORK_ID), any(), anyInt(), any()); - verify(mWifiConfigManager) - .setNetworkCandidateScanResult(eq(TEST_NETWORK_ID2), any(), anyInt(), any()); - verify(mWifiConfigManager) .updateScanDetailForNetwork(eq(TEST_NETWORK_ID), eq(scanDetails.get(0))); verify(mWifiConfigManager) .updateScanDetailForNetwork(eq(TEST_NETWORK_ID2), eq(scanDetails.get(0))); diff --git a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java index dba7220a05..213757cedb 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java @@ -29,6 +29,7 @@ import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_AD import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_DEVICE_NAME; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_P2P_PENDING_FACTORY_RESET; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; +import static com.android.server.wifi.p2p.WifiP2pServiceImpl.IPC_DHCP_RESULTS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -78,6 +79,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.location.LocationManager; import android.net.ConnectivityManager; +import android.net.DhcpResultsParcelable; import android.net.InetAddresses; import android.net.LinkAddress; import android.net.MacAddress; @@ -202,6 +204,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { private static final String thisDeviceName = "thisDeviceName"; private static final String ANONYMIZED_DEVICE_ADDRESS = "02:00:00:00:00:00"; private static final String TEST_PACKAGE_NAME = "com.p2p.test"; + private static final String TEST_PACKAGE2_NAME = "com.p2p.test2"; private static final String TEST_NETWORK_NAME = "DIRECT-xy-NEW"; private static final String TEST_ANDROID_ID = "314Deadbeef"; private static final String[] TEST_REQUIRED_PERMISSIONS_T = @@ -230,8 +233,10 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { private BroadcastReceiver mTetherStateReceiver; private BroadcastReceiver mUserRestrictionReceiver; private Handler mClientHandler; + private Handler mClient2Handler; private Messenger mP2pStateMachineMessenger; private Messenger mClientMessenger; + private Messenger mClient2Messenger; private WifiP2pServiceImpl mWifiP2pServiceImpl; private TestLooper mClientHanderLooper; private TestLooper mLooper; @@ -252,6 +257,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { private TetheringManager.TetheringEventCallback mTetheringEventCallback; private Bundle mExtras = new Bundle(); private IWifiP2pListener mP2pListener = mock(IWifiP2pListener.class); + private IWifiP2pListener mP2pListener2 = mock(IWifiP2pListener.class); private ArgumentCaptor<WifiSettingsConfigStore.OnSettingsChangedListener> mD2DAllowedSettingsCallbackCaptor = ArgumentCaptor.forClass(WifiSettingsConfigStore.OnSettingsChangedListener.class); @@ -652,9 +658,10 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { /** * Send WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT. */ - private void sendGroupRemovedMsg() throws Exception { + private void sendGroupRemovedMsg(WifiP2pGroup group) throws Exception { Message msg = Message.obtain(); msg.what = WifiP2pMonitor.P2P_GROUP_REMOVED_EVENT; + msg.obj = group; mP2pStateMachineMessenger.send(Message.obtain(msg)); mLooper.dispatchAll(); } @@ -1383,7 +1390,9 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { generatorTestData(); mClientHanderLooper = new TestLooper(); mClientHandler = spy(new Handler(mClientHanderLooper.getLooper())); + mClient2Handler = spy(new Handler(mClientHanderLooper.getLooper())); mClientMessenger = new Messenger(mClientHandler); + mClient2Messenger = new Messenger(mClient2Handler); mLooper = new TestLooper(); when(mContext.getSystemService(Context.ALARM_SERVICE)) @@ -1517,6 +1526,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { when(mDeviceConfigFacade.isP2pFailureBugreportEnabled()).thenReturn(false); when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager); when(mP2pListener.asBinder()).thenReturn(mock(IBinder.class)); + when(mP2pListener2.asBinder()).thenReturn(mock(IBinder.class)); mWifiP2pServiceImpl = new WifiP2pServiceImpl(mContext, mWifiInjector); if (supported) { @@ -1525,20 +1535,24 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { // * LocationManager.MODE_CHANGED_ACTION -- always // * TetheringManager.ACTION_TETHER_STATE_CHANGED -- < S // * UserManager.ACTION_USER_RESTRICTIONS_CHANGED -- >= T + verify(mContext).registerReceiverForAllUsers( + mBcastRxCaptor.capture(), + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + eq(null), any(Handler.class)); if (SdkLevel.isAtLeastT()) { - verify(mContext, times(3)).registerReceiver(mBcastRxCaptor.capture(), + verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(), any(IntentFilter.class)); mUserRestrictionReceiver = mBcastRxCaptor.getAllValues().get(2); } else if (SdkLevel.isAtLeastS()) { - verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(), + verify(mContext).registerReceiver(mBcastRxCaptor.capture(), any(IntentFilter.class)); } else { - verify(mContext, times(3)).registerReceiver(mBcastRxCaptor.capture(), + verify(mContext, times(2)).registerReceiver(mBcastRxCaptor.capture(), any(IntentFilter.class)); mTetherStateReceiver = mBcastRxCaptor.getAllValues().get(2); } - mWifiStateChangedReceiver = mBcastRxCaptor.getAllValues().get(0); - mLocationModeReceiver = mBcastRxCaptor.getAllValues().get(1); + mWifiStateChangedReceiver = mBcastRxCaptor.getAllValues().get(1); + mLocationModeReceiver = mBcastRxCaptor.getAllValues().get(0); verify(mWifiSettingsConfigStore).registerChangeListener( eq(D2D_ALLOWED_WHEN_INFRA_STA_DISABLED), mD2DAllowedSettingsCallbackCaptor.capture(), any()); @@ -1558,9 +1572,11 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { mStaticMockSession = mockitoSession() .mockStatic(NetworkInterface.class) .mockStatic(Process.class) + .mockStatic(WifiInjector.class) .startMocking(); lenient().when(NetworkInterface.getByName(eq(IFACE_NAME_P2P))) .thenReturn(mP2pNetworkInterface); + when(WifiInjector.getInstance()).thenReturn(mWifiInjector); when(mLayoutInflater.cloneInContext(any())).thenReturn(mLayoutInflater); when(mLayoutInflater.inflate(anyInt(), any())).thenReturn(mView); when(mLayoutInflater.inflate(anyInt(), any(), anyBoolean())).thenReturn(mView); @@ -1579,6 +1595,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { mWifiP2pServiceImpl.handleBootCompleted(); if (SdkLevel.isAtLeastT()) { mWifiP2pServiceImpl.registerWifiP2pListener(mP2pListener, TEST_PACKAGE_NAME, mExtras); + mWifiP2pServiceImpl.registerWifiP2pListener(mP2pListener2, TEST_PACKAGE2_NAME, mExtras); } } @@ -2956,6 +2973,407 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { anyInt(), anyInt(), anyString(), eq(true)); } + /** + * Sets up the environment for P2P Ownership test where Client1 is the group owner. + */ + private void groupOwnershipConfigTestSetup() throws Exception { + assumeTrue(SdkLevel.isAtLeastV()); + when(mFeatureFlags.p2pOwnership()).thenReturn(true); + forceP2pEnabled(mClient1); + sendChannelInfoUpdateMsg(TEST_PACKAGE2_NAME, "testFeature", mClient2, mClient2Messenger); + + // group created by client1 + when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(true); + sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); + verify(mWifiNative).p2pGroupAdd(any(), eq(false)); + assertTrue(mClientHandler.hasMessages(WifiP2pManager.CREATE_GROUP_SUCCEEDED)); + assertFalse(mClient2Handler.hasMessages(WifiP2pManager.CREATE_GROUP_SUCCEEDED)); + + WifiP2pGroup group = new WifiP2pGroup(); + group.setNetworkName("DIRECT-test"); + group.setOwner(new WifiP2pDevice("thisDeviceMac")); + group.setIsGroupOwner(true); + group.setInterface(IFACE_NAME_P2P); + sendGroupStartedMsg(group); + simulateTetherReady(); + reset(mClientHandler); + } + + /** + * Sets up the environment for P2P Ownership test with WPS group. + */ + private void groupOwnershipWpsTestSetup() throws Exception { + assumeTrue(SdkLevel.isAtLeastV()); + mWifiP2pServiceImpl.registerWifiP2pListener(mP2pListener2, TEST_PACKAGE2_NAME, mExtras); + forceP2pEnabled(mClient1); + sendChannelInfoUpdateMsg(TEST_PACKAGE2_NAME, "testFeature", mClient2, mClient2Messenger); + + // WPS group created + WifiP2pGroup group = new WifiP2pGroup(); + group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); + group.setNetworkName(TEST_NETWORK_NAME); + group.setOwner(new WifiP2pDevice("thisDeviceMac")); + group.setIsGroupOwner(true); + group.setInterface(IFACE_NAME_P2P); + sendGroupStartedMsg(group); + simulateTetherReady(); + } + + /** Verify that only the group owner can send an invitation connection */ + @Test + public void testGroupOwnershipConfigJoinInvite() throws Exception { + groupOwnershipConfigTestSetup(); + + // client2 cannot send an invitation to join + sendConnectMsg(mClient2Messenger, mTestWifiP2pPeerConfig); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_FAILED, message.what); + assertEquals(WifiP2pManager.BUSY, message.arg1); + + // client1 can send an invitation to join + when(mWifiNative.p2pInvite(any(), any())).thenReturn(true); + mockPeersList(); + sendConnectMsg(mClientMessenger, mTestWifiP2pPeerConfig); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_SUCCEEDED, message.what); + } + + /** Verify that any client can send an invitation connection */ + @Test + public void testGroupOwnershipWpsJoinInvite() throws Exception { + groupOwnershipWpsTestSetup(); + + // client1 can send an invitation to join + when(mWifiNative.p2pInvite(any(), any())).thenReturn(true); + mockPeersList(); + sendConnectMsg(mClientMessenger, mTestWifiP2pPeerConfig); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_SUCCEEDED, message.what); + + // client2 can send an invitation to join + sendConnectMsg(mClient2Messenger, mTestWifiP2pPeerConfig); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CONNECT_SUCCEEDED, message.what); + } + + /** Verify that only the group owner can cancel an invitation connection */ + @Test + public void testGroupOwnershipConfigCancelInvitationConnect() throws Exception { + groupOwnershipConfigTestSetup(); + + // client2 cannot cancel invitation connection + sendSimpleMsg(mClient2Messenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_FAILED, message.what); + assertEquals(WifiP2pManager.BUSY, message.arg1); + + // client1 can cancel invitation connection + sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); + } + + /** Verify that any client can cancel an invitation connection */ + @Test + public void testGroupOwnershipWpsCancelInvitationConnect() throws Exception { + groupOwnershipWpsTestSetup(); + + // client1 can cancel invitation connection + sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); + + // client2 can cancel invitation connection + sendSimpleMsg(mClient2Messenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); + } + + /** Verify that only the client that initiated the connection can cancel it */ + @Test + public void testGroupOwnershipConfigCancelConnect() throws Exception { + assumeTrue(SdkLevel.isAtLeastV()); + when(mFeatureFlags.p2pOwnership()).thenReturn(true); + forceP2pEnabled(mClient1); + sendChannelInfoUpdateMsg(TEST_PACKAGE2_NAME, "testFeature", mClient2, mClient2Messenger); + + // group created by client1 + when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(true); + sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger); + verify(mWifiNative).p2pGroupAdd(any(), eq(false)); + reset(mClientHandler); + + // client2 cannot cancel connection + sendSimpleMsg(mClient2Messenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_FAILED, message.what); + assertEquals(WifiP2pManager.BUSY, message.arg1); + + // client1 can cancel connection + sendSimpleMsg(mClientMessenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); + } + + /** Verify that any client can cancel an ongoing WPS connection */ + @Test + public void testGroupOwnershipWpsCancelConnect() throws Exception { + assumeTrue(SdkLevel.isAtLeastV()); + when(mFeatureFlags.p2pOwnership()).thenReturn(true); + forceP2pEnabled(mClient1); + sendChannelInfoUpdateMsg(TEST_PACKAGE2_NAME, "testFeature", mClient2, mClient2Messenger); + + // connection initiated by client1 + when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true); + mockEnterGroupNegotiationState(); + + // client2 can cancel connection + sendSimpleMsg(mClient2Messenger, WifiP2pManager.CANCEL_CONNECT); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.CANCEL_CONNECT_SUCCEEDED, message.what); + } + + /** Verify that only the group owner can remove the group */ + @Test + public void testGroupOwnershipConfigRemoveGroup() throws Exception { + groupOwnershipConfigTestSetup(); + + // client2 cannot remove group + sendSimpleMsg(mClient2Messenger, WifiP2pManager.REMOVE_GROUP); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.REMOVE_GROUP_FAILED, message.what); + assertEquals(WifiP2pManager.BUSY, message.arg1); + + // client1 can remove group + when(mWifiNative.p2pGroupRemove(eq(IFACE_NAME_P2P))).thenReturn(true); + sendSimpleMsg(mClientMessenger, WifiP2pManager.REMOVE_GROUP); + verify(mWifiNative).p2pGroupRemove(eq(IFACE_NAME_P2P)); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.REMOVE_GROUP_SUCCEEDED, message.what); + } + + /** Verify that any client can remove the group */ + @Test + public void testGroupOwnershipWpsRemoveGroup() throws Exception { + groupOwnershipWpsTestSetup(); + + // client2 can remove group + when(mWifiNative.p2pGroupRemove(eq(IFACE_NAME_P2P))).thenReturn(true); + sendSimpleMsg(mClient2Messenger, WifiP2pManager.REMOVE_GROUP); + verify(mWifiNative).p2pGroupRemove(eq(IFACE_NAME_P2P)); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + assertEquals(WifiP2pManager.REMOVE_GROUP_SUCCEEDED, message.what); + } + + /** Verify that only the group owner can get group info */ + @Test + public void testGroupOwnershipConfigGetGroupInformation() throws Exception { + groupOwnershipConfigTestSetup(); + + // client2 cannot get P2P group info + sendRequestGroupInfoMsg(mClient2Messenger); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); + WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; + assertNull(wifiP2pGroup); + + // client1 can get P2P group info + sendRequestGroupInfoMsg(mClientMessenger); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); + wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; + assertNotNull(wifiP2pGroup); + } + + /** Verify that any client can get group info */ + @Test + public void testGroupOwnershipWpsGetGroupInformation() throws Exception { + groupOwnershipWpsTestSetup(); + + // client1 can get P2P group info + sendRequestGroupInfoMsg(mClientMessenger); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); + WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; + assertNotNull(wifiP2pGroup); + + // client2 can get P2P group info + sendRequestGroupInfoMsg(mClient2Messenger); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + assertEquals(WifiP2pManager.RESPONSE_GROUP_INFO, mMessageCaptor.getValue().what); + wifiP2pGroup = (WifiP2pGroup) mMessageCaptor.getValue().obj; + assertNotNull(wifiP2pGroup); + } + + /** Verify that only the group owner can get connection info */ + @Test + public void testGroupOwnershipConfigGetConnectionInfo() throws Exception { + groupOwnershipConfigTestSetup(); + + // client2 cannot get P2P connection info + sendSimpleMsg(mClient2Messenger, WifiP2pManager.REQUEST_CONNECTION_INFO); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + WifiP2pInfo info = (WifiP2pInfo) message.obj; + assertEquals(WifiP2pManager.RESPONSE_CONNECTION_INFO, message.what); + assertEquals((new WifiP2pInfo()).toString(), info.toString()); + + // client1 can get P2P connection info + sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_CONNECTION_INFO); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + info = (WifiP2pInfo) message.obj; + assertEquals(WifiP2pManager.RESPONSE_CONNECTION_INFO, mMessageCaptor.getValue().what); + assertTrue(info.groupFormed); + } + + /** Verify that any client can get connection info */ + @Test + public void testGroupOwnershipWpsGetConnectionInfo() throws Exception { + groupOwnershipWpsTestSetup(); + + // client1 can get P2P connection info + sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_CONNECTION_INFO); + verify(mClientHandler).sendMessage(mMessageCaptor.capture()); + Message message = mMessageCaptor.getValue(); + WifiP2pInfo info = (WifiP2pInfo) message.obj; + assertEquals(WifiP2pManager.RESPONSE_CONNECTION_INFO, mMessageCaptor.getValue().what); + assertTrue(info.groupFormed); + + // client2 can get P2P connection info + sendSimpleMsg(mClient2Messenger, WifiP2pManager.REQUEST_CONNECTION_INFO); + verify(mClient2Handler).sendMessage(mMessageCaptor.capture()); + message = mMessageCaptor.getValue(); + info = (WifiP2pInfo) message.obj; + assertEquals(WifiP2pManager.RESPONSE_CONNECTION_INFO, mMessageCaptor.getValue().what); + assertTrue(info.groupFormed); + } + + /** Verify that only the group owner receives the connection changed broadcast */ + @Test + public void testGroupOwnershipConfigBroadcast() throws Exception { + groupOwnershipConfigTestSetup(); + + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext, atLeastOnce()).sendBroadcast(intentCaptor.capture(), any(), any()); + + ArrayList<Intent> intentArrayList = new ArrayList<>(); + for (int i = 0; i < intentCaptor.getAllValues().size(); i++) { + Intent intent = intentCaptor.getAllValues().get(i); + if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { + intentArrayList.add(intent); + } + } + // Connection changed broadcast is sent 3 times: + // 1. Entering P2pEnabledState + // 2. Entering GroupCreatingState + // 3. Entering GroupCreatedState + // Each time, sendBroadcast is called twice (refer sendBroadcastWithExcludedPermissions) + // Verify group created broadcast only sent to client1 + Intent intent = intentArrayList.get(4); + assertEquals(TEST_PACKAGE_NAME, intent.getPackage()); + // Verify broadcast sent to NEARBY_WIFI_DEVICES apps do not have the package name set + intent = intentArrayList.get(5); + assertNull(intent.getPackage()); + } + + /** Verify that all clients receive the connection changed broadcast */ + @Test + public void testGroupOwnershipWpsBroadcast() throws Exception { + groupOwnershipWpsTestSetup(); + + WifiP2pDevice connectedClientDevice = new WifiP2pDevice(mTestWifiP2pDevice); + connectedClientDevice.setInterfaceMacAddress(MacAddress.fromString(PEER_INTERFACE_ADDRESS)); + sendApStaConnectedEvent(connectedClientDevice); + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mContext, atLeastOnce()).sendBroadcast(intentCaptor.capture(), any(), any()); + + ArrayList<Intent> intentArrayList = new ArrayList<>(); + for (int i = 0; i < intentCaptor.getAllValues().size(); i++) { + Intent intent = intentCaptor.getAllValues().get(i); + if (intent.getAction().equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { + intentArrayList.add(intent); + } + } + // Connection changed broadcast is sent 3 times: + // 1. Entering P2pEnabledState + // 2. Entering GroupCreatingState + // 3. Peer connection in GroupCreatedState + // Each time, sendBroadcast is called twice (refer sendBroadcastWithExcludedPermissions) + // Verify group created broadcast sent to all clients + Intent intent = intentArrayList.get(4); + assertNull(intent.getPackage()); + } + + /** Verify that only the group owner receives the group related callback */ + @Test + public void testGroupOwnershipConfigP2pListener() throws Exception { + groupOwnershipConfigTestSetup(); + + verify(mP2pListener).onGroupCreated(any(), any()); + verify(mP2pListener2, never()).onGroupCreated(any(), any()); + + WifiP2pDevice peerClientDevice = new WifiP2pDevice(); + peerClientDevice.deviceName = "peerClientDeviceName"; + peerClientDevice.deviceAddress = "11:22:33:aa:bb:cc"; + peerClientDevice.setInterfaceMacAddress(MacAddress.fromString(PEER_INTERFACE_ADDRESS)); + sendSimpleMsg(null, WifiP2pMonitor.AP_STA_CONNECTED_EVENT, peerClientDevice); + verify(mP2pListener).onPeerClientJoined(any(), any()); + verify(mP2pListener2, never()).onPeerClientJoined(any(), any()); + + sendSimpleMsg(null, WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, peerClientDevice); + verify(mP2pListener).onPeerClientDisconnected(any(), any()); + verify(mP2pListener2, never()).onPeerClientDisconnected(any(), any()); + + sendSimpleMsg(null, WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT, TEST_GROUP_FREQUENCY); + verify(mP2pListener).onFrequencyChanged(any(), any()); + verify(mP2pListener2, never()).onFrequencyChanged(any(), any()); + } + + /** Verify that all clients receive the group related callback */ + @Test + public void testGroupOwnershipWpsP2pListener() throws Exception { + groupOwnershipWpsTestSetup(); + + DhcpResultsParcelable dhcpResults = new DhcpResultsParcelable(); + dhcpResults.serverAddress = P2P_GO_IP; + sendSimpleMsg(mClientMessenger, IPC_DHCP_RESULTS, dhcpResults); + verify(mP2pListener).onGroupCreated(any(), any()); + verify(mP2pListener2).onGroupCreated(any(), any()); + + WifiP2pDevice connectedClientDevice = new WifiP2pDevice(mTestWifiP2pDevice); + connectedClientDevice.setInterfaceMacAddress(MacAddress.fromString(PEER_INTERFACE_ADDRESS)); + sendApStaConnectedEvent(connectedClientDevice); + verify(mP2pListener).onPeerClientJoined(any(), any()); + verify(mP2pListener2).onPeerClientJoined(any(), any()); + + // Need to connect a second peer device before testing disconnect to avoid removing group + WifiP2pDevice secondPeerDevice = new WifiP2pDevice(connectedClientDevice); + secondPeerDevice.deviceAddress = "11:22:33:aa:bb:cc"; + sendApStaConnectedEvent(secondPeerDevice); + sendSimpleMsg(null, WifiP2pMonitor.AP_STA_DISCONNECTED_EVENT, connectedClientDevice); + verify(mP2pListener).onPeerClientDisconnected(any(), any()); + verify(mP2pListener2).onPeerClientDisconnected(any(), any()); + + sendSimpleMsg(null, WifiP2pMonitor.P2P_FREQUENCY_CHANGED_EVENT, TEST_GROUP_FREQUENCY); + verify(mP2pListener).onFrequencyChanged(any(), any()); + verify(mP2pListener2).onFrequencyChanged(any(), any()); + } + /** Verify the p2p randomized MAC feature is enabled if OEM supports it. */ @Test public void testP2pRandomMacWithOemSupport() throws Exception { @@ -3168,7 +3586,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { WifiP2pGroup groupCaptured = groupCaptor.getValue(); assertEquals(mTestWifiP2pNewPersistentGoGroup.toString(), groupCaptured.toString()); - sendGroupRemovedMsg(); + sendGroupRemovedMsg(groupCaptured); verify(mWifiP2pMetrics).endGroupEvent(); } @@ -7197,6 +7615,33 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { WpsInfo.PBC, WifiP2pManager.CONNECTION_REQUEST_ACCEPT); } + /** + * Verify sunny scenario for setConnectionRequestResult show pin event. + */ + @Test + public void testSetConnectionRequestResultSuccessShowPin() throws Exception { + assumeTrue(SdkLevel.isAtLeastS()); + forceP2pEnabled(mClient1); + Binder binder = new Binder(); + verifyAddExternalApprover(binder, true, true, + MacAddress.fromString(mTestWifiP2pDevice.deviceAddress)); + + WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent(); + pdEvent.device = mTestWifiP2pDevice; + pdEvent.pin = "pin"; + sendSimpleMsg(null, + WifiP2pMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT, + pdEvent); + mLooper.dispatchAll(); + + sendSetConnectionRequestResultMsg(mClientMessenger, + MacAddress.fromString(mTestWifiP2pDevice.deviceAddress), + WifiP2pManager.CONNECTION_REQUEST_ACCEPT, binder); + + verify(mWifiNative).p2pConnect(any(), anyBoolean()); + verify(mWifiNative, never()).p2pStopFind(); + } + private void verifyMultiApproverMatch(List<MacAddress> addresses, MacAddress expectedMatch) throws Exception { when(mWifiPermissionsUtil.checkManageWifiNetworkSelectionPermission(anyInt())) @@ -7785,7 +8230,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { verify(mWifiP2pMetrics).startGroupEvent(group); verify(mWifiNative).p2pStopFind(); verify(mWifiNative).p2pExtListen(eq(false), anyInt(), anyInt(), eq(null)); - sendGroupRemovedMsg(); + sendGroupRemovedMsg(group); //force to back disabled state mockEnterDisabledState(); @@ -8125,7 +8570,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { p2pGroupCaptor.capture()); assertEquals(TEST_GROUP_FREQUENCY, p2pGroupCaptor.getValue().getFrequency()); - sendGroupRemovedMsg(); + sendGroupRemovedMsg(p2pGroup); mockEnterDisabledState(); mLooper.dispatchAll(); verify(mP2pListener).onGroupRemoved(); @@ -8139,6 +8584,35 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { } /** + * Verify that p2p listener group created callback is sent for negotiated GO + */ + @Test + public void testP2pListenerWpsGroupCreated() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + forceP2pEnabled(mClient1); + + WifiP2pGroup group = new WifiP2pGroup(); + group.setNetworkId(WifiP2pGroup.NETWORK_ID_PERSISTENT); + group.setNetworkName(TEST_NETWORK_NAME); + group.setOwner(new WifiP2pDevice("thisDeviceMac")); + group.setIsGroupOwner(true); + group.setInterface(IFACE_NAME_P2P); + sendGroupStartedMsg(group); + simulateTetherReady(); + ArgumentCaptor<WifiP2pInfo> p2pInfoCaptor = ArgumentCaptor.forClass(WifiP2pInfo.class); + ArgumentCaptor<WifiP2pGroup> p2pGroupCaptor = ArgumentCaptor.forClass(WifiP2pGroup.class); + WifiP2pDevice peerClientDevice = new WifiP2pDevice(); + peerClientDevice.deviceName = "peerClientDeviceName"; + peerClientDevice.deviceAddress = "11:22:33:aa:bb:cc"; + peerClientDevice.setInterfaceMacAddress(MacAddress.fromString(PEER_INTERFACE_ADDRESS)); + sendSimpleMsg(null, WifiP2pMonitor.AP_STA_CONNECTED_EVENT, peerClientDevice); + verify(mP2pListener).onGroupCreated(p2pInfoCaptor.capture(), p2pGroupCaptor.capture()); + assertEquals(TEST_NETWORK_NAME, p2pGroupCaptor.getValue().getNetworkName()); + assertFalse(p2pGroupCaptor.getValue().isClientListEmpty()); + assertTrue(p2pInfoCaptor.getValue().groupFormed); + } + + /** * Verify that p2p disable when the D2d allowed value changes to false */ @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java index c96116914d..cc570c77c7 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java @@ -32,6 +32,7 @@ import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; @@ -51,7 +52,6 @@ import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.PackageManager; import android.location.LocationManager; import android.net.MacAddress; @@ -252,8 +252,11 @@ public class RttServiceImplTest extends WifiBaseTest { mMockLooper.dispatchAll(); ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); - verify(mockContext, times(2)).registerReceiver(bcastRxCaptor.capture(), - any(IntentFilter.class)); + verify(mockContext).registerReceiver(bcastRxCaptor.capture(), + argThat(filter -> filter.hasAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED))); + verify(mockContext).registerReceiverForAllUsers(bcastRxCaptor.capture(), + argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION)), + eq(null), any(Handler.class)); mPowerBcastReceiver = bcastRxCaptor.getAllValues().get(0); mLocationModeReceiver = bcastRxCaptor.getAllValues().get(1); diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java index 2ddeeeb03e..1e7df0db7a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java @@ -77,6 +77,38 @@ public class RttTestUtils { } /** + * Returns a placeholder ranging request with 4 requests and a non-default in-range burst size: + * - First: 802.11mc capable + * - Second: 802.11mc not capable + * - Third: Aware peer + * - Fourth: 802.11az & 802.11mc capable + */ + public static RangingRequest getDummyRangingRequestWith11az(byte lastMacByte) { + RangingRequest.Builder builder = new RangingRequest.Builder(); + + ScanResult scan1 = new ScanResult(); + scan1.BSSID = "00:01:02:03:04:" + String.format("%02d", lastMacByte); + scan1.setFlag(ScanResult.FLAG_80211mc_RESPONDER); + scan1.channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ; + ScanResult scan2 = new ScanResult(); + scan2.BSSID = "0A:0B:0C:0D:0E:" + String.format("%02d", lastMacByte); + scan2.channelWidth = ScanResult.CHANNEL_WIDTH_20MHZ; + MacAddress mac1 = MacAddress.fromString("08:09:08:07:06:05"); + + builder.addAccessPoint(scan1); + builder.addNon80211mcCapableAccessPoint(scan2); + // Changing default RTT burst size to a valid, but maximum, value + builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize()); + builder.addWifiAwarePeer(mac1); + // Add 11az & 11mc supported AP + scan1.BSSID = "00:11:22:33:44:" + String.format("%02d", lastMacByte); + scan1.setFlag(ScanResult.FLAG_80211mc_RESPONDER); + scan1.setFlag(ScanResult.FLAG_80211az_NTB_RESPONDER); + scan1.channelWidth = ScanResult.CHANNEL_WIDTH_40MHZ; + builder.addAccessPoint(scan1); + return builder.build(); + } + /** * Returns a placeholder ranging request with 11mc request with a specified burst size. */ public static RangingRequest getDummyRangingRequestMcOnly(byte lastMacByte, int rttBurstSize) { diff --git a/service/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java index 3d0b4e5579..469f505713 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/scanner/BaseWifiScannerImplTest.java @@ -484,9 +484,8 @@ public abstract class BaseWifiScannerImplTest extends WifiBaseTest { mLooper.dispatchAll(); - for (ScanResult result : fullResults) { - order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); - } + order.verify(eventHandler).onFullScanResults(any(), eq(0)); + order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); assertScanDataEquals(scanData, mScanner.getLatestSingleScanResults()); @@ -551,9 +550,7 @@ public abstract class BaseWifiScannerImplTest extends WifiBaseTest { mLooper.dispatchAll(); if (expectFullResults) { - for (ScanResult result : results.getRawScanResults()) { - order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); - } + order.verify(eventHandler).onFullScanResults(any(), eq(0)); } order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); diff --git a/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java b/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java index b8f3a6bd46..ff8bcfb8fd 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/scanner/WifiScanningServiceTest.java @@ -461,6 +461,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { String serviceDump = dumpService(); Pattern logLineRegex = Pattern.compile("^.+" + type + ": ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME + + ", attributionTag=" + TEST_FEATURE_ID + ", Mock for Stub, hashCode: \\d+\\]", Pattern.MULTILINE); assertTrue("dump did not contain log with {" + logLineRegex @@ -473,6 +474,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { String extraPattern = extra == null ? "" : "," + extra; Pattern logLineRegex = Pattern.compile("^.+" + callback + ": ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME + + ", attributionTag=" + TEST_FEATURE_ID + ", Mock for Stub, hashCode: \\d+\\]" + extraPattern + "$", Pattern.MULTILINE); assertTrue("dump did not contain callback log with callback {" + logLineRegex @@ -2178,7 +2180,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { verifyNoMoreInteractions(client.listener); verifyNoMoreInteractions(client1.listener); assertDumpContainsRequestLog("registerScanListener"); - assertDumpContainsCallbackLog("singleScanResults", + assertDumpContainsCallbackLog("singleScanResults listener", "results=" + results.getScanData().getResults().length); } @@ -2314,9 +2316,9 @@ public class WifiScanningServiceTest extends WifiBaseTest { client.verifyScanResultsReceived(results2and3.getScanData()); assertDumpContainsRequestLog("registerScanListener"); - assertDumpContainsCallbackLog("singleScanResults", + assertDumpContainsCallbackLog("singleScanResults listener", "results=" + results1.getRawScanResults().length); - assertDumpContainsCallbackLog("singleScanResults", + assertDumpContainsCallbackLog("singleScanResults listener", "results=" + results2and3.getRawScanResults().length); } @@ -2754,6 +2756,7 @@ public class WifiScanningServiceTest extends WifiBaseTest { Pattern logLineRegex = Pattern.compile( "^.+" + "Successfully stopped all requests for client " + "ClientInfo\\[uid=\\d+, package=" + TEST_PACKAGE_NAME + + ", attributionTag=" + TEST_FEATURE_ID + ", Mock for Stub, hashCode: \\d+\\]", Pattern.MULTILINE); assertTrue("dump did not contain log with [" + logLineRegex + "]\n" + serviceDump + "\n", @@ -2922,6 +2925,28 @@ public class WifiScanningServiceTest extends WifiBaseTest { client.verifyPnoNetworkFoundReceived(scanResults.getRawScanResults()); } + @Test + public void testPnoStartStopBackToBack() throws Exception { + mWifiScanningServiceImpl.startService(); + mLooper.dispatchAll(); + assertTrue(mWifiScanningServiceImpl.setScanningEnabled(true, 0, TEST_PACKAGE_NAME)); + mLooper.dispatchAll(); + + TestClient client = new TestClient(); + + // removing a unregistered client should not crash + mWifiScanningServiceImpl.stopPnoScan(client.listener, TEST_PACKAGE_NAME, null); + mLooper.dispatchAll(); + + // back to back start and stop should work + mWifiScanningServiceImpl.startPnoScan(client.listener, new WifiScanner.ScanSettings(), + new WifiScanner.PnoSettings(), TEST_PACKAGE_NAME, null); + mWifiScanningServiceImpl.stopPnoScan(client.listener, TEST_PACKAGE_NAME, null); + mLooper.dispatchAll(); + client.verifyLinkedToDeath(); + client.verifyUnlinkedToDeath(); + } + /** * Verifies that only clients with NETWORK_STACK permission can call restricted APIs. * diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java index 5774278cc1..c4ed18d7d4 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java @@ -39,11 +39,11 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.validateMockitoUsage; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; -import android.content.Context; -import android.content.res.Resources; import android.net.MacAddress; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; @@ -51,26 +51,32 @@ import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApConfiguration.Builder; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiManager; import android.net.wifi.WifiScanner; import android.net.wifi.nl80211.DeviceWiphyCapabilities; +import android.net.wifi.util.WifiResourceCache; import android.util.SparseArray; import android.util.SparseIntArray; import androidx.test.filters.SmallTest; +import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.SoftApManager; import com.android.server.wifi.WifiBaseTest; import com.android.server.wifi.WifiNative; import com.android.server.wifi.WifiSettingsConfigStore; import com.android.server.wifi.coex.CoexManager; +import com.android.wifi.flags.Flags; import com.android.wifi.resources.R; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; import java.util.ArrayList; import java.util.Arrays; @@ -166,8 +172,8 @@ public class ApConfigUtilTest extends WifiBaseTest { private static final int[] ALLOWED_60G_CHANS = {1, 2}; // ch# 1, 2 private static final int[] TEST_5G_DFS_FREQS = {5280, 5520}; // ch#56, 104 - @Mock Context mContext; - @Mock Resources mResources; + @Mock WifiContext mContext; + @Mock WifiResourceCache mResources; @Mock WifiNative mWifiNative; @Mock CoexManager mCoexManager; @Mock WifiSettingsConfigStore mConfigStore; @@ -176,12 +182,18 @@ public class ApConfigUtilTest extends WifiBaseTest { private SoftApCapability mCapability; private boolean mApBridgeIfaceCobinationSupported = false; private boolean mApBridgeWithStaIfaceCobinationSupported = false; + private MockitoSession mSession; + /** * Setup test. */ @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + // Mock WifiMigration to avoid calling into its static methods + mSession = ExtendedMockito.mockitoSession() + .mockStatic(Flags.class, withSettings().lenient()) + .startMocking(); final long testFeatures = SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT | SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED | SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED; @@ -189,7 +201,7 @@ public class ApConfigUtilTest extends WifiBaseTest { mCapability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, ALLOWED_2G_CHANS); mCapability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, ALLOWED_5G_CHANS); mCapability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, ALLOWED_60G_CHANS); - when(mContext.getResources()).thenReturn(mResources); + when(mContext.getResourceCache()).thenReturn(mResources); when(mResources.getBoolean(R.bool.config_wifi24ghzSupport)).thenReturn(true); when(mResources.getBoolean(R.bool.config_wifi5ghzSupport)).thenReturn(true); when(mResources.getBoolean(R.bool.config_wifiSoftap24ghzSupported)).thenReturn(true); @@ -221,6 +233,17 @@ public class ApConfigUtilTest extends WifiBaseTest { } /** + * Called after each test + */ + @After + public void cleanup() { + validateMockitoUsage(); + if (mSession != null) { + mSession.finishMocking(); + } + } + + /** * Verify Bridge AP support when Iface combination for AP bridge is allowed. */ @Test @@ -1455,7 +1478,7 @@ public class ApConfigUtilTest extends WifiBaseTest { .thenReturn(false); /* 11be is disallowed when IEEE80211_BE feature is not supported */ assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, - mContext, config, true)); + mContext, config, true, 0, false)); when(mResources.getBoolean(R.bool.config_wifiSoftapIeee80211beSupported)) .thenReturn(true); @@ -1465,13 +1488,34 @@ public class ApConfigUtilTest extends WifiBaseTest { .thenReturn(true); /* 11be is allowed if chip supports single link MLO in bridged mode */ assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, - mContext, config, true)); + mContext, config, true, 0, false)); /* 11be is not allowed if chip doesn't support single link MLO in bridged mode */ when(mResources.getBoolean(R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) .thenReturn(false); assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, - mContext, config, true)); + mContext, config, true, 0, false)); + + when(Flags.mloSap()).thenReturn(true); + // two MLDs supported, allow 11be on bridged mode. + when(mResources.getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported)) + .thenReturn(2); + assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, + mContext, config, true, 0, false)); + + // One MLD only, disallow 11be on bridged AP. + when(mResources.getInteger(R.integer.config_wifiSoftApMaxNumberMLDSupported)) + .thenReturn(1); + assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, + mContext, config, true, 0, false)); + + // One MLD only, disallow 11be when there is existing 11be AP. + assertFalse(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, + mContext, config, false, 1, false)); + + // One MLD only but chip support MultilinksOnMLD, allow 11be on bridged AP. + assertTrue(ApConfigUtil.is11beAllowedForThisConfiguration(mDeviceWiphyCapabilities, + mContext, config, true, 0, true)); } @Test public void testIs11beDisabledForSecurityType() throws Exception { diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/HalAidlUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/HalAidlUtilTest.java index 102ef51d8a..95b9779fdd 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/util/HalAidlUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/util/HalAidlUtilTest.java @@ -19,15 +19,11 @@ package com.android.server.wifi.util; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import android.hardware.wifi.common.OuiKeyedData; import android.net.wifi.util.PersistableBundleUtils; import android.os.PersistableBundle; -import com.android.modules.utils.build.SdkLevel; - -import org.junit.Before; import org.junit.Test; import java.util.ArrayList; @@ -39,11 +35,6 @@ import java.util.List; public class HalAidlUtilTest { private static final int TEST_VENDOR_DATA_LIST_SIZE = 10; - @Before - public void setUp() throws Exception { - assumeTrue(SdkLevel.isAtLeastV()); - } - private static PersistableBundle createTestPersistableBundle() { PersistableBundle bundle = new PersistableBundle(); bundle.putString("stringKey", "someStringData"); diff --git a/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java index 0d5e495193..abc04e5f9d 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java @@ -466,11 +466,13 @@ public class InformationElementUtilTest extends WifiBaseTest { InformationElement[] ies, int beaconCap, boolean isOweSupported, + boolean isRsnOverridingSupported, String capsStr, SparseIntArray unknownAkmMap) { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(ies, beaconCap, isOweSupported, 2400, unknownAkmMap); + capabilities.from(ies, beaconCap, isOweSupported, isRsnOverridingSupported, 2400, + unknownAkmMap); String result = capabilities.generateCapabilitiesString(); assertEquals(capsStr, result); @@ -484,7 +486,8 @@ public class InformationElementUtilTest extends WifiBaseTest { SparseIntArray unknownAkmMap) { InformationElement[] ies = new InformationElement[] { ie }; verifyCapabilityStringFromIes( - new InformationElement[] {ie}, beaconCap, isOweSupported, capsStr, unknownAkmMap); + new InformationElement[] {ie}, beaconCap, isOweSupported, false, capsStr, + unknownAkmMap); } private void verifyCapabilityStringFromIeWithoutOweSupported( @@ -801,6 +804,7 @@ public class InformationElementUtilTest extends WifiBaseTest { ies, 0x1 << 4, false, + false, "[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][RSN-PSK-CCMP+TKIP]", null); } @@ -1130,6 +1134,210 @@ public class InformationElementUtilTest extends WifiBaseTest { } /** + * Test Capabilities.generateCapabilitiesString() with RSN, RSNO & RSNO2 element + * This configuration is same as a Wi-Fi 7 supported AP configured in + * WPA3-Compatibility Mode operating on the 2.4GHz/5GHz. + * Expect the function to return a string with the proper security information. + */ + @Test + public void buildCapabilities_rsnRsnoAndRsno2Element() { + //RSNE Element carries WPA-PSK (AKM: 2) + InformationElement ieRsn = new InformationElement(); + ieRsn.id = InformationElement.EID_RSN; + ieRsn.bytes = new byte[] { + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Pairwise Cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // PSK AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, + // RSN capabilities + (byte) 0x00, (byte) 0x00, + }; + + //RSNE Override Element carries SAE (AKM: 8) + InformationElement ieRsno = new InformationElement(); + ieRsno.id = InformationElement.EID_VSA; + ieRsno.bytes = new byte[] { + // RSNO (OUI type - 0x29) WFA vendor specific IE header + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x29, + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Pairwise Cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // SAE AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08, + // RSN capabilities + (byte) 0xC0, (byte) 0x00 }; + + //RSNE Override Element 2 Element carries SAE_EXT_KEY (AKM: 24) + InformationElement ieRsno2 = new InformationElement(); + ieRsno2.id = InformationElement.EID_VSA; + ieRsno2.bytes = new byte[]{ + // RSNO2 (OUI type - 0x2A) WFA vendor specific IE header + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x2A, + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Cipher suite: GCMP-256 + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // SAE-EXT-KEY AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x18, + // Padding + // RSN capabilities + (byte) 0xC0, (byte) 0x00, + }; + + InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno, ieRsno2 }; + + verifyCapabilityStringFromIes( + ies, + 0x1 << 4, + true, + true, + "[WPA2-PSK-CCMP][RSN-PSK-CCMP][RSN-SAE-CCMP][RSN-SAE_EXT_KEY-GCMP-256][MFPC][RSNO]", + null); + } + + /** + * Test Capabilities.generateCapabilitiesString() with RSN, RSNO & RSNO2 element + * This configuration is same as a Wi-Fi 7 supported AP configured in + * WPA3-Compatibility Mode operating on the 6GHz band. + * Expect the function to return a string with the proper security information. + */ + @Test + public void buildCapabilities_rsnAndRsno2Element() { + //RSNE Element carries SAE (AKM: 8) + InformationElement ieRsn = new InformationElement(); + ieRsn.id = InformationElement.EID_RSN; + ieRsn.bytes = new byte[] { + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Pairwise Cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // SAE AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08, + // RSN capabilities + (byte) 0xC0, (byte) 0x00, + }; + + //RSNE Override Element 2 Element carries SAE_EXT_KEY (AKM: 24) + InformationElement ieRsno2 = new InformationElement(); + ieRsno2.id = InformationElement.EID_VSA; + ieRsno2.bytes = new byte[]{ + // RSNO2 (OUI type - 0x2A) WFA vendor specific IE header + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x2A, + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Cipher suite: GCMP-256 + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x09, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // SAE-EXT-KEY AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x18, + // Padding + // RSN capabilities + (byte) 0xC0, (byte) 0x00, + }; + + InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno2 }; + + verifyCapabilityStringFromIes( + ies, + 0x1 << 4, + true, + true, + "[RSN-SAE-CCMP][RSN-SAE_EXT_KEY-GCMP-256][MFPR][MFPC][RSNO]", + null); + } + + /** + * Test Capabilities.generateCapabilitiesString() without RSN Overriding support. + * The AP advertise WPA2 security params in RSN IE and WPA3 security params in RSNO element. + * But without the RSN Overriding support, it is expected to return a capabilities string + * which contains only WPA2 security params. + */ + @Test + public void buildCapabilities_rsnAndRsnoElementWithoutRsnOverridingSupport() { + //RSNE Element carries WPA-PSK (AKM: 2) + InformationElement ieRsn = new InformationElement(); + ieRsn.id = InformationElement.EID_RSN; + ieRsn.bytes = new byte[] { + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Pairwise Cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // PSK AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, + // RSN capabilities + (byte) 0x00, (byte) 0x00, + }; + + //RSNE Override Element carries SAE (AKM: 8) + InformationElement ieRsno = new InformationElement(); + ieRsno.id = InformationElement.EID_VSA; + ieRsno.bytes = new byte[] { + // RSNO (OUI type - 0x29) WFA vendor specific IE header + (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x29, + // RSNE Version (0x0001) + (byte) 0x01, (byte) 0x00, + // Group cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of pairwise cipher suites (1) + (byte) 0x01, (byte) 0x00, + // Pairwise Cipher suite: CCMP + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, + // Number of AKMs (1) + (byte) 0x01, (byte) 0x00, + // SAE AKM + (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x08, + // RSN capabilities + (byte) 0xC0, (byte) 0x00 }; + InformationElement[] ies = new InformationElement[] { ieRsn, ieRsno }; + + verifyCapabilityStringFromIes( + ies, + 0x1 << 4, + true, + false, + "[WPA2-PSK-CCMP][RSN-PSK-CCMP]", + null); + } + + /** * Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE which are malformed. * Expect the function to return a string with empty key management & pairswise cipher security * information. @@ -1148,7 +1356,7 @@ public class InformationElementUtilTest extends WifiBaseTest { (byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x50 }; InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn }; - verifyCapabilityStringFromIes(ies, 0x1 << 4, false, "[WPA][RSN]", null); + verifyCapabilityStringFromIes(ies, 0x1 << 4, false, false, "[WPA][RSN]", null); } /** @@ -1172,7 +1380,8 @@ public class InformationElementUtilTest extends WifiBaseTest { ieWps.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04 }; InformationElement[] ies = new InformationElement[] { ieWpa, ieWps }; - verifyCapabilityStringFromIes(ies, 0x1 << 4, false, "[WPA-PSK-CCMP+TKIP][WPS]", null); + verifyCapabilityStringFromIes(ies, 0x1 << 4, false, false, "[WPA-PSK-CCMP+TKIP][WPS]", + null); } /** @@ -1253,7 +1462,7 @@ public class InformationElementUtilTest extends WifiBaseTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(new InformationElement[0], beaconCap, false, 2400, null); + capabilities.from(new InformationElement[0], beaconCap, false, false, 2400, null); String result = capabilities.generateCapabilitiesString(); assertEquals("[IBSS]", result); @@ -1270,7 +1479,7 @@ public class InformationElementUtilTest extends WifiBaseTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(new InformationElement[0], beaconCap, false, 58320, null); + capabilities.from(new InformationElement[0], beaconCap, false, false, 58320, null); String result = capabilities.generateCapabilitiesString(); assertEquals("[IBSS]", result); @@ -1287,7 +1496,7 @@ public class InformationElementUtilTest extends WifiBaseTest { InformationElementUtil.Capabilities capabilities = new InformationElementUtil.Capabilities(); - capabilities.from(new InformationElement[0], beaconCap, false, 58320, null); + capabilities.from(new InformationElement[0], beaconCap, false, false, 58320, null); String result = capabilities.generateCapabilitiesString(); assertEquals("[ESS]", result); |