diff options
177 files changed, 10595 insertions, 2508 deletions
diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig index 2da04a5284..30f50d9b2c 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,78 @@ flag { description: "Add new API to get BSSID blocklist" bug: "336109216" is_fixed_read_only: true +} + +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" }
\ No newline at end of file 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..7ae116d1d1 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -719,6 +719,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 getAutojoinRestrictionSecurityTypes(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.Set<java.lang.Integer>>); 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 +785,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 setAutojoinRestrictionSecurityTypes(@NonNull java.util.Set<java.lang.Integer>); 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 index 5f58810584..153127170d 100644 --- a/framework/java/android/net/wifi/BaseWifiService.java +++ b/framework/java/android/net/wifi/BaseWifiService.java @@ -32,6 +32,7 @@ import android.os.RemoteException; import android.os.WorkSource; import com.android.modules.utils.ParceledListSlice; +import com.android.modules.utils.StringParceledListSlice; import java.util.List; import java.util.Map; @@ -123,24 +124,24 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public void setSsidsAllowlist(String packageName, List<WifiSsid> ssids) { + public void setSsidsAllowlist(String packageName, ParceledListSlice<WifiSsid> ssids) { throw new UnsupportedOperationException(); } @Override - public List<WifiSsid> getSsidsAllowlist(String packageName) { + public ParceledListSlice<WifiSsid> getSsidsAllowlist(String packageName) { throw new UnsupportedOperationException(); } @Override public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( - List<ScanResult> scanResults) { + ParceledListSlice<ScanResult> scanResults) { throw new UnsupportedOperationException(); } @Override public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( - List<OsuProvider> osuProviders) { + ParceledListSlice<OsuProvider> osuProviders) { throw new UnsupportedOperationException(); } @@ -167,12 +168,14 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public List<PasspointConfiguration> getPasspointConfigurations(String packageName) { + public ParceledListSlice<PasspointConfiguration> getPasspointConfigurations( + String packageName) { throw new UnsupportedOperationException(); } @Override - public List<WifiConfiguration> getWifiConfigsForPasspointProfiles(List<String> fqdnList) { + public ParceledListSlice<WifiConfiguration> getWifiConfigsForPasspointProfiles( + StringParceledListSlice fqdnList) { throw new UnsupportedOperationException(); } @@ -723,19 +726,20 @@ public class BaseWifiService extends IWifiManager.Stub { @Override public int addNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, + ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, String callingFeatureId) { throw new UnsupportedOperationException(); } @Override public int removeNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, int action) { + ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, String callingPackageName, + int action) { throw new UnsupportedOperationException(); } @Override - public List<WifiNetworkSuggestion> getNetworkSuggestions(String packageName) { + public ParceledListSlice<WifiNetworkSuggestion> getNetworkSuggestions(String packageName) { throw new UnsupportedOperationException(); } @@ -875,8 +879,9 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public List<WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( - List<ScanResult> scanResults) { + public ParceledListSlice<WifiConfiguration> + getWifiConfigForMatchedNetworkSuggestionsSharedWithUser( + ParceledListSlice<ScanResult> scanResults) { throw new UnsupportedOperationException(); } @@ -911,8 +916,8 @@ public class BaseWifiService extends IWifiManager.Stub { @Override public Map<WifiNetworkSuggestion, List<ScanResult>> getMatchingScanResults( - List<WifiNetworkSuggestion> networkSuggestions, - List<ScanResult> scanResults, + ParceledListSlice<WifiNetworkSuggestion> networkSuggestions, + ParceledListSlice<ScanResult> scanResults, String callingPackage, String callingFeatureId) { throw new UnsupportedOperationException(); } @@ -929,7 +934,8 @@ public class BaseWifiService extends IWifiManager.Stub { @Override public Map<String, Map<Integer, List<ScanResult>>> - getAllMatchingPasspointProfilesForScanResults(List<ScanResult> scanResults) { + getAllMatchingPasspointProfilesForScanResults( + ParceledListSlice<ScanResult> scanResults) { throw new UnsupportedOperationException(); } @@ -1014,7 +1020,8 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public void notifyWifiSsidPolicyChanged(int policyType, @NonNull List<WifiSsid> ssids) { + public void notifyWifiSsidPolicyChanged(int policyType, + @NonNull ParceledListSlice<WifiSsid> ssids) { throw new UnsupportedOperationException(); } @@ -1035,7 +1042,8 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public void addCustomDhcpOptions(WifiSsid ssid, byte[] oui, @NonNull List<DhcpOption> options) { + public void addCustomDhcpOptions(WifiSsid ssid, byte[] oui, + @NonNull ParceledListSlice<DhcpOption> options) { throw new UnsupportedOperationException(); } @@ -1056,7 +1064,7 @@ public class BaseWifiService extends IWifiManager.Stub { } @Override - public void addQosPolicies(@NonNull List<QosPolicyParams> policyParamsList, + public void addQosPolicies(@NonNull ParceledListSlice<QosPolicyParams> policyParamsList, @NonNull IBinder binder, @NonNull String packageName, @NonNull IListListener listener) { throw new UnsupportedOperationException(); } @@ -1212,4 +1220,14 @@ public class BaseWifiService extends IWifiManager.Stub { public boolean isPnoSupported() { throw new UnsupportedOperationException(); } + + @Override + public void setAutojoinRestrictionSecurityTypes(int restrictions, Bundle extras) { + throw new UnsupportedOperationException(); + } + + @Override + public void getAutojoinRestrictionSecurityTypes(IIntegerListener listener, Bundle extras) { + throw new UnsupportedOperationException(); + } } diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl index 0a6e210249..a1eef116b7 100644 --- a/framework/java/android/net/wifi/IWifiManager.aidl +++ b/framework/java/android/net/wifi/IWifiManager.aidl @@ -79,6 +79,7 @@ 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. @@ -111,13 +112,13 @@ interface IWifiManager Map getAllMatchingFqdnsForScanResults(in List<ScanResult> scanResult); - 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); @@ -127,9 +128,9 @@ interface IWifiManager 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); @@ -332,12 +333,12 @@ interface IWifiManager void unregisterNetworkRequestMatchCallback(in INetworkRequestMatchCallback callback); - int addNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName, + 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(); @@ -376,7 +377,7 @@ interface IWifiManager 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); @@ -393,13 +394,13 @@ 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); @@ -443,7 +444,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,7 +452,7 @@ 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); @@ -459,7 +460,7 @@ interface IWifiManager 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); @@ -518,4 +519,8 @@ interface IWifiManager void restoreWifiBackupData(in byte[] data); boolean isPnoSupported(); + + void setAutojoinRestrictionSecurityTypes(int restrictions, in Bundle extras); + + void getAutojoinRestrictionSecurityTypes(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/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java index 7bd0c0d591..e4371001f8 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(); } @@ -4567,7 +4578,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 +5170,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) { @@ -11320,8 +11333,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 +11647,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 +11907,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 +12455,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 +12488,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 +12513,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 +12521,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 +12868,133 @@ public class WifiManager { throw e.rethrowFromSystemServer(); } } + + /** + * Restrict Wi-Fi autojoin on ScanResults matching the selected security types. + * This does not restrict manual connections. + * + * @param restrictions The autojoin restriction types to be set. It should be a Set of Integers. + * If null value is provided, an IllegalArgumentException will be thrown. + * Set of {@link WifiAnnotations.SecurityType} constants specifying the + * autojoin restrictions on the device. If any restrictions are set, then + * the autojoin to the network should be skipped for the specified security + * types. + * However, certain combinations of restricted security types are not + * allowed. + * 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 restrict autojoin to Wi-Fi networks with security type, OPEN, WEP + * or OWE, use following argument. + * + * {@code + * Set<Integer> restrictions = new ArraySet<>( + * Set.of(WifiInfo.SECURITY_TYPE_OPEN, + * WifiInfo.SECURITY_TYPE_WEP, + * WifiInfo.SECURITY_TYPE_OWE)); + * wifiManager.setAutojoinRestrictionSecurityTypes(restrictions); + * } + * + * To clear autojoin restriction on all security types, use following + * argument. + * + * {@code + * wifiManager.setAutojoinRestrictionSecurityTypes( + * Collections.emptySet()); + * } + * </pre> + * + * @throws IllegalArgumentException if restrictions is null. + * @throws IllegalArgumentException if restrictions contains + * Integer element out of [0, Integer.SIZE) range. + * @throws RemoteException if there is an error communicating with the system server. + * @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 setAutojoinRestrictionSecurityTypes( + @NonNull @WifiAnnotations.SecurityType Set<Integer> restrictions) { + if (restrictions == null) { + throw new IllegalArgumentException("restrictions cannot be null"); + } + for (int securityType : restrictions) { + if (securityType < 0 || securityType >= Integer.SIZE) { + throw new IllegalArgumentException("restrictions include invalid value."); + } + } + try { + Bundle extras = new Bundle(); + if (SdkLevel.isAtLeastS()) { + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + } + int restrictionBitmap = 0; + for (int securityType : restrictions) { + restrictionBitmap |= 0x1 << securityType; + } + mService.setAutojoinRestrictionSecurityTypes(restrictionBitmap, extras); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves the autojoin restricted 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 the + * retrieved autojoin restriction type as a Set of Integers. + * + * @throws NullPointerException if either executor or resultsCallback is null. + * @throws RemoteException if there is an error communicating with the system server. + * + * @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 getAutojoinRestrictionSecurityTypes(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Set<Integer>> resultsCallback) { + Objects.requireNonNull(executor, "executor cannot be null"); + Objects.requireNonNull(resultsCallback, "resultsCallback cannot be null"); + try { + Bundle extras = new Bundle(); + if (SdkLevel.isAtLeastS()) { + extras.putParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE, + mContext.getAttributionSource()); + } + mService.getAutojoinRestrictionSecurityTypes(new IIntegerListener.Stub() { + @Override + public void onResult(int value) { + Binder.clearCallingIdentity(); + executor.execute(() -> { + Set<Integer> restrictions = new ArraySet<>(); + for (int i = 0; i < Integer.SIZE; i++) { + if (((0x1 << i) & value) != 0) { + restrictions.add(i); + } + } + resultsCallback.accept(restrictions); + }); + } + }, 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..8c8fcb6d89 100644 --- a/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java +++ b/framework/java/android/net/wifi/WifiUsabilityStatsEntry.java @@ -152,6 +152,16 @@ 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; + /** {@hide} */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"WME_ACCESS_CATEGORY_"}, value = { @@ -265,6 +275,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 +568,75 @@ 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(); + } + } + + /** * Wifi link layer radio stats. */ public static final class RadioStats implements Parcelable { @@ -499,6 +655,7 @@ public final class WifiUsabilityStatsEntry implements Parcelable { private long mTotalRoamScanTimeMillis; private long mTotalPnoScanTimeMillis; private long mTotalHotspot2ScanTimeMillis; + private int[] mTxTimeMsPerLevel; /** @hide */ public RadioStats() { @@ -542,6 +699,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 +757,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 +775,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 +845,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 +877,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 +914,10 @@ 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; /** @hide */ public LinkStats() { @@ -704,6 +925,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 +942,8 @@ public final class WifiUsabilityStatsEntry implements Parcelable { mTotalRadioOnFreqTimeMillis = 0; mContentionTimeStats = null; mRateStats = null; + mPacketStats = null; + mPeerInfo = null; } /** @hide @@ -725,6 +953,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 +972,26 @@ 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. */ - 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) { 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 +1004,8 @@ public final class WifiUsabilityStatsEntry implements Parcelable { this.mTotalRadioOnFreqTimeMillis = totalRadioOnFreqTimeMillis; this.mContentionTimeStats = contentionTimeStats; this.mRateStats = rateStats; + this.mPacketStats = packetStats; + this.mPeerInfo = peerInfo; } @Override @@ -774,6 +1019,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 +1036,8 @@ 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); } /** Implement the Parcelable interface */ @@ -794,11 +1046,14 @@ 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)); } public LinkStats[] newArray(int size) { @@ -826,7 +1081,9 @@ 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) { mTimeStampMillis = timeStampMillis; mRssi = rssi; mLinkSpeedMbps = linkSpeedMbps; @@ -863,6 +1120,11 @@ public final class WifiUsabilityStatsEntry implements Parcelable { mCellularSignalStrengthDb = cellularSignalStrengthDb; mIsSameRegisteredCell = isSameRegisteredCell; mLinkStats = linkStats; + mWifiLinkCount = wifiLinkCount; + mMloMode = mloMode; + mTxTransmittedBytes = txTransmittedBytes; + mRxTransmittedBytes = rxTransmittedBytes; + mLabelBadEventCount = labelBadEventCount; } /** Implement the Parcelable interface */ @@ -908,6 +1170,11 @@ 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); } /** Implement the Parcelable interface */ @@ -929,7 +1196,8 @@ 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() ); } @@ -1003,6 +1271,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 +1695,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 +1770,55 @@ 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); + } + + /** * Radio stats from all the radios, see {@link RadioStats#getRadioId()} * @return A list of Wifi link layer radio stats, see {@link RadioStats} */ @@ -1485,4 +1897,29 @@ 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; + } } 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/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/WifiManagerTest.java b/framework/tests/src/android/net/wifi/WifiManagerTest.java index b18a4f9f3c..d5718fbdff 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; @@ -120,6 +121,8 @@ 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.twt.TwtRequest; @@ -138,6 +141,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 +782,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 +2371,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 +2395,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 +2406,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 +2423,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 +2510,33 @@ 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); 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)); 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)); 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)); verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(), any(WifiUsabilityStatsEntry.class)); } @@ -3314,8 +3328,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 +3416,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()); } /** @@ -4384,4 +4398,81 @@ public class WifiManagerTest { mWifiManager.isPreferredNetworkOffloadSupported(); verify(mWifiService).isPnoSupported(); } + + @Test + public void testSetAutoJoinRestrictionSecurityTypesToWifiServiceImpl() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + Set<Integer> restrictions = new ArraySet<>( + Set.of(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.setAutojoinRestrictionSecurityTypes(restrictions); + verify(mWifiService).setAutojoinRestrictionSecurityTypes(eq(restrictionBitmap), + bundleCaptor.capture()); + assertEquals(mContext.getAttributionSource(), + bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE)); + + // Null argument + assertThrows(IllegalArgumentException.class, + () -> mWifiManager.setAutojoinRestrictionSecurityTypes(null)); + // Argument with negative integer element, Valid integer range is [0, Integer.SIZE(32)). + assertThrows(IllegalArgumentException.class, + () -> mWifiManager.setAutojoinRestrictionSecurityTypes(new ArraySet<>( + Set.of(WifiInfo.SECURITY_TYPE_OPEN, + WifiInfo.SECURITY_TYPE_WEP, + WifiInfo.SECURITY_TYPE_OWE, + -1)))); + // Argument with integer element, 32. Valid integer range is [0, Integer.SIZE(32)). + assertThrows(IllegalArgumentException.class, + () -> mWifiManager.setAutojoinRestrictionSecurityTypes(new ArraySet<>( + Set.of(WifiInfo.SECURITY_TYPE_OPEN, + WifiInfo.SECURITY_TYPE_WEP, + WifiInfo.SECURITY_TYPE_OWE, + Integer.SIZE)))); + } + + @Test + public void testGetAutoJoinRestrictionSecurityTypesToWifiServiceImpl() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + final Set<Integer> restrictionToSet = new ArraySet<>( + Set.of(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<Set<Integer>> mockResultsCallback = mock(Consumer.class); + + // null executor + assertThrows(NullPointerException.class, + () -> mWifiManager.getAutojoinRestrictionSecurityTypes(null, mockResultsCallback)); + // null resultsCallback + assertThrows(NullPointerException.class, + () -> mWifiManager.getAutojoinRestrictionSecurityTypes(executor, null)); + + ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); + ArgumentCaptor<IIntegerListener.Stub> cbCaptor = ArgumentCaptor.forClass( + IIntegerListener.Stub.class); + + ArgumentCaptor<Set<Integer>> resultCaptor = ArgumentCaptor.forClass(Set.class); + + mWifiManager.getAutojoinRestrictionSecurityTypes(new SynchronousExecutor(), + mockResultsCallback); + verify(mWifiService).getAutojoinRestrictionSecurityTypes(cbCaptor.capture(), + bundleCaptor.capture()); + assertEquals(mContext.getAttributionSource(), + bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE)); + + cbCaptor.getValue().onResult(restrictionBitmap); + + verify(mockResultsCallback).accept(resultCaptor.capture()); + assertEquals(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..45abed1211 100644 --- a/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java +++ b/framework/tests/src/android/net/wifi/WifiUsabilityStatsEntryTest.java @@ -23,6 +23,8 @@ 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.os.Parcel; @@ -80,37 +82,42 @@ 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); 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)); 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)); 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, 1, 0, 10, 20, 1); 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, 1, 0, 10, 20, 1); try { usabilityStatsEntryWithInvalidDutyCycleValue.getTimeSliceDutyCycleInPercent(); fail(); @@ -136,27 +143,34 @@ 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); 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)); 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)); 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, 1, 0, 10, 20, 1 ); } @@ -336,6 +350,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 +488,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 +616,15 @@ 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()); + } } } + assertEquals(expected.getWifiLinkCount(), actual.getWifiLinkCount()); } /** @@ -496,14 +635,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)); 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); + true, true, 23, 24, 25, true, linkStats, 1, 0, 10, 20, 1); 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/service/Android.bp b/service/Android.bp index ae9e40cd85..2cbb51597f 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -95,7 +95,7 @@ java_library { "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..2b3b9f9ab8 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. @@ -1342,4 +1355,34 @@ --> <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..d499e366a2 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" /> @@ -344,7 +346,11 @@ <item type="array" name="config_wifiTwtBlockedOuiList" /> <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..0df5d77874 100644 --- a/service/java/com/android/server/wifi/ActiveModeWarden.java +++ b/service/java/com/android/server/wifi/ActiveModeWarden.java @@ -33,6 +33,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.ActiveModeManager.ROLE_SOFTAP_TETHERED; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS; +import static com.android.server.wifi.util.GeneralUtil.bitsetToLong; import android.annotation.NonNull; import android.annotation.Nullable; @@ -51,10 +52,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 +99,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; @@ -127,7 +131,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; @@ -191,6 +195,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 +385,7 @@ public class ActiveModeWarden { DefaultClientModeManager defaultClientModeManager, BatteryStatsManager batteryStatsManager, WifiDiagnostics wifiDiagnostics, - Context context, + WifiContext context, WifiSettingsStore settingsStore, FrameworkFacade facade, WifiPermissionsUtil wifiPermissionsUtil, @@ -392,6 +397,7 @@ public class ActiveModeWarden { mLooper = looper; mHandler = new Handler(looper); mContext = context; + mResourceCache = mContext.getResourceCache(); mWifiDiagnostics = wifiDiagnostics; mSettingsStore = settingsStore; mFacade = facade; @@ -601,7 +607,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 +620,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 +646,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForLocalOnlyConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled); } @@ -650,7 +656,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMbb() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled); } @@ -660,7 +666,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForRestrictedConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled); } @@ -670,7 +676,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMultiInternet() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled); } @@ -706,7 +712,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 +1496,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 +1749,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 +1852,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 +1974,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; @@ -2733,27 +2740,28 @@ public class ActiveModeWarden { * @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 supportedFeatureBitset, boolean isStaApConcurrencySupported, boolean isStaStaConcurrencySupported) { + long supportedFeatureSet = bitsetToLong(supportedFeatureBitset); long concurrencyFeatureSet = 0L; if (isStaApConcurrencySupported) { concurrencyFeatureSet |= 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; } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) { concurrencyFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB; } - if (mContext.getResources().getBoolean( + if (mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) { concurrencyFeatureSet |= 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; } @@ -2767,13 +2775,13 @@ public class ActiveModeWarden { (WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT); } - if (!mContext.getResources().getBoolean( + if (!mResourceCache.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( + 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; 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..f9e63a0268 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,7 +35,14 @@ 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 static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import android.annotation.IntDef; import android.annotation.NonNull; @@ -175,6 +183,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 +706,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, @@ -1640,7 +1648,14 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } private boolean isLinkLayerStatsSupported() { - return (getSupportedFeatures() & WIFI_FEATURE_LINK_LAYER_STATS) != 0; + return getSupportedFeatures().get(getCapabilityIndex(WIFI_FEATURE_LINK_LAYER_STATS)); + } + + /** + * @return true if this device supports WPA3_SAE + */ + private boolean isWpa3SaeSupported() { + return getSupportedFeatures().get(getCapabilityIndex(WIFI_FEATURE_WPA3_SAE)); } /** @@ -1668,6 +1683,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 +1980,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 +2044,9 @@ 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(); + boolean hasTdlsCapability = + getSupportedFeatures().get(getCapabilityIndex(WIFI_FEATURE_TDLS)); + return hasTdlsCapability && isConnected() && canEnableTdls(); } /** @@ -2430,6 +2450,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 +2918,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setSuccessfulRxPacketsPerSecond(0); mWifiScoreReport.reset(); mLastLinkLayerStats = null; + if (isPrimary()) { + mWifiMetrics.resetWifiUnusableEvent(); + } updateCurrentConnectionInfo(); } @@ -3250,6 +3279,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 +3770,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; } /** @@ -4131,6 +4163,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(); @@ -4840,6 +4873,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!isTrustOnFirstUseSupported()) { mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected); } + mFrameworkDisconnectReasonOverride = 0; connectToNetwork(config); break; } @@ -5377,7 +5411,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())) { @@ -6773,12 +6808,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 +6824,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); } @@ -6899,6 +6937,19 @@ public class ClientModeImpl extends StateMachine implements ClientMode { int statusDataStall = mWifiDataStall.checkDataStallAndThroughputSufficiency( mInterfaceName, mLastConnectionCapabilities, mLastLinkLayerStats, stats, mWifiInfo, txBytes, rxBytes); + 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.getLingering(), + mWifiInfo, mLastConnectionCapabilities); + mWifiScoreReport.clearScorerPredictionStatusForEvaluation(); + } + if (mDataStallTriggerTimeMs == -1 && statusDataStall != WifiIsUnusableEvent.TYPE_UNKNOWN) { mDataStallTriggerTimeMs = mClock.getElapsedSinceBootMillis(); @@ -6997,6 +7048,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; } @@ -8036,21 +8088,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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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..8d0d9c44b6 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.bitsetToLong; 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; @@ -951,6 +952,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) { @@ -1851,6 +1860,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 +1908,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 +2532,7 @@ public class HalDeviceManager { return false; } + boolean success = false; synchronized (mLock) { WifiChip chip = getChip(iface); if (chip == null) { @@ -2504,7 +2545,6 @@ public class HalDeviceManager { return false; } - boolean success = false; switch (type) { case WifiChip.IFACE_TYPE_STA: mClientModeManagers.remove(name); @@ -2523,20 +2563,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 +2586,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 +2609,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,12 +2858,12 @@ public class HalDeviceManager { * @param wifiChip WifiChip to get the features for. * @return Bitset of WifiManager.WIFI_FEATURE_* values. */ - public long getChipCapabilities(@NonNull WifiChip wifiChip) { + private long getChipCapabilities(@NonNull WifiChip wifiChip) { if (wifiChip == null) return 0; - WifiChip.Response<Long> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist(); + WifiChip.Response<BitSet> capsResp = wifiChip.getCapabilitiesBeforeIfacesExist(); if (capsResp.getStatusCode() == WifiHal.WIFI_STATUS_SUCCESS) { - return capsResp.getValue(); + return bitsetToLong(capsResp.getValue()); } else if (capsResp.getStatusCode() != WifiHal.WIFI_STATUS_ERROR_REMOTE_EXCEPTION) { // Non-remote exception here is likely because HIDL HAL < v1.5 // does not support getting capabilities before creating an interface. 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..c689998078 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; @@ -39,7 +38,9 @@ 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 +85,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 +97,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 +129,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 +383,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); } } @@ -688,15 +700,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: @@ -901,20 +913,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 +966,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..ce74efe1fd 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; @@ -31,7 +30,9 @@ 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 +75,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 +88,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 +133,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 +793,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 +810,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 +835,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 +1073,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: 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..bdd4b4617f 100644 --- a/service/java/com/android/server/wifi/MboOceController.java +++ b/service/java/com/android/server/wifi/MboOceController.java @@ -19,12 +19,16 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; 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 +64,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(getCapabilityIndex(WIFI_FEATURE_MBO)); + mIsOceSupported = supportedFeatures.get(getCapabilityIndex(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..18883ea5a2 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,20 +57,29 @@ 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(); 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"); } @@ -81,12 +91,17 @@ public abstract class RunnerState extends State { @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 +112,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..5afaf78c82 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; @@ -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; @@ -854,7 +858,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"); @@ -1064,7 +1068,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 +1185,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 +1201,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 +1216,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 +1229,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); @@ -1401,6 +1365,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 +1461,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 +1480,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, @@ -2060,8 +2091,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 +2333,8 @@ public class SoftApManager implements ActiveModeManager { mWifiNative.isStaApConcurrencySupported(), ApConfigUtil.isStaWithBridgedModeSupported(mContext, mWifiNative), getCurrentStaFreqMhz(), - securityType); + securityType, + mRequestorWs); } private void writeSoftApStoppedEvent(@StopEvent int stopEvent) { diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackAidlImpl.java index 5f377894cb..ae98ccbfdc 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)); } } @@ -1239,6 +1232,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..facbb7bfe0 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)); } } 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..f31c0f71d1 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java @@ -33,6 +33,9 @@ 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 static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import android.annotation.NonNull; import android.content.Context; @@ -87,7 +90,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; @@ -106,9 +111,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; @@ -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,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { private SupplicantStaIfaceHal.QosScsResponseCallback mQosScsResponseCallback; private MscsParams mLastMscsParams; + @VisibleForTesting + protected boolean mHasMigratedLegacyKeystoreAliases = false; + private class SupplicantDeathRecipient implements DeathRecipient { @Override public void binderDied() { @@ -435,6 +446,9 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { mCurrentNetworkRemoteHandles.clear(); mLinkedNetworkLocalAndRemoteConfigs.clear(); mNonStandardCertCallback = null; + mCurrentNetworkConnectTimestamp.clear(); + mCurrentNetworkFallbackSsidIndex.clear(); + mCurrentNetworkFallbackSsids.clear(); } } @@ -642,24 +656,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 +753,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 +763,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 +817,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 +932,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 +2585,24 @@ 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( + getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)); + advancedCapabilities.set(getCapabilityIndex(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(getCapabilityIndex(WIFI_FEATURE_WPA3_SAE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE supported"); @@ -2573,7 +2610,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.SUITE_B_192) != 0) { - advancedCapabilities |= WIFI_FEATURE_WPA3_SUITE_B; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SUITE_B supported"); @@ -2581,7 +2618,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.OWE) != 0) { - advancedCapabilities |= WIFI_FEATURE_OWE; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_OWE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OWE supported"); @@ -2589,8 +2626,8 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.DPP) != 0) { - advancedCapabilities |= WIFI_FEATURE_DPP - | WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP)); + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP supported"); @@ -2599,7 +2636,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.WAPI_PSK) != 0) { - advancedCapabilities |= WIFI_FEATURE_WAPI; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_WAPI)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WAPI supported"); @@ -2607,7 +2644,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA256) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA256; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA256)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA256 supported"); @@ -2615,7 +2652,7 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((keyMgmtCapabilities & KeyMgmtMask.FILS_SHA384) != 0) { - advancedCapabilities |= WIFI_FEATURE_FILS_SHA384; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_FILS_SHA384)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA384 supported"); @@ -2652,21 +2689,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(getCapabilityIndex(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(getCapabilityIndex(WIFI_FEATURE_TLS_V1_3)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": EAP-TLS v1.3 supported"); } @@ -2675,24 +2712,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(getCapabilityIndex(WIFI_FEATURE_MBO)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": MBO supported"); } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.OCE) != 0) { - featureSet |= WIFI_FEATURE_OCE; + featureSet.set(getCapabilityIndex(WIFI_FEATURE_OCE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OCE supported"); } @@ -2700,14 +2734,14 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { } if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.SAE_PK) != 0) { - featureSet |= WIFI_FEATURE_SAE_PK; + featureSet.set(getCapabilityIndex(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(getCapabilityIndex(WIFI_FEATURE_WFD_R2)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WFD-R2 supported"); } @@ -2715,19 +2749,40 @@ public class SupplicantStaIfaceHalAidlImpl implements ISupplicantStaIfaceHal { if ((drvCapabilitiesMask & WpaDriverCapabilitiesMask.TRUST_ON_FIRST_USE) != 0) { - featureSet |= WIFI_FEATURE_TRUST_ON_FIRST_USE; + featureSet.set(getCapabilityIndex(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 +4093,13 @@ 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()) { + WifiMigration.migrateLegacyKeystoreToWifiBlobstore(); + mHasMigratedLegacyKeystoreAliases = true; + } + 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..c98e23af3a 100644 --- a/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHalHidlImpl.java @@ -30,6 +30,8 @@ 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 com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.content.Context; import android.hardware.wifi.V1_0.WifiChannelWidthInMhz; @@ -73,9 +75,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 +102,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 +125,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 +649,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { mCurrentNetworkLocalConfigs.clear(); mCurrentNetworkRemoteHandles.clear(); mLinkedNetworkLocalAndRemoteConfigs.clear(); + mCurrentNetworkConnectTimestamp.clear(); + mCurrentNetworkFallbackSsidIndex.clear(); + mCurrentNetworkFallbackSsids.clear(); } } @@ -976,24 +984,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 +1081,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 +1091,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 +1143,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 +1255,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 +2961,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(getCapabilityIndex(WIFI_FEATURE_WPA3_SAE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE supported"); @@ -2951,7 +2983,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(getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SUITE_B supported"); @@ -2960,7 +2992,7 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.OWE) != 0) { - advancedCapabilities |= WIFI_FEATURE_OWE; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_OWE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OWE supported"); @@ -2969,13 +3001,13 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { if ((keyMgmtCapabilities & android.hardware.wifi.supplicant.V1_2.ISupplicantStaNetwork .KeyMgmtMask.DPP) != 0) { - advancedCapabilities |= WIFI_FEATURE_DPP; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP supported"); } if (isV1_4()) { - advancedCapabilities |= WIFI_FEATURE_DPP_ENROLLEE_RESPONDER; + advancedCapabilities.set(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": DPP ENROLLEE RESPONDER supported"); } @@ -2983,8 +3015,9 @@ public class SupplicantStaIfaceHalHidlImpl implements ISupplicantStaIfaceHal { } if (isV1_4()) { - advancedCapabilities |= WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS - | WIFI_FEATURE_DECORATED_IDENTITY; + advancedCapabilities.set( + getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)); + advancedCapabilities.set(getCapabilityIndex(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 +3026,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(getCapabilityIndex(WIFI_FEATURE_WAPI)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": WAPI supported"); @@ -3002,7 +3035,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(getCapabilityIndex(WIFI_FEATURE_FILS_SHA256)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA256 supported"); @@ -3010,7 +3043,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(getCapabilityIndex(WIFI_FEATURE_FILS_SHA384)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": FILS_SHA384 supported"); @@ -3164,15 +3197,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 +3210,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(getCapabilityIndex(WIFI_FEATURE_MBO)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": MBO supported"); } if ((drvCapabilitiesMask.value & WpaDriverCapabilitiesMask.OCE) != 0) { - featureSet |= WIFI_FEATURE_OCE; + featureSet.set(getCapabilityIndex(WIFI_FEATURE_OCE)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": OCE supported"); } @@ -3199,7 +3229,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(getCapabilityIndex(WIFI_FEATURE_SAE_PK)); if (mVerboseLoggingEnabled) { Log.v(TAG, methodStr + ": SAE-PK supported"); } @@ -3207,7 +3237,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(getCapabilityIndex(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..3a0a810003 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalAidlImpl.java @@ -16,6 +16,11 @@ 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 static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.content.Context; import android.hardware.wifi.supplicant.AuthAlgMask; @@ -38,7 +43,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 +155,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 +888,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(getCapabilityIndex(WIFI_FEATURE_TLS_V1_3))) { maxTlsVersionSupported = WifiEnterpriseConfig.TLS_V1_3; } @@ -1044,8 +1048,8 @@ 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( + getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) { Log.d(TAG, "Ignore unsupported GCMP_256 cipher."); break; } @@ -1106,8 +1110,8 @@ public class SupplicantStaNetworkHalAidlImpl { mask |= PairwiseCipherMask.CCMP; break; case WifiConfiguration.PairwiseCipher.GCMP_256: - if (0 == (mAdvanceKeyMgmtFeatures - & WifiManager.WIFI_FEATURE_WPA3_SUITE_B)) { + if (!mAdvanceKeyMgmtFeatures.get( + getCapabilityIndex(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..896019f5ac 100644 --- a/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java +++ b/service/java/com/android/server/wifi/SupplicantStaNetworkHalHidlImpl.java @@ -15,6 +15,10 @@ */ package com.android.server.wifi; +import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B; + +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.content.Context; import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetworkCallback; @@ -24,7 +28,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 +137,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 +994,8 @@ 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( + getCapabilityIndex(WIFI_FEATURE_WPA3_SUITE_B))) { Log.d(TAG, "Ignore unsupporting GCMP_256 cipher."); break; } @@ -1068,7 +1072,8 @@ 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( + getCapabilityIndex(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..80f2572e1a 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -23,6 +23,8 @@ import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_NO_PERMISSION 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.util.GeneralUtil.getCapabilityIndex; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -81,6 +83,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 +127,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 +484,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; } } @@ -1430,7 +1442,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 +1592,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(getCapabilityIndex(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 +3557,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 +3596,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..abde127654 100644 --- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java +++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java @@ -16,8 +16,13 @@ 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.GeneralUtil.getCapabilityIndex; import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; import android.annotation.SuppressLint; @@ -31,6 +36,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 +52,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 +78,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 = "*"; @@ -745,12 +754,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 +769,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 +800,7 @@ public class WifiConfigurationUtil { return false; } if (config.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP) - && (supportedFeatureSet & WifiManager.WIFI_FEATURE_DPP_AKM) == 0) { + && !supportedFeatureSet.get(getCapabilityIndex(WifiManager.WIFI_FEATURE_DPP_AKM))) { Log.e(TAG, "DPP AKM is not supported"); return false; } @@ -793,10 +816,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 +1183,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_WPA3_SAE)); case WifiConfiguration.SECURITY_TYPE_OWE: - return 0 != (wifiFeatures & WifiManager.WIFI_FEATURE_OWE); + return wifiFeatures.get(getCapabilityIndex(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..ceb107fd75 100644 --- a/service/java/com/android/server/wifi/WifiConnectivityHelper.java +++ b/service/java/com/android/server/wifi/WifiConnectivityHelper.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.util.GeneralUtil.getCapabilityIndex; + import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -25,6 +27,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 +66,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(getCapabilityIndex(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..666b3594f8 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 mAutojoinRestrictionSecurityTypes = 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, + mAutojoinRestrictionSecurityTypes); + // 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 setAutojoinRestrictionSecurityTypes(int restrictions) { + localLog("Set auto join restriction on select security types - restrictions: " + + restrictions); + mAutojoinRestrictionSecurityTypes = restrictions; + } + + /** + * Return auto join restriction on select security types + */ + public int getAutojoinRestrictionSecurityTypes() { + return mAutojoinRestrictionSecurityTypes; + } + + /** * 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..cff47d2257 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,10 +300,10 @@ 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); mWifiMetrics = new WifiMetrics(mContext, mFrameworkFacade, mClock, wifiLooper, awareMetrics, rttMetrics, new WifiPowerMetrics(mBatteryStats), mWifiP2pMetrics, mDppMetrics, mWifiMonitor, mWifiDeviceStateChangeManager); @@ -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,22 +578,23 @@ 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); @@ -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..d3b7ab39c3 100644 --- a/service/java/com/android/server/wifi/WifiLinkLayerStats.java +++ b/service/java/com/android/server/wifi/WifiLinkLayerStats.java @@ -16,7 +16,9 @@ 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; @@ -303,6 +305,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 +468,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 +479,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..67df0be144 100644 --- a/service/java/com/android/server/wifi/WifiLockManager.java +++ b/service/java/com/android/server/wifi/WifiLockManager.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; @@ -43,6 +45,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 +852,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_LOW_LATENCY))) { mLatencyModeSupport = LOW_LATENCY_SUPPORTED; } else { mLatencyModeSupport = LOW_LATENCY_NOT_SUPPORTED; diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 93cb2ab8d8..b253161519 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,12 +127,15 @@ 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; @@ -126,8 +155,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 +167,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 +242,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 +276,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 +303,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 +318,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 +339,8 @@ public class WifiMetrics { private boolean mFirstConnectionAfterBoot = true; private long mLastTotalBeaconRx = 0; private int mScorerUid = Process.WIFI_UID; + @VisibleForTesting + int mUnusableEventType = WifiIsUnusableEvent.TYPE_UNKNOWN; /** * Wi-Fi usability state per interface as predicted by the network scorer. @@ -446,11 +486,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; @@ -488,7 +536,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 +660,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 +714,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 +1240,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; @@ -1650,7 +1707,7 @@ public class WifiMetrics { new WifiDeviceStateChangeManager.StateChangeCallback() { @Override public void onScreenStateChanged(boolean screenOn) { - setScreenState(screenOn); + handleScreenStateChanged(screenOn); } }); } @@ -4927,8 +4984,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 +5150,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 +5210,68 @@ 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); + } + } + } + } + } + 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); pw.println(line.toString()); } @@ -5624,7 +5748,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 +6097,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 +6115,7 @@ public class WifiMetrics { mProbeElapsedTimeSinceLastUpdateMs = -1; mProbeMcsRateSinceLastUpdate = -1; mScoreBreachLowTimeMillis = -1; + mAccumulatedLabelBadCount = 0; mMeteredNetworkStatsBuilder.clear(); mWifiConfigStoreReadDurationHistogram.clear(); mWifiConfigStoreWriteDurationHistogram.clear(); @@ -6049,11 +6174,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(); + } } } @@ -6936,6 +7066,7 @@ public class WifiMetrics { WifiIsUnusableEvent event = new WifiIsUnusableEvent(); event.type = triggerType; + mUnusableEventType = triggerType; if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) { event.firmwareAlertCode = firmwareAlertCode; } @@ -6995,12 +7126,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 +7155,163 @@ 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(); + 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; + } + } + wifiUsabilityStatsEntry.linkStats[i] = linkStats; + } + } + wifiUsabilityStatsEntry.mloMode = stats.wifiMloMode; + wifiUsabilityStatsEntry.labelBadEventCount = mAccumulatedLabelBadCount; + } + wifiUsabilityStatsEntry.timeStampMs = stats.timeStampInMs; wifiUsabilityStatsEntry.totalTxSuccess = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo; @@ -7050,6 +7339,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 +7376,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 +7471,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 +7514,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 +7622,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 +7699,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 = @@ -7363,6 +7763,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 +7782,8 @@ 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)); linkStats.put(inStat.link_id, outStat); } @@ -7427,7 +7831,8 @@ 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 ); } @@ -7559,6 +7964,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 +7983,8 @@ public class WifiMetrics { stats[i].totalBackgroundScanTimeMs, stats[i].totalRoamScanTimeMs, stats[i].totalPnoScanTimeMs, - stats[i].totalHotspot2ScanTimeMs); + stats[i].totalHotspot2ScanTimeMs, + txTimeMsPerLevel); } } @@ -7616,6 +8030,12 @@ 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; return out; } @@ -7627,16 +8047,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 +8070,7 @@ public class WifiMetrics { if (!isPrimary(ifaceName)) { return; } - if (mWifiUsabilityStatsEntriesList.isEmpty() || !mScreenOn) { + if (mWifiUsabilityStatsEntriesRingBuffer.isEmpty() || !mScreenOn) { return; } if (label == WifiUsabilityStats.LABEL_GOOD) { @@ -7658,9 +8080,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 +8098,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 +8108,10 @@ public class WifiMetrics { createWifiUsabilityStatsWithLabel(label, triggerType, firmwareAlertCode)); } + mAccumulatedLabelBadCount++; } - mWifiUsabilityStatsCounter = 0; - mWifiUsabilityStatsEntriesList.clear(); + mWifiUsabilityStatsEntryCounter = 0; + mWifiUsabilityStatsEntriesRingBuffer.clear(); } } @@ -8770,6 +9193,243 @@ 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; + } + + /** + * Log a ScorerPredictionResultReported atom. + */ + public void logScorerPredictionResult(boolean hasActiveModem, + boolean hasActiveSubInfo, + boolean isMobileDataEnabled, + int pollingIntervalMs, + int aospScorerPrediction, + int externalScorerPrediction, + boolean lingering, + WifiInfo wifiInfo, + ConnectionCapabilities connectionCapabilities + ) { + boolean isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable(); + boolean isThroughputSufficient = mWifiDataStall.isThroughputSufficient(); + int deviceState = getDeviceStateForScorer( + hasActiveModem, + hasActiveSubInfo, isMobileDataEnabled, isCellularDataAvailable, + mAdaptiveConnectivityEnabled); + int scorerUnusableEvent = convertWifiUnusableTypeForScorer(mUnusableEventType); + int wifiFrameworkState = getFrameworkStateForScorer(lingering); + Speeds speedsNetworkCapabilities = getNetworkCapabilitiesSpeeds(); + SpeedSufficient speedSufficientNetworkCapabilities = + calcSpeedSufficientNetworkCapabilities(speedsNetworkCapabilities); + WifiDataStall.Speeds speedsThroughputPredictor = mWifiDataStall.getThrouhgputPredictorSpeeds( + wifiInfo, connectionCapabilities); + SpeedSufficient speedSufficientThroughputPredictor = + calcSpeedSufficientThroughputPredictor(speedsThroughputPredictor); + + WifiStatsLog.write_non_chained(SCORER_PREDICTION_RESULT_REPORTED, + Process.WIFI_UID, + null, + aospScorerPrediction, + scorerUnusableEvent, + isThroughputSufficient, deviceState, pollingIntervalMs, + wifiFrameworkState, speedSufficientNetworkCapabilities.Downstream, + speedSufficientNetworkCapabilities.Upstream, + speedSufficientThroughputPredictor.Downstream, + speedSufficientThroughputPredictor.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, + wifiFrameworkState, speedSufficientNetworkCapabilities.Downstream, + speedSufficientNetworkCapabilities.Upstream, + speedSufficientThroughputPredictor.Downstream, + speedSufficientThroughputPredictor.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 +10108,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 +10118,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); diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 9ec97ee493..d363b49041 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -21,11 +21,15 @@ 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.getCapabilityIndex; +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; @@ -134,12 +138,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; @@ -391,7 +396,7 @@ public class WifiNative { /** Network observer registered for this interface */ public NetworkObserverInternal networkObserver; /** Interface feature set / capabilities */ - public long featureSet; + public BitSet featureSet; public int bandsSupported; public DeviceWiphyCapabilities phyCapabilities; public WifiHal.WifiInterface iface; @@ -1757,7 +1762,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(getCapabilityIndex(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 +2101,7 @@ public class WifiNative { ies, result.getCapabilities(), mIsEnhancedOpenSupported, + mIsRsnOverridingSupported, result.getFrequencyMhz(), mUnknownAkmMap); String flags = capabilities.generateCapabilitiesString(); @@ -3618,6 +3630,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 +3768,7 @@ public class WifiNative { WifiLinkLayerStats stats = mWifiVendorHal.getWifiLinkLayerStats(ifaceName); if (stats != null) { stats.aggregateLinkLayerStats(); + stats.wifiMloMode = getMloMode(); } return stats; } @@ -3931,19 +3949,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 +3989,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(getCapabilityIndex(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(getCapabilityIndex(WifiManager.WIFI_FEATURE_DPP_AKM)); Log.v(TAG, ": DPP AKM supported"); } } @@ -5159,12 +5176,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 +5189,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..f8328de7b4 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -22,6 +22,7 @@ import static android.net.wifi.WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SEL import static android.net.wifi.WifiNetworkSelectionConfig.ASSOCIATED_NETWORK_SELECTION_OVERRIDE_NONE; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import android.annotation.IntDef; import android.annotation.NonNull; @@ -467,7 +468,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 +477,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 +614,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 +682,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 +709,8 @@ public class WifiNetworkSelector { mIsEnhancedOpenSupportedInitialized = true; ClientModeManager primaryManager = mWifiInjector.getActiveModeWarden().getPrimaryClientModeManager(); - mIsEnhancedOpenSupported = (primaryManager.getSupportedFeatures() & WIFI_FEATURE_OWE) != 0; + mIsEnhancedOpenSupported = primaryManager.getSupportedFeatures() + .get(getCapabilityIndex(WIFI_FEATURE_OWE)); return mIsEnhancedOpenSupported; } @@ -1075,7 +1100,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 +1118,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 +1156,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..05868baf17 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,6 +1118,7 @@ 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 @@ -1148,12 +1197,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 +1227,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 +1250,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 +1294,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..436aac1d82 100644 --- a/service/java/com/android/server/wifi/WifiServiceImpl.java +++ b/service/java/com/android/server/wifi/WifiServiceImpl.java @@ -28,8 +28,10 @@ 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; @@ -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; @@ -335,7 +338,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 +519,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 +696,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 +874,20 @@ public class WifiServiceImpl extends BaseWifiService { mWifiInjector.getWifiDeviceStateChangeManager().handleBootCompleted(); setPulledAtomCallbacks(); mTwtManager.registerWifiNativeTwtEvents(); + 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(); }, TAG + "#handleBootCompleted"); } @@ -1195,6 +1197,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 +1313,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 +1495,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 +1516,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 +1657,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 +1678,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; } @@ -1749,6 +1805,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 +1842,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 +1949,8 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public boolean stopSoftAp() { + enforceValidCallingUser(); + // NETWORK_STACK is a signature only permission. enforceNetworkStackPermission(); @@ -1989,7 +2050,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 +2060,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()]; @@ -2293,7 +2353,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 +2911,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 +2938,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 @@ -3535,7 +3597,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 +3693,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 +3715,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 +3731,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 +3755,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 +3768,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 +3792,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 +3800,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 +3820,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 +3829,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 +3849,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 +3859,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 +3959,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 +4443,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 +4736,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 +4866,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 +4879,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 +5101,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 +5118,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 +5134,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 +5154,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); @@ -5604,7 +5683,7 @@ public class WifiServiceImpl extends BaseWifiService { mWifiInjector.getWifiVoipDetector().dump(fd, pw, args); } pw.println(); - mWifiResourceCache.dump(pw); + mResourceCache.dump(pw); } }, TAG + "#dump"); } @@ -5739,7 +5818,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 @@ -6227,7 +6306,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 +6339,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 +6363,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 +6377,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 +6396,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")); } /** @@ -7555,7 +7641,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); @@ -7761,11 +7848,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 +7869,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 +7926,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 +7958,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public String[] getOemPrivilegedWifiAdminPackages() { - return mContext.getResources() + return mResourceCache .getStringArray(R.array.config_oemPrivilegedWifiAdminPackages); } @@ -7951,7 +8040,7 @@ public class WifiServiceImpl extends BaseWifiService { } @Override public int getMaxNumberOfChannelsPerRequest() { - return mContext.getResources() + return mResourceCache .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels); } @@ -7999,7 +8088,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 +8103,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"); } @@ -8538,7 +8633,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 +8668,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 +8697,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 +8857,90 @@ public class WifiServiceImpl extends BaseWifiService { } }, TAG + "#queryD2dAllowedWhenInfraStaDisabled"); } + + /** + * See {@link WifiManager#setAutoJoinRestrictionSecurityTypes(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 setAutojoinRestrictionSecurityTypes(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("setAutoJoinRestrictionSecurityTypes uid=% Package Name=% restrictions=%") + .c(uid).c(getPackageName(extras)).c(restrictions).flush(); + } + mWifiThreadRunner.post(() -> { + mWifiConnectivityManager.setAutojoinRestrictionSecurityTypes(restrictions); + }, TAG + "#setAutoJoinRestrictionSecurityTypes"); + } + + /** + * See {@link WifiManager#getAutojoinRestrictionSecurityTypes(Executor, Consumer)} + */ + @Override + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + public void getAutojoinRestrictionSecurityTypes(@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("getAutojoinRestrictionSecurityTypes: Uid=% Package Name=%").c( + Binder.getCallingUid()).c(getPackageName(extras)).flush(); + } + + mWifiThreadRunner.post(() -> { + try { + listener.onResult(mWifiConnectivityManager.getAutojoinRestrictionSecurityTypes()); + } catch (RemoteException e) { + Log.e(TAG, e.getMessage(), e); + } + }, TAG + "#getAutojoinRestrictionSecurityTypes"); + } } 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..1439406afb 100644 --- a/service/java/com/android/server/wifi/WifiShellCommand.java +++ b/service/java/com/android/server/wifi/WifiShellCommand.java @@ -29,6 +29,9 @@ 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; 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.HalDeviceManager.HDM_CREATE_IFACE_AP; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_AP_BRIDGE; @@ -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); @@ -1123,7 +1174,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 +1215,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 +1225,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 +1244,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 +1262,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 +2246,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 +2288,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 +3109,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 +3130,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 +3354,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 +3405,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..9d2f1d5ffa 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.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_AP_BRIDGE; import static com.android.server.wifi.HalDeviceManager.HDM_CREATE_IFACE_STA; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import android.annotation.NonNull; import android.annotation.Nullable; @@ -56,6 +57,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; @@ -788,15 +790,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(getCapabilityIndex((long) pair.first)); } } - enter("System feature set: %").c(featureSet).flush(); + enter("System feature set: %").c(featureSet.toString()).flush(); return featureSet; } @@ -873,50 +875,51 @@ 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( + getCapabilityIndex(WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS)); } } } if (mWifiGlobals.isWpa3SaeH2eSupported()) { - featureSet |= WifiManager.WIFI_FEATURE_SAE_H2E; + featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SAE_H2E)); } Set<Integer> supportedIfaceTypes = mHalDeviceManager.getSupportedIfaceTypes(); if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_STA)) { - featureSet |= WifiManager.WIFI_FEATURE_INFRA; + featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_INFRA)); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_AP)) { - featureSet |= WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT; + featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_MOBILE_HOTSPOT)); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_P2P)) { - featureSet |= WifiManager.WIFI_FEATURE_P2P; + featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_P2P)); } if (supportedIfaceTypes.contains(WifiChip.IFACE_TYPE_NAN)) { - featureSet |= WifiManager.WIFI_FEATURE_AWARE; + featureSet.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_AWARE)); } return featureSet; diff --git a/service/java/com/android/server/wifi/aware/PairingConfigManager.java b/service/java/com/android/server/wifi/aware/PairingConfigManager.java index 6bc7e3504b..59061d2439 100644 --- a/service/java/com/android/server/wifi/aware/PairingConfigManager.java +++ b/service/java/com/android/server/wifi/aware/PairingConfigManager.java @@ -24,6 +24,7 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -41,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 @@ -75,7 +80,6 @@ public class PairingConfigManager { private byte[] createRandomNik() { long first, second; - Random mRandom = new SecureRandom(); first = mRandom.nextLong(); second = mRandom.nextLong(); @@ -118,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); @@ -154,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); @@ -185,17 +185,19 @@ public class PairingConfigManager { public void removePairedDevice(String packageName, String alias) { mAliasToNikMap.remove(alias); mAliasToSecurityInfoMap.remove(alias); - Set<String> aliasSet = mPerAppPairedAliasMap.remove(packageName); - if (aliasSet == null) { - return; + if (mPerAppPairedAliasMap.containsKey(packageName)) { + mPerAppPairedAliasMap.get(packageName).remove(alias); } - aliasSet.remove(alias); } /** * Get all paired devices alias for target calling app */ public List<String> getAllPairedDevices(String callingPackage) { - return new ArrayList<>(mPerAppPairedAliasMap.get(callingPackage)); + Set<String> aliasSet = mPerAppPairedAliasMap.get(callingPackage); + if (aliasSet == null) { + return Collections.emptyList(); + } + return new ArrayList<>(aliasSet); } } 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..3df13e88a9 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(); } } }, @@ -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..6ce53df724 100644 --- a/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiChipAidlImpl.java @@ -23,6 +23,8 @@ import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_80; import static android.hardware.wifi.WifiChannelWidthInMhz.WIDTH_80P80; import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -78,6 +80,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 +392,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 +401,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 +1593,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT)); } if (bitmapContains(halFeatureSet, FeatureSetMask.D2D_RTT)) { - features |= WifiManager.WIFI_FEATURE_D2D_RTT; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_D2D_RTT)); } if (bitmapContains(halFeatureSet, FeatureSetMask.D2AP_RTT)) { - features |= WifiManager.WIFI_FEATURE_D2AP_RTT; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_D2AP_RTT)); } if (bitmapContains(halFeatureSet, FeatureSetMask.SET_LATENCY_MODE)) { - features |= WifiManager.WIFI_FEATURE_LOW_LATENCY; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_LOW_LATENCY)); } if (bitmapContains(halFeatureSet, FeatureSetMask.P2P_RAND_MAC)) { - features |= WifiManager.WIFI_FEATURE_P2P_RAND_MAC; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_P2P_RAND_MAC)); } if (bitmapContains(halFeatureSet, FeatureSetMask.WIGIG)) { - features |= WifiManager.WIFI_FEATURE_INFRA_60G; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_INFRA_60G)); } if (bitmapContains(halFeatureSet, FeatureSetMask.T2LM_NEGOTIATION)) { - features |= WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION; + features.set(getCapabilityIndex(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..505b6545d4 100644 --- a/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiChipHidlImpl.java @@ -23,6 +23,8 @@ import static android.hardware.wifi.V1_6.WifiChannelWidthInMhz.WIDTH_80; import static android.hardware.wifi.V1_6.WifiChannelWidthInMhz.WIDTH_80P80; import static android.net.wifi.CoexUnsafeChannel.POWER_CAP_NONE; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -64,6 +66,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 +239,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 +249,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 +803,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 +826,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 +854,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( @@ -1790,11 +1793,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(getCapabilityIndex(sChipFeatureCapabilityTranslation[i][0])); } } return features; @@ -1807,14 +1810,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(getCapabilityIndex(sChipFeatureCapabilityTranslation15[i][0])); } } return features; @@ -1827,14 +1830,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(getCapabilityIndex(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..84db58d1f9 100644 --- a/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceAidlImpl.java @@ -17,6 +17,7 @@ package com.android.server.wifi.hal; import static com.android.server.wifi.hal.WifiHalAidlImpl.isServiceVersionAtLeast; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import android.annotation.NonNull; import android.annotation.Nullable; @@ -80,6 +81,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 +283,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 +295,7 @@ public class WifiStaIfaceAidlImpl implements IWifiStaIface { } catch (ServiceSpecificException e) { handleServiceSpecificException(e, methodStr); } - return 0L; + return new BitSet(); } } @@ -1265,59 +1267,60 @@ 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(getCapabilityIndex(WifiManager.WIFI_FEATURE_PASSPOINT)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN)) { - features |= WifiManager.WIFI_FEATURE_SCANNER; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCANNER)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.PNO)) { - features |= WifiManager.WIFI_FEATURE_PNO; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PNO)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS)) { - features |= WifiManager.WIFI_FEATURE_TDLS; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.TDLS_OFFCHANNEL)) { - features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; + features.set(getCapabilityIndex(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(getCapabilityIndex(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.RSSI_MONITOR)) { - features |= WifiManager.WIFI_FEATURE_RSSI_MONITOR; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_RSSI_MONITOR)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.KEEP_ALIVE)) { - features |= WifiManager.WIFI_FEATURE_MKEEP_ALIVE; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_MKEEP_ALIVE)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.ND_OFFLOAD)) { - features |= WifiManager.WIFI_FEATURE_CONFIG_NDO; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONFIG_NDO)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.CONTROL_ROAMING)) { - features |= WifiManager.WIFI_FEATURE_CONTROL_ROAMING; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_CONTROL_ROAMING)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.PROBE_IE_ALLOWLIST)) { - features |= WifiManager.WIFI_FEATURE_IE_WHITELIST; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_IE_WHITELIST)); } if (hasCapability(halFeatureSet, android.hardware.wifi.IWifiStaIface.FeatureSetMask.SCAN_RAND)) { - features |= WifiManager.WIFI_FEATURE_SCAN_RAND; + features.set(getCapabilityIndex(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( + getCapabilityIndex(WifiManager.WIFI_FEATURE_AGGRESSIVE_ROAMING_MODE_SUPPORT)); } return features; } @@ -1476,11 +1479,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..bdcecdeb03 100644 --- a/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java +++ b/service/java/com/android/server/wifi/hal/WifiStaIfaceHidlImpl.java @@ -18,6 +18,8 @@ package com.android.server.wifi.hal; import static android.net.wifi.WifiUsabilityStatsEntry.LINK_STATE_UNKNOWN; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -61,6 +63,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 +162,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 +470,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 +892,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_PASSPOINT)); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN)) { - features |= WifiManager.WIFI_FEATURE_SCANNER; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_SCANNER)); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.PNO)) { - features |= WifiManager.WIFI_FEATURE_PNO; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_PNO)); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS)) { - features |= WifiManager.WIFI_FEATURE_TDLS; + features.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_TDLS)); } if (hasCapability(caps, android.hardware.wifi.V1_0.IWifiStaIface.StaIfaceCapabilityMask.TDLS_OFFCHANNEL)) { - features |= WifiManager.WIFI_FEATURE_TDLS_OFFCHANNEL; + features.set(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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(getCapabilityIndex(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/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..6fb46f4667 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); @@ -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/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..3da0bf1586 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; @@ -241,7 +243,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 +257,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 +300,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 +379,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 +400,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 +420,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 +434,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 +469,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 +531,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 +649,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 +698,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 +759,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 +803,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 +821,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); @@ -842,7 +898,7 @@ public class ApConfigUtil { * @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) { if (!ApConfigUtil.isIeee80211beSupported(context)) { @@ -853,7 +909,7 @@ public class ApConfigUtil { return false; } if (isBridgedMode - && !context.getResources().getBoolean( + && !context.getResourceCache().getBoolean( R.bool.config_wifiSoftApSingleLinkMloInBridgedModeSupported)) { return false; } @@ -876,7 +932,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 +1044,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 +1107,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 +1144,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 +1155,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 +1178,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 +1191,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 +1206,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 +1220,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 +1235,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 +1246,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 +1257,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 +1268,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 +1280,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 +1312,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 +1324,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 +1336,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 +1347,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 +1479,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 +1488,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 +1662,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 +1681,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..62e57f7e87 100644 --- a/service/proto/src/metrics.proto +++ b/service/proto/src/metrics.proto @@ -2709,6 +2709,25 @@ 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; } message ContentionTimeStats { @@ -2742,6 +2761,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 +2836,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 +2901,103 @@ 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; +} + +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 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..1de52c87b7 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,7 @@ 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.util.GeneralUtil.longToBitset; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; @@ -63,10 +65,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,8 +80,10 @@ 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.IBinder; @@ -96,6 +98,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; @@ -158,8 +161,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 +209,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { private BroadcastReceiver mEmergencyCallbackModeChangedBr; private BroadcastReceiver mEmergencyCallStateChangedBr; + private StaticMockitoSession mStaticMockSession; /** * Set up the test environment. @@ -215,8 +219,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 +234,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); @@ -341,6 +349,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { @After public void cleanUp() throws Exception { mActiveModeWarden = null; + mStaticMockSession.finishMocking(); mLooper.dispatchAll(); } @@ -385,7 +394,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(longToBitset(testFeatureSet)); // ClientModeManager starts in SCAN_ONLY role. mClientListener.onRoleChanged(mClientModeManager); mLooper.dispatchAll(); @@ -431,7 +441,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); when(mClientModeManager.getCurrentNetwork()).thenReturn(null); - when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(TEST_FEATURE_SET); + when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(longToBitset(TEST_FEATURE_SET)); if (!isClientModeSwitch) { mClientListener.onStarted(mClientModeManager); mLooper.dispatchAll(); @@ -678,7 +688,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 +797,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,7 +1508,7 @@ 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(); @@ -1532,7 +1542,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 +1657,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(); @@ -3027,16 +3037,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 +3131,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)); @@ -3361,7 +3371,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 +3393,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 +3406,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 +3436,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 +3448,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 +3460,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 +3473,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 +3498,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 +3516,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( @@ -3521,7 +3531,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { 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( @@ -3559,7 +3569,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 +3593,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 +3605,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 +3617,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 +3630,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 +3644,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 +3657,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 +3682,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 +3695,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 +3708,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 +3722,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 +3737,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 +3752,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 +3837,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 +3918,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 +3982,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 +4042,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 +4090,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 +4367,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 +4445,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 +4749,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 +4814,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( @@ -4866,7 +4876,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { enterScanOnlyModeActiveState(); long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( - supportedFeaturesFromWifiNative); + longToBitset(supportedFeaturesFromWifiNative)); when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); mClientListener.onStarted(mClientModeManager); @@ -4890,20 +4900,20 @@ public class ActiveModeWardenTest extends WifiBaseTest { enterScanOnlyModeActiveState(); long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( - supportedFeaturesFromWifiNative); + longToBitset(supportedFeaturesFromWifiNative)); mClientListener.onStarted(mClientModeManager); assertEquals(supportedFeaturesFromWifiNative, 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()); - when(mResources.getBoolean( + when(mWifiResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) .thenReturn(true); mClientListener.onStarted(mClientModeManager); @@ -4912,10 +4922,10 @@ public class ActiveModeWardenTest extends WifiBaseTest { | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB, 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 @@ -4928,17 +4938,17 @@ public class ActiveModeWardenTest extends WifiBaseTest { private long testGetSupportedFeaturesCaseForMacRandomization( long 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())) - .thenReturn(supportedFeaturesFromWifiNative); + .thenReturn(longToBitset(supportedFeaturesFromWifiNative)); mClientListener.onStarted(mClientModeManager); mLooper.dispatchAll(); return mActiveModeWarden.getSupportedFeatureSet(); @@ -4972,7 +4982,7 @@ public class ActiveModeWardenTest extends WifiBaseTest { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( !rttDisabled); when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn( - supportedFeaturesFromWifiNative); + longToBitset(supportedFeaturesFromWifiNative)); mClientListener.onStarted(mClientModeManager); mLooper.dispatchAll(); return mActiveModeWarden.getSupportedFeatureSet(); 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..92933f4ef5 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.util.GeneralUtil.longToBitset; 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,7 @@ 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); + longToBitset(WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE)); when(mWifiInjector.getWifiGlobals()).thenReturn(mWifiGlobals); when(mWifiInjector.getWifiHandlerThread()).thenReturn(mWifiHandlerThread); when(mWifiInjector.getSsidTranslator()).thenReturn(mSsidTranslator); @@ -1574,6 +1576,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 +1803,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 +2651,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. @@ -3970,7 +4025,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); + longToBitset(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 +4060,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); + longToBitset(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 +4114,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); + longToBitset(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 +4174,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); + longToBitset(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 +4715,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); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -4687,7 +4742,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); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -5407,7 +5462,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); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(llStats); when(mWifiNative.signalPoll(any())).thenReturn(signalPollResults); @@ -6028,7 +6083,7 @@ public class ClientModeImplTest extends WifiBaseTest { failOnRssiChangeBroadcast(); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + longToBitset(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 +6110,7 @@ public class ClientModeImplTest extends WifiBaseTest { failOnRssiChangeBroadcast(); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats stats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(stats); when(mWifiDataStall.checkDataStallAndThroughputSufficiency(any(), @@ -6891,9 +6946,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); + longToBitset(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 +7856,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 +8041,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); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); InOrder inOrder = inOrder(mWifiNative, mWifiScoreReport); inOrder.verify(mWifiNative, never()).getWifiLinkLayerStats(any()); connect(); @@ -8996,7 +9054,7 @@ public class ClientModeImplTest extends WifiBaseTest { clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis()); @@ -9040,7 +9098,7 @@ public class ClientModeImplTest extends WifiBaseTest { verifyNoMoreInteractions(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats()); // No link layer stats collection on secondary CMM. @@ -9059,7 +9117,7 @@ public class ClientModeImplTest extends WifiBaseTest { clearInvocations(mWifiNative, mWifiMetrics, mWifiDataStall); when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(new WifiLinkLayerStats()); // No link layer stats collection on secondary CMM. @@ -9092,7 +9150,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); + longToBitset(WifiManager.WIFI_FEATURE_LINK_LAYER_STATS)); WifiLinkLayerStats oldLLStats = new WifiLinkLayerStats(); when(mWifiNative.getWifiLinkLayerStats(any())).thenReturn(oldLLStats); mLooper.moveTimeForward(mWifiGlobals.getPollRssiIntervalMillis()); @@ -9121,7 +9179,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 +9802,7 @@ public class ClientModeImplTest extends WifiBaseTest { throws Exception { if (isTrustOnFirstUseSupported) { when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); } mCmi.mInsecureEapNetworkHandler = mInsecureEapNetworkHandler; @@ -10099,6 +10157,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 +10186,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 +10879,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(longToBitset(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 +10973,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); + longToBitset(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 +11204,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( + longToBitset(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..d9dba28708 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.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -111,7 +112,7 @@ 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); + longToBitset(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..f4fe2814b8 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.util.GeneralUtil.longToBitset; 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; @@ -1738,6 +1740,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. @@ -3987,6 +4019,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 /////////////////////////////////////////////////////////////////////////////////////// @@ -4361,9 +4491,9 @@ public class HalDeviceManagerTest extends WifiBaseTest { mChipMockBase = chipMockBase; } - public WifiChip.Response<Long> answer() { - WifiChip.Response<Long> response = - new WifiChip.Response<>(mChipMockBase.chipCapabilities); + public WifiChip.Response<BitSet> answer() { + WifiChip.Response<BitSet> response = + new WifiChip.Response<>(longToBitset(mChipMockBase.chipCapabilities)); response.setStatusCode(mChipMockBase.allowGetCapsBeforeIfaceCreated ? WifiHal.WIFI_STATUS_SUCCESS : WifiHal.WIFI_STATUS_ERROR_UNKNOWN); return response; @@ -5285,4 +5415,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..0d54c8114f 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; @@ -57,8 +56,10 @@ import android.net.MacAddress; 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; @@ -105,7 +106,7 @@ public class HostapdHalAidlImpTest extends WifiBaseTest { 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 +193,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()); @@ -1194,15 +1196,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..a6a9010a18 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; @@ -37,6 +51,7 @@ import android.hidl.manager.V1_0.IServiceNotification; 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.IHwBinder; @@ -75,7 +90,7 @@ public class HostapdHalHidlImpTest extends WifiBaseTest { 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 +101,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 +173,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 +190,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(), 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..67f9b27f83 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/MboOceControllerTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; + import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.*; @@ -34,6 +36,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 +78,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_MBO)); } if (isOceEnabled) { - featureSet |= WifiManager.WIFI_FEATURE_OCE; + featureSet.set(getCapabilityIndex(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..a548cd5663 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.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.*; @@ -68,7 +69,7 @@ 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); + longToBitset(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..8a0d33daaa 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.util.GeneralUtil.longToBitset; + 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); + longToBitset(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..7ae7175330 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,7 +62,6 @@ 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; @@ -79,6 +79,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,6 +93,7 @@ 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; @@ -100,12 +102,14 @@ 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; @@ -195,7 +199,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; @@ -238,6 +242,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) { @@ -323,8 +328,13 @@ public class SoftApManagerTest extends WifiBaseTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mStaticMockSession = mockitoSession() + .mockStatic(WifiInjector.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 +350,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 +403,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()) @@ -452,6 +463,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 +554,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 +631,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 +669,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 +711,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 +750,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 +784,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 +1029,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)); } /** @@ -1079,7 +1096,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 +1174,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 +1242,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 +1296,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 +1331,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 +1378,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 +1989,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 +2553,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 +2594,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 +2739,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 +2767,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 +2803,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 +3197,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 +3233,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 +3344,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 +3378,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 +3555,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 +3795,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 +3818,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 +3829,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 +3851,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 +3868,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 +3882,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 +3896,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 +3912,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 +3930,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 +3999,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 +4008,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 +4079,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 +4103,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 +4127,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 +4153,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 +4182,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 +4209,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 +4225,112 @@ public class SoftApManagerTest extends WifiBaseTest { 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..0bb0be97d2 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,14 @@ 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.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -52,9 +57,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 +121,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 +133,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 +142,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 +150,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 +190,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 +213,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 +258,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 +282,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 @@ -1409,6 +1437,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 +1464,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 +1476,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 +1832,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 +1845,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesWpa3Sae() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.SAE, WIFI_FEATURE_WPA3_SAE); + checkKeyMgmtCapabilities(KeyMgmtMask.SAE, longToBitset(WIFI_FEATURE_WPA3_SAE)); } /** @@ -1819,7 +1853,7 @@ 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, longToBitset(WIFI_FEATURE_WPA3_SUITE_B)); } /** @@ -1827,7 +1861,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesOwe() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.OWE, WIFI_FEATURE_OWE); + checkKeyMgmtCapabilities(KeyMgmtMask.OWE, longToBitset(WIFI_FEATURE_OWE)); } /** @@ -1836,7 +1870,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { @Test public void testGetKeyMgmtCapabilitiesOweAndSae() throws Exception { checkKeyMgmtCapabilities(KeyMgmtMask.OWE | KeyMgmtMask.SAE, - WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE); + longToBitset(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE)); } /** @@ -1844,8 +1878,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, + longToBitset(WIFI_FEATURE_DPP | WIFI_FEATURE_DPP_ENROLLEE_RESPONDER)); } /** @@ -1853,7 +1887,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesWapi() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, WIFI_FEATURE_WAPI); + checkKeyMgmtCapabilities(KeyMgmtMask.WAPI_PSK, longToBitset(WIFI_FEATURE_WAPI)); } /** @@ -1861,7 +1895,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesFilsSha256() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256, WIFI_FEATURE_FILS_SHA256); + checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA256, longToBitset(WIFI_FEATURE_FILS_SHA256)); } /** @@ -1869,7 +1903,7 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { */ @Test public void testGetKeyMgmtCapabilitiesFilsSha384() throws Exception { - checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384, WIFI_FEATURE_FILS_SHA384); + checkKeyMgmtCapabilities(KeyMgmtMask.FILS_SHA384, longToBitset(WIFI_FEATURE_FILS_SHA384)); } /** @@ -2133,7 +2167,8 @@ public class SupplicantStaIfaceHalAidlImplTest extends WifiBaseTest { executeAndValidateInitializationSequence(); doReturn(WpaDriverCapabilitiesMask.MBO).when(mISupplicantStaIfaceMock) .getWpaDriverCapabilities(); - assertEquals(WIFI_FEATURE_MBO, mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME)); + assertTrue(longToBitset(WIFI_FEATURE_MBO) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -2144,8 +2179,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(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -2156,8 +2191,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(longToBitset(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 +2313,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 +2400,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 +2435,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()); - // Validate that we initiated another connect sequence to the fallback SUPPLICANT_SSID. + // 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); - // Fallback SSID was not found, finally broadcast NETWORK_NOT_FOUND and try the first SSID - // again. + // 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); + + // 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 +2869,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(getCapabilityIndex(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS)); + capabilities.set(getCapabilityIndex(WIFI_FEATURE_DECORATED_IDENTITY)); + return capabilities; } /** @@ -3396,4 +3480,15 @@ 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); + assertFalse(mDut.mHasMigratedLegacyKeystoreAliases); + executeAndValidateInitializationSequence(); + 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..4ba62fcd06 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,9 @@ 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.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -107,6 +110,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 +140,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 +317,7 @@ public class SupplicantStaIfaceHalHidlImplTest extends WifiBaseTest { ssids.add(TRANSLATED_SUPPLICANT_SSID); return ssids; }); + when(mClock.getElapsedSinceBootMillis()).thenReturn(TIME_START_MS); mDut = new SupplicantStaIfaceHalSpy(); } @@ -1638,6 +1644,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 +1671,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 +1683,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 +2191,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 +2199,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 +2218,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(longToBitset(WIFI_FEATURE_WPA3_SAE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2223,8 +2237,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(longToBitset(WIFI_FEATURE_WPA3_SUITE_B) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2242,7 +2256,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(longToBitset(WIFI_FEATURE_OWE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2261,8 +2276,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(longToBitset(WIFI_FEATURE_OWE | WIFI_FEATURE_WPA3_SAE) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2280,7 +2295,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(longToBitset(WIFI_FEATURE_DPP) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2297,9 +2313,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(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER))); } /** @@ -2317,9 +2332,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(getCapabilityIndex(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER))); } /** @@ -2337,7 +2351,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(longToBitset(WIFI_FEATURE_WAPI) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2355,8 +2370,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(longToBitset(WIFI_FEATURE_FILS_SHA256) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -2374,8 +2389,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(longToBitset(WIFI_FEATURE_FILS_SHA384) + .equals(mDut.getAdvancedCapabilities(WLAN0_IFACE_NAME))); } /** @@ -3506,15 +3521,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 +3547,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(longToBitset(WIFI_FEATURE_MBO) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3552,8 +3568,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(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3573,8 +3589,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(longToBitset(WIFI_FEATURE_MBO | WIFI_FEATURE_OCE) + .equals(mDut.getWpaDriverFeatureSet(WLAN0_IFACE_NAME))); } /** @@ -3751,6 +3767,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 +3871,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 +3904,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..84de1f8d64 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,8 @@ package com.android.server.wifi; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -49,6 +51,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 +928,9 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest { @Test public void testGetAdvancedCapabilities() { initializeWithAidlImpl(true); - long capabilities = 0X1234; + BitSet capabilities = longToBitset(0X1234); 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 +940,9 @@ public class SupplicantStaIfaceHalTest extends WifiBaseTest { @Test public void testGetWpaDriverFeatureSet() { initializeWithAidlImpl(true); - long capabilities = 0X1234; + BitSet capabilities = longToBitset(0X1234); 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..9b08be96cf 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,9 @@ */ package com.android.server.wifi; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; + import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -104,8 +107,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 +125,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_WPA3_SUITE_B)); mSupplicantNetwork = new SupplicantStaNetworkHalAidlImpl(1, mISupplicantStaNetworkMock, IFACE_NAME, mContext, mWifiMonitor, mWifiGlobals, mAdvanceKeyMgmtFeatures, mWpaDriverFeatures); @@ -1193,7 +1196,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 +1332,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 +1350,10 @@ public class SupplicantStaNetworkHalAidlImplTest extends WifiBaseTest { public void testEapMinimumTlsVersionWifiConfigurationSaveLoadWithAidlV2TlsV13Supported() throws Exception { // Re-init mock to AIDL v2 with TLS v1.3 support. + mWpaDriverFeatures = longToBitset(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..b34402e793 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.util.GeneralUtil.longToBitset; + 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 = longToBitset(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/WakeupControllerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java index 10ae4d9fbb..7ba7a60030 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.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -128,7 +129,7 @@ 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); + longToBitset(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..f5036d51c8 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.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -106,7 +107,7 @@ 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); + longToBitset(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..4c55a63f9c 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.util.GeneralUtil.longToBitset; + 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); + longToBitset(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..7e4d7e75c6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -18,6 +18,8 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; import static com.android.server.wifi.WifiConfigManager.BUFFERED_WRITE_ALARM_TAG; import static org.junit.Assert.assertEquals; @@ -115,6 +117,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 +367,7 @@ 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); + longToBitset(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 +2033,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( + longToBitset(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. @@ -5551,6 +5554,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)); } @@ -7939,7 +7979,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); + } when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn(featureSet); WifiConfiguration config = prepareTofuEapConfig( @@ -8061,7 +8104,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); @@ -8076,7 +8119,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificatePathSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( WifiEnterpriseConfig.Eap.PEAP, WifiEnterpriseConfig.Phase2.NONE), true); @@ -8094,7 +8137,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateWithoutAltSubjectNames() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8120,7 +8163,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateWithAltSubjectNames() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8160,7 +8203,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateFaiulreInvalidArgument() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE)); int openNetId = verifyAddNetwork(WifiConfigurationTestUtil.createOpenNetwork(), true); int eapPeapNetId = verifyAddNetwork(prepareTofuEapConfig( @@ -8196,7 +8239,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateCaCertificateSuccessWithSelfSignedCertificate() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(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 +8255,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { @Test public void testUpdateServerCertificateHashSuccess() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(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 +8270,7 @@ public class WifiConfigManagerTest extends WifiBaseTest { public void testUpdateCaCertificateFailureWithSelfSignedCertificateAndTofuNotEnabled() throws Exception { when(mPrimaryClientModeManager.getSupportedFeatures()).thenReturn( - WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE); + longToBitset(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..21b9159537 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,9 @@ 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 com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -53,9 +56,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 +81,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 +101,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 +1505,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(getCapabilityIndex(WifiManager.WIFI_FEATURE_DPP_AKM), false); WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork(); config.setSecurityParams(WifiInfo.SECURITY_TYPE_DPP); @@ -1507,7 +1515,7 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { assertFalse(WifiConfigurationUtil.validate(config, supportedFeatures, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)); - supportedFeatures = WifiManager.WIFI_FEATURE_DPP_AKM; + supportedFeatures.set(getCapabilityIndex(WifiManager.WIFI_FEATURE_DPP_AKM), true); assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures, WifiConfigurationUtil.VALIDATE_FOR_ADD)); assertTrue(WifiConfigurationUtil.validate(config, supportedFeatures, @@ -1606,4 +1614,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..da23a62e27 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,9 @@ package com.android.server.wifi; import static android.net.wifi.WifiManager.WIFI_FEATURE_CONTROL_ROAMING; +import static com.android.server.wifi.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; + import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -32,6 +35,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 +72,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(longToBitset(WIFI_FEATURE_CONTROL_ROAMING)); WifiNative.RoamingCapabilities roamCap = new WifiNative.RoamingCapabilities(); roamCap.maxBlocklistSize = MAX_BSSID_BLOCKLIST_SIZE; @@ -119,7 +124,9 @@ public class WifiConnectivityHelperTest extends WifiBaseTest { */ @Test public void returnFirmwareRoamingNotSupported() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_CONTROL_ROAMING); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(getCapabilityIndex(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..086beb7bac 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 setAutojoinRestrictionSecurityTypes method is working correctly. + * Also verify getAutojoinRestrictionSecurityTypes method is working correctly. + */ + @Test + public void testSetAndGetAutojoinRestrictionSecurityTypes() { + // test default value of auto-join restriction secirity types (NONE) + assertEquals(0/*restrict none by default*/, + mWifiConnectivityManager.getAutojoinRestrictionSecurityTypes()); + + // 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.setAutojoinRestrictionSecurityTypes(restrictOpenWepOwe); + assertEquals(restrictOpenWepOwe, mWifiConnectivityManager + .getAutojoinRestrictionSecurityTypes()); + + // test resetting auto-join restriction on all secirity types + mWifiConnectivityManager.setAutojoinRestrictionSecurityTypes(0/*restrict none*/); + assertEquals(0/*restrict none*/, mWifiConnectivityManager + .getAutojoinRestrictionSecurityTypes()); + } + /* * 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..6d79eed1a7 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,8 @@ 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.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; @@ -69,6 +71,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 +136,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 +533,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); } @@ -560,7 +564,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -702,7 +706,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -747,7 +751,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(longToBitset(WifiManager.WIFI_MODE_FULL_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -1009,7 +1013,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); @@ -1029,7 +1033,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(longToBitset(WifiManager.WIFI_FEATURE_TX_POWER_LIMIT)); acquireWifiLockSuccessful(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "", mBinder, mWorkSource); @@ -1049,7 +1053,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1088,7 +1092,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Fail the call to ClientModeManager when(mClientModeManager.setLowLatencyMode(true)).thenReturn(false); @@ -1118,7 +1122,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Succeed to setLowLatencyMode() when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1147,7 +1151,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1186,7 +1190,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1229,7 +1233,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); // Make sure setLowLatencyMode() is successful when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); @@ -1272,7 +1276,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); // Make sure setLowLatencyMode()/setPowerSave() is successful @@ -1324,7 +1328,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1359,7 +1363,7 @@ public class WifiLockManagerTest extends WifiBaseTest { anyBoolean())).thenReturn(true); setScreenState(false); when(mClientModeManager.getSupportedFeatures()) - .thenReturn((long) WifiManager.WIFI_FEATURE_LOW_LATENCY); + .thenReturn(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1400,7 +1404,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1446,7 +1450,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1475,7 +1479,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1508,7 +1512,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); mWifiLockManager.updateWifiClientConnected(mClientModeManager, true); InOrder inOrder = inOrder(mClientModeManager); @@ -1541,7 +1545,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1699,7 +1703,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); when(mClientModeManager.setLowLatencyMode(anyBoolean())).thenReturn(true); expectedMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; } @@ -1752,7 +1756,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mWifiMetrics); @@ -1899,7 +1903,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(longToBitset(WifiManager.WIFI_FEATURE_LOW_LATENCY)); InOrder inOrder = inOrder(mClientModeManager); @@ -1945,8 +1949,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(longToBitset(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})); @@ -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(getCapabilityIndex(WifiManager.WIFI_FEATURE_LOW_LATENCY), false); + supportedFeatures.set(getCapabilityIndex(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(longToBitset(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(longToBitset(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(longToBitset(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..8cb75c5a33 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,11 @@ 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; @Captor ArgumentCaptor<ActiveModeWarden.ModeChangeCallback> mModeChangeCallbackArgumentCaptor; @Captor ArgumentCaptor<Handler> mHandlerCaptor; @Captor @@ -227,6 +265,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, @@ -274,7 +319,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 +4509,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 +4560,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 +4601,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 +7373,470 @@ 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.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, + true, mWifiInfo, mCapabilities); + + 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_AWAKENING, + 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.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, + true, mWifiInfo, mCapabilities); + + 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_AWAKENING, + 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_AWAKENING, + 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.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, + true, mWifiInfo, mCapabilities); + + 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_AWAKENING, + 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.logWifiIsUnusableEvent(TEST_IFACE_NAME, + WifiIsUnusableEvent.TYPE_DATA_STALL_BAD_TX); + + 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, + true, mWifiInfo, mCapabilities); + + 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_AWAKENING, + 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.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, + true, mWifiInfo, mCapabilities); + + 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_AWAKENING, + 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/WifiNativeInterfaceManagementTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java index 0fcc471052..1c6b57d48d 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; @@ -85,7 +91,7 @@ public class WifiNativeInterfaceManagementTest extends WifiBaseTest { private static final String IFACE_NAME_1 = "mockWlan1"; private static final String SELF_RECOVERY_IFACE_NAME = "mockWlan2"; 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 +132,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 +187,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 +210,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 +241,18 @@ 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); + mInOrder = inOrder(mWifiVendorHal, mWificondControl, mSupplicantStaIfaceHal, mHostapdHal, mWifiMonitor, mNetdWrapper, mIfaceCallback0, mIfaceCallback1, mIfaceEventCallback0, mWifiMetrics, mWifiP2pNative); @@ -259,6 +275,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 +600,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 +628,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 +641,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 +1396,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()); } @@ -1829,8 +1848,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 +2064,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..0ccb2bf5e7 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,8 @@ 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.longToBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -43,6 +45,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 +55,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 +74,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 +95,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,7 +257,7 @@ public class WifiNativeTest extends WifiBaseTest { return result; } - public static final long WIFI_TEST_FEATURE = 0x800000000L; + private static final BitSet WIFI_TEST_FEATURE = longToBitset(0x800000000L); 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); @@ -283,6 +290,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 +310,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 +327,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 +342,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 +358,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, @@ -1586,13 +1604,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 = 0x321; + 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(longToBitset(legacyFeatures))); } /** @@ -1633,8 +1672,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 +1859,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..0c09a4df21 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.util.GeneralUtil.longToBitset; 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,7 @@ 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); + longToBitset(WifiManager.WIFI_FEATURE_WPA3_SAE | WifiManager.WIFI_FEATURE_OWE)); mWifiNetworkFactory = new WifiNetworkFactory(mLooper.getLooper(), mContext, mNetworkCapabilities, mActivityManager, mAlarmManager, mAppOpsManager, @@ -712,7 +720,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 +730,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 +773,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 +785,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 +799,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 +1694,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 +1712,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 +4064,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..a71cf87082 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,8 @@ 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.util.GeneralUtil.getCapabilityIndex; +import static com.android.server.wifi.util.GeneralUtil.longToBitset; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -72,6 +74,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 +160,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 +559,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 +593,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 +630,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 +642,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 +684,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 +696,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 +736,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 +754,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 +796,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 +822,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 +858,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 +899,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 +939,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 +977,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 +1017,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 +1060,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 +1109,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 +1143,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 +1178,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 +1248,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 +1282,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 +1308,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 +1347,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 +1378,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 +1418,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 +1444,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 +1497,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 +1512,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 +1553,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 +1566,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 +1608,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 +1619,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 +1654,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 +1671,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 +1721,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 +1937,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 +1949,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 +2065,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 +2107,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 +2145,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 +2180,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 +2195,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 +2225,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 +2257,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 +2289,7 @@ 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(longToBitset(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(getCapabilityIndex(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(longToBitset(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(longToBitset(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(longToBitset(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,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweAutoUpgradeWithOpenNetworkWhenAutoUpgradeEnabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn(longToBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -2992,7 +3037,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 +3063,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweAutoUpgradeWithOpenNetworkWhenOpenTypeIsDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn(longToBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -3036,7 +3081,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 +3098,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testOweNoAutoUpgradeWithOpenNetworkWhenAutoUpgradeDisabled() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_OWE); + when(mClientModeManager.getSupportedFeatures()).thenReturn(longToBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(false); when(mScanRequestProxy.isOpenOnlyNetworkInRange(eq(TEST_AUTO_UPGRADE_SSID))) @@ -3069,7 +3114,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 +3130,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 +3147,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 +3180,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 +3224,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 +3239,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScan() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(longToBitset(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 +3248,16 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForPskSaeConfigAndSaeScanNegative() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_WPA3_SAE); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(getCapabilityIndex(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(longToBitset(WIFI_FEATURE_OWE)); when(mWifiGlobals.isOweUpgradeEnabled()).thenReturn(true); setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]", SECURITY_NONE | SECURITY_OWE, WifiConfiguration.SECURITY_TYPE_OWE); @@ -3217,7 +3265,9 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { @Test public void verifySecurityParamsSelectionForOpenOweConfigAndOweScanNegative() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_OWE); + BitSet supportedFeatures = new BitSet(); + supportedFeatures.set(getCapabilityIndex(WIFI_FEATURE_OWE), false); + when(mClientModeManager.getSupportedFeatures()).thenReturn(supportedFeatures); setupMultiConfigAndSingleScanAndVerify("[OWE-SAE-CCMP][ESS][MFPR]", SECURITY_NONE | SECURITY_OWE, -1); } @@ -3251,7 +3301,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 +3321,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testPskWithPskOnlyForPskSaeTransitionNetworks() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(longToBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); when(mWifiGlobals.isWpa3SaeUpgradeOffloadEnabled()).thenReturn(true); @@ -3290,7 +3341,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 +3359,8 @@ public class WifiNetworkSelectorTest extends WifiBaseTest { */ @Test public void testNetworkSelectionForUserSelectedNetwork() { - when(mClientModeManager.getSupportedFeatures()).thenReturn(WIFI_FEATURE_WPA3_SAE); + when(mClientModeManager.getSupportedFeatures()) + .thenReturn(longToBitset(WIFI_FEATURE_WPA3_SAE)); when(mWifiGlobals.isWpa3SaeUpgradeEnabled()).thenReturn(true); ScanDetailsAndWifiConfigs scanDetailsAndConfigs = setupAutoUpgradeNetworks( @@ -3398,7 +3450,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..d19b969161 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.util.GeneralUtil.longToBitset; 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,7 @@ 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); + longToBitset(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 +753,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 +789,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 +4725,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 +4741,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 +4770,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 +4778,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..437102e0bf 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java @@ -103,8 +103,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,6 +244,7 @@ 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; @@ -505,7 +506,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 +529,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 +566,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); @@ -861,7 +861,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 +1191,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 +1357,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 +1639,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 +1656,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 +2082,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 +2101,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 +2459,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 +2469,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 +2479,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 +2489,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 +2500,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 +2511,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 +2522,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 +2533,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 +2545,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 +2553,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 +3470,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 +3502,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 +3537,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 +4851,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 +4865,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 +4881,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 +4894,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 +4905,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 +4918,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 +4931,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 +4943,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 +5049,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 +5110,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 +6857,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 +7314,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 +7323,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 +7347,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 +7371,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 +7394,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 +7417,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 +7439,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 +7457,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 +7475,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 +7484,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 +7502,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 +7518,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 +7559,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 +7574,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 +7588,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 +7601,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 +8432,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 +8565,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 +8574,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 +8596,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); } @@ -9002,7 +9041,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 +9056,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 +9074,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 +9086,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 +9176,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 +9209,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>()); @@ -9437,7 +9480,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()); } /** @@ -10726,7 +10769,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 +11334,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 +11362,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 +11387,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 +11416,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 +11905,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 +11936,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 +11948,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 +11963,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 +11981,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)); } } @@ -12829,4 +12878,90 @@ public class WifiServiceImplTest extends WifiBaseTest { // Only WEP disconnect verify(cmmWep).disconnect(); } + + @Test + public void testGetWifiConfigForMatchedNetworkSuggestionsSharedWithUserForMultiTypeConfigs() { + long featureFlags = 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 testSetAutojoinRestrictionSecurityTypesWithPermission() 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.setAutojoinRestrictionSecurityTypes(0/*restrict none*/, + mExtras)); + // Has permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); + // Null argument + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinRestrictionSecurityTypes(0/*restrict none*/, + null)); + // Invalid argument + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinRestrictionSecurityTypes( + 0x1 << WifiInfo.SECURITY_TYPE_OWE, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinRestrictionSecurityTypes( + 0x1 << WifiInfo.SECURITY_TYPE_SAE, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.setAutojoinRestrictionSecurityTypes( + 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.setAutojoinRestrictionSecurityTypes(restrictions, mExtras); + mLooper.dispatchAll(); + verify(mWifiConnectivityManager).setAutojoinRestrictionSecurityTypes(eq(restrictions)); + } + + @Test + public void testGetAutojoinRestrictionSecurityTypesWithPermission() 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.getAutojoinRestrictionSecurityTypes(listener, mExtras)); + // Null arguments + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.getAutojoinRestrictionSecurityTypes(null, mExtras)); + assertThrows(IllegalArgumentException.class, + () -> mWifiServiceImpl.getAutojoinRestrictionSecurityTypes(listener, null)); + // has permission to call API + when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true); + when(mWifiConnectivityManager.getAutojoinRestrictionSecurityTypes()).thenReturn(7); + mWifiServiceImpl.getAutojoinRestrictionSecurityTypes(listener, mExtras); + mLooper.dispatchAll(); + inOrder.verify(listener).onResult(7); + } } 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..0862fd7245 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.util.GeneralUtil.longToBitset; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -86,6 +87,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; @@ -553,10 +555,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 = longToBitset( + WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); + BitSet chipCaps = longToBitset(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,7 +570,7 @@ public class WifiVendorHalTest extends WifiBaseTest { when(mWifiGlobals.isWpa3SaeH2eSupported()).thenReturn(true); when(mHalDeviceManager.is24g5gDbsSupported(any())).thenReturn(true); - long expectedFeatureSet = ( + BitSet expectedFeatureSet = longToBitset( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS | WifiManager.WIFI_FEATURE_TX_POWER_LIMIT @@ -578,7 +580,8 @@ public class WifiVendorHalTest extends WifiBaseTest { | 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 +606,13 @@ public class WifiVendorHalTest extends WifiBaseTest { when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_WIFI_AWARE))) .thenReturn(true); - long expectedFeatureSet = ( + BitSet expectedFeatureSet = longToBitset( WifiManager.WIFI_FEATURE_INFRA | WifiManager.WIFI_FEATURE_P2P | WifiManager.WIFI_FEATURE_AWARE ); - assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME)); + assertTrue(expectedFeatureSet.equals( + mWifiVendorHal.getSupportedFeatureSet(TEST_IFACE_NAME))); } /** 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..ee53e22771 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 @@ -761,7 +761,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 +827,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -3826,95 +3827,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 +4094,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 +4592,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 +4727,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 +4856,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 +4988,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 +5113,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 +5798,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 +5837,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -5948,7 +5867,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 +5918,8 @@ public class WifiAwareStateManagerTest extends WifiBaseTest { validateInternalClientInfoCleanedUp(clientId1); validateInternalClientInfoCleanedUp(clientId2); - + mMockLooper.dispatchAll(); + inOrder.verify(mMockNativeManager).releaseAware(); verifyNoMoreInteractions(mockCallback1, mockCallback2, mMockNative); } @@ -6060,7 +5980,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..2850a1abec 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.util.GeneralUtil.longToBitset; 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,12 @@ public class WifiChipAidlImplTest extends WifiBaseTest { | android.hardware.wifi.IWifiChip.FeatureSetMask.D2D_RTT | android.hardware.wifi.IWifiChip.FeatureSetMask.D2AP_RTT ); - long expected = ( + BitSet expected = longToBitset( WifiManager.WIFI_FEATURE_TX_POWER_LIMIT | WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT ); - assertEquals(expected, mDut.halToFrameworkChipFeatureSet(halFeatures)); + 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..53dd5b47a5 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.util.GeneralUtil.longToBitset; + 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,12 @@ 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 = ( + BitSet expected = longToBitset( WifiManager.WIFI_FEATURE_TX_POWER_LIMIT | WifiManager.WIFI_FEATURE_D2D_RTT | WifiManager.WIFI_FEATURE_D2AP_RTT ); - assertEquals(expected, mDut.wifiFeatureMaskFromChipCapabilities(caps)); + assertTrue(expected.equals(mDut.wifiFeatureMaskFromChipCapabilities(caps))); } /** @@ -170,11 +173,11 @@ 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 = ( + BitSet expected = longToBitset( WifiManager.WIFI_FEATURE_LOW_LATENCY | WifiManager.WIFI_FEATURE_D2D_RTT ); - assertEquals(expected, mDut.wifiFeatureMaskFromChipCapabilities_1_3(caps)); + 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..4a0a4e3e9f 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.util.GeneralUtil.longToBitset; + 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,10 @@ public class WifiStaIfaceAidlImplTest extends WifiBaseTest { IWifiStaIface.FeatureSetMask.BACKGROUND_SCAN | IWifiStaIface.FeatureSetMask.LINK_LAYER_STATS ); - long expected = ( + BitSet expected = longToBitset( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mDut.halToFrameworkStaFeatureSet(halFeatures)); + 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..8adb4fd171 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.util.GeneralUtil.longToBitset; + 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,10 @@ public class WifiStaIfaceHidlImplTest extends WifiBaseTest { IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS ); - long expected = ( + BitSet expected = longToBitset( WifiManager.WIFI_FEATURE_SCANNER | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS); - assertEquals(expected, mDut.halToFrameworkStaIfaceCapability(caps)); + 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..2ec2e59152 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) { @@ -1579,6 +1589,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 +2967,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 +3580,7 @@ public class WifiP2pServiceImplTest extends WifiBaseTest { WifiP2pGroup groupCaptured = groupCaptor.getValue(); assertEquals(mTestWifiP2pNewPersistentGoGroup.toString(), groupCaptured.toString()); - sendGroupRemovedMsg(); + sendGroupRemovedMsg(groupCaptured); verify(mWifiP2pMetrics).endGroupEvent(); } @@ -7197,6 +7609,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 +8224,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 +8564,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 +8578,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/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..749d05ef8d 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 @@ -42,8 +42,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.Context; -import android.content.res.Resources; import android.net.MacAddress; import android.net.wifi.CoexUnsafeChannel; import android.net.wifi.ScanResult; @@ -51,9 +49,11 @@ 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; @@ -166,8 +166,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; @@ -189,7 +189,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); 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); |