diff options
148 files changed, 8129 insertions, 2081 deletions
diff --git a/flags/wifi_flags.aconfig b/flags/wifi_flags.aconfig index 2da04a5284..7b4decfefe 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,69 @@ 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: "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/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..0d3ae0a753 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(); } diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl index 0a6e210249..dc8a44407f 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); 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..4ab897e730 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) 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/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..54c16f36ba 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; @@ -138,6 +139,7 @@ import androidx.test.filters.SmallTest; import com.android.modules.utils.HandlerExecutor; import com.android.modules.utils.build.SdkLevel; +import com.android.wifi.x.com.android.modules.utils.ParceledListSlice; import org.junit.Before; import org.junit.Test; @@ -778,12 +780,12 @@ public class WifiManagerTest { List<WifiSsid> expectedSsids = new ArrayList<>(); expectedSsids.add(WifiSsid.fromString("\"TEST_SSID\"")); mWifiManager.setSsidsAllowlist(new ArraySet<>(expectedSsids)); - verify(mWifiService).setSsidsAllowlist(any(), eq(expectedSsids)); + verify(mWifiService).setSsidsAllowlist(any(), + argThat(a -> a.getList().equals(expectedSsids))); // test empty set - mWifiManager.setSsidsAllowlist(Collections.EMPTY_SET); - verify(mWifiService).setSsidsAllowlist(any(), - eq(Collections.EMPTY_LIST)); + mWifiManager.setSsidsAllowlist(Collections.emptySet()); + verify(mWifiService).setSsidsAllowlist(any(), argThat(a -> a.getList().isEmpty())); } /** @@ -2367,16 +2369,20 @@ public class WifiManagerTest { */ @Test public void testGetAllMatchingWifiConfigs() throws Exception { - Map<String, List<ScanResult>> passpointProfiles = new HashMap<>(); - passpointProfiles.put("www.test.com_987a69bca26", new ArrayList<>()); + Map<String, Map<Integer, List<ScanResult>>> passpointProfiles = new HashMap<>(); + Map<Integer, List<ScanResult>> matchingResults = new HashMap<>(); + matchingResults.put(PASSPOINT_HOME_NETWORK, new ArrayList<>()); + passpointProfiles.put("www.test.com_987a69bca26", matchingResults); when(mWifiService.getAllMatchingPasspointProfilesForScanResults( - any(List.class))).thenReturn(passpointProfiles); + any())).thenReturn(passpointProfiles); + when(mWifiService.getWifiConfigsForPasspointProfiles(any())) + .thenReturn(new ParceledListSlice<>(Collections.emptyList())); InOrder inOrder = inOrder(mWifiService); mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>()); - inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any(List.class)); - inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any(List.class)); + inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any()); + inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any()); } /** @@ -2387,7 +2393,7 @@ public class WifiManagerTest { public void testGetMatchingOsuProviders() throws Exception { mWifiManager.getMatchingOsuProviders(new ArrayList<>()); - verify(mWifiService).getMatchingOsuProviders(any(List.class)); + verify(mWifiService).getMatchingOsuProviders(any()); } /** @@ -2398,16 +2404,16 @@ public class WifiManagerTest { @Test public void addGetRemoveNetworkSuggestions() throws Exception { List<WifiNetworkSuggestion> testList = new ArrayList<>(); - when(mWifiService.addNetworkSuggestions(any(List.class), anyString(), + when(mWifiService.addNetworkSuggestions(any(), anyString(), nullable(String.class))).thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); - when(mWifiService.removeNetworkSuggestions(any(List.class), anyString(), anyInt())) + when(mWifiService.removeNetworkSuggestions(any(), anyString(), anyInt())) .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); when(mWifiService.getNetworkSuggestions(anyString())) - .thenReturn(testList); + .thenReturn(new ParceledListSlice<>(testList)); assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager.addNetworkSuggestions(testList)); - verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME), + verify(mWifiService).addNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), nullable(String.class)); assertEquals(testList, mWifiManager.getNetworkSuggestions()); @@ -2415,17 +2421,17 @@ public class WifiManagerTest { assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager.removeNetworkSuggestions(new ArrayList<>())); - verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME), + verify(mWifiService).removeNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_DISCONNECT)); } @Test public void testRemoveNetworkSuggestionWithAction() throws Exception { - when(mWifiService.removeNetworkSuggestions(anyList(), anyString(), anyInt())) + when(mWifiService.removeNetworkSuggestions(any(), anyString(), anyInt())) .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS); assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager .removeNetworkSuggestions(new ArrayList<>(), ACTION_REMOVE_SUGGESTION_LINGER)); - verify(mWifiService).removeNetworkSuggestions(any(List.class), + verify(mWifiService).removeNetworkSuggestions(any(), eq(TEST_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_LINGER)); } @@ -3314,8 +3320,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 +3408,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()); } /** 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/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 4bdb63efbf..c111ede747 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -96,7 +96,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..aaaa4ab5d6 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,27 @@ --> <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"> + <item>2032</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. + Only enable this flag if Supplicant and driver/firmware supports RSN Overriding. otherwise + the connection may fail or downgrade to WPA2 --> + <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..6b6b5c00f5 100644 --- a/service/java/com/android/server/wifi/ActiveModeWarden.java +++ b/service/java/com/android/server/wifi/ActiveModeWarden.java @@ -51,10 +51,12 @@ import android.net.wifi.SoftApCapability; import android.net.wifi.SoftApConfiguration; import android.net.wifi.SoftApState; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiContext; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.WifiManager.DeviceMobilityState; import android.net.wifi.WifiScanner; +import android.net.wifi.util.WifiResourceCache; import android.os.BatteryStatsManager; import android.os.Build; import android.os.Handler; @@ -127,7 +129,7 @@ public class ActiveModeWarden { private final WifiInjector mWifiInjector; private final Looper mLooper; private final Handler mHandler; - private final Context mContext; + private final WifiContext mContext; private final WifiDiagnostics mWifiDiagnostics; private final WifiSettingsStore mSettingsStore; private final FrameworkFacade mFacade; @@ -191,6 +193,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 +383,7 @@ public class ActiveModeWarden { DefaultClientModeManager defaultClientModeManager, BatteryStatsManager batteryStatsManager, WifiDiagnostics wifiDiagnostics, - Context context, + WifiContext context, WifiSettingsStore settingsStore, FrameworkFacade facade, WifiPermissionsUtil wifiPermissionsUtil, @@ -392,6 +395,7 @@ public class ActiveModeWarden { mLooper = looper; mHandler = new Handler(looper); mContext = context; + mResourceCache = mContext.getResourceCache(); mWifiDiagnostics = wifiDiagnostics; mSettingsStore = settingsStore; mFacade = facade; @@ -601,7 +605,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 +618,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 +644,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForLocalOnlyConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled); } @@ -650,7 +654,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMbb() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled); } @@ -660,7 +664,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForRestrictedConnections() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled); } @@ -670,7 +674,7 @@ public class ActiveModeWarden { */ public boolean isStaStaConcurrencySupportedForMultiInternet() { return mWifiNative.isStaStaConcurrencySupported() - && mContext.getResources().getBoolean( + && mResourceCache.getBoolean( R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled); } @@ -706,7 +710,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 +1494,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 +1747,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 +1850,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 +1972,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; @@ -2741,19 +2746,19 @@ public class ActiveModeWarden { 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 +2772,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/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 913ac9bf7b..8e97cae460 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -26,6 +26,7 @@ import static android.net.wifi.WifiManager.WIFI_FEATURE_FILS_SHA384; import static android.net.wifi.WifiManager.WIFI_FEATURE_LINK_LAYER_STATS; import static android.net.wifi.WifiManager.WIFI_FEATURE_TDLS; import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE; +import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; @@ -34,6 +35,12 @@ import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LO import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.WifiSettingsConfigStore.SECONDARY_WIFI_STA_FACTORY_MAC_ADDRESS; import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_STA_FACTORY_MAC_ADDRESS; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_LOCAL_ONLY; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_OTHERS; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_PRIMARY; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_INTERNET; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_LONG_LIVED; +import static com.android.server.wifi.proto.WifiStatsLog.WIFI_CONNECTION_RESULT_REPORTED__ROLE__ROLE_CLIENT_SECONDARY_TRANSIENT; import static com.android.server.wifi.proto.WifiStatsLog.WIFI_DISCONNECT_REPORTED__FAILURE_CODE__SUPPLICANT_DISCONNECTED; import android.annotation.IntDef; @@ -697,7 +704,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, @@ -1644,6 +1650,13 @@ public class ClientModeImpl extends StateMachine implements ClientMode { } /** + * @return true if this device supports WPA3_SAE + */ + private boolean isWpa3SaeSupported() { + return (getSupportedFeatures() & WIFI_FEATURE_WPA3_SAE) != 0; + } + + /** * Update interface capabilities * This method is used to update some of interface capabilities defined in overlay */ @@ -1668,6 +1681,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); } @@ -2430,6 +2447,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 +2915,9 @@ public class ClientModeImpl extends StateMachine implements ClientMode { mWifiInfo.setSuccessfulRxPacketsPerSecond(0); mWifiScoreReport.reset(); mLastLinkLayerStats = null; + if (isPrimary()) { + mWifiMetrics.resetWifiUnusableEvent(); + } updateCurrentConnectionInfo(); } @@ -3250,6 +3276,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 +3767,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 +4160,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 +4870,7 @@ public class ClientModeImpl extends StateMachine implements ClientMode { if (!isTrustOnFirstUseSupported()) { mInsecureEapNetworkHandler.startUserApprovalIfNecessary(mIsUserSelected); } + mFrameworkDisconnectReasonOverride = 0; connectToNetwork(config); break; } @@ -5377,7 +5408,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 +6805,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 +6821,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 +6934,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 +7045,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; } diff --git a/service/java/com/android/server/wifi/ConcreteClientModeManager.java b/service/java/com/android/server/wifi/ConcreteClientModeManager.java index 3864262b56..33c5f3142f 100644 --- a/service/java/com/android/server/wifi/ConcreteClientModeManager.java +++ b/service/java/com/android/server/wifi/ConcreteClientModeManager.java @@ -465,6 +465,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); } 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..96e703dfcb 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 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/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..7129609f9b 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,37 +1927,28 @@ 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); } diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHalAidlImpl.java index 1bcf4b742d..b378188fd6 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,13 +2749,13 @@ 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; } @@ -4038,6 +4072,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..87d0a5b7dc 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -124,6 +124,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 +481,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; } } diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java index 4421fcd08e..501a071b34 100644 --- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java +++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java @@ -16,7 +16,11 @@ package com.android.server.wifi; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_NUM; import static android.net.wifi.WifiManager.ALL_ZEROS_MAC_ADDRESS; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_NUMBER_OF_OI; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_OI_VALUE; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES; import static com.android.server.wifi.util.NativeUtil.addEnclosingQuotes; @@ -31,6 +35,7 @@ import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSpecifier; import android.net.wifi.WifiScanner; import android.net.wifi.WifiSsid; +import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.PatternMatcher; import android.text.TextUtils; import android.util.Log; @@ -46,8 +51,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; /** * WifiConfiguration utility for any {@link android.net.wifi.WifiConfiguration} related operations. @@ -70,6 +77,7 @@ public class WifiConfigurationUtil { private static final int PSK_SAE_HEX_LEN = 64; private static final int WEP104_KEY_BYTES_LEN = 13; private static final int WEP40_KEY_BYTES_LEN = 5; + private static final int MAX_STRING_LENGTH = 512; @VisibleForTesting public static final String PASSWORD_MASK = "*"; @@ -750,7 +758,8 @@ public class WifiConfigurationUtil { 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 +768,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) @@ -793,10 +815,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; diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java index 59d8934edf..b7e12e0686 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; @@ -67,12 +69,14 @@ import com.android.server.wifi.hotspot2.PasspointManager; import com.android.server.wifi.proto.WifiStatsLog; import com.android.server.wifi.scanner.WifiScannerInternal; import com.android.server.wifi.util.WifiPermissionsUtil; +import com.android.wifi.flags.FeatureFlags; import com.android.wifi.resources.R; 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; @@ -180,6 +184,7 @@ public class WifiConnectivityManager { private final WifiChannelUtilization mWifiChannelUtilization; private final PowerManager mPowerManager; private final DeviceConfigFacade mDeviceConfigFacade; + private final FeatureFlags mFeatureFlags; private final ActiveModeWarden mActiveModeWarden; private final FrameworkFacade mFrameworkFacade; private final WifiPermissionsUtil mWifiPermissionsUtil; @@ -218,9 +223,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 +272,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 +325,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 +333,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 +660,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); @@ -649,6 +685,12 @@ public class WifiConnectivityManager { scanDetails, bssidBlocklist, cmmStates, mUntrustedConnectionAllowed, mOemPaidConnectionAllowed, mOemPrivateConnectionAllowed, mRestrictedConnectionAllowedUids, skipSufficiencyCheck); + + // Filter candidates before caching to avoid reconnecting on failure + if (mFeatureFlags.delayedCarrierNetworkSelection()) { + candidates = filterDelayedCarrierSelectionCandidates(candidates, listenerName, + isFullScan); + } mLatestCandidates = candidates; mLatestCandidatesTimestampMs = mClock.getElapsedSinceBootMillis(); @@ -875,12 +917,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<>(); @@ -1375,6 +1507,7 @@ public class WifiConnectivityManager { mPasspointManager = passpointManager; mMultiInternetManager = multiInternetManager; mDeviceConfigFacade = deviceConfigFacade; + mFeatureFlags = mDeviceConfigFacade.getFeatureFlags(); mActiveModeWarden = activeModeWarden; mFrameworkFacade = frameworkFacade; mWifiGlobals = wifiGlobals; @@ -1388,6 +1521,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 +1960,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 +2318,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 +2685,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 +2858,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 +2977,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 +3309,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 +3548,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(); + } + } + } } /** 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..97131f0c96 100644 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ b/service/java/com/android/server/wifi/WifiDataStall.java @@ -306,6 +306,43 @@ 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; + } + /** * 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..ddb7a0f48a 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -269,6 +269,7 @@ public class WifiInjector { private final WifiRoamingModeManager mWifiRoamingModeManager; private final TwtManager mTwtManager; private final WifiVoipDetector mWifiVoipDetector; + private final boolean mHasActiveModem; public WifiInjector(WifiContext context) { if (context == null) { @@ -623,12 +624,13 @@ public class WifiInjector { mTwtManager = new TwtManager(this, mCmiMonitor, mWifiNative, wifiHandler, mClock, WifiTwtSession.MAX_TWT_SESSIONS, 1); mBackupRestoreController = new BackupRestoreController(mWifiSettingsBackupRestore, mClock); - if (mFeatureFlags.voipDetection() && SdkLevel.isAtLeastV()) { + if (mFeatureFlags.voipDetectionBugfix() && SdkLevel.isAtLeastV()) { mWifiVoipDetector = new WifiVoipDetector(mContext, wifiHandler, this, mWifiCarrierInfoManager); } else { mWifiVoipDetector = null; } + mHasActiveModem = makeTelephonyManager().getActiveModemCount() > 0; } /** @@ -1295,4 +1297,11 @@ public class WifiInjector { public WifiVoipDetector getWifiVoipDetector() { return mWifiVoipDetector; } + + /** + * Return true if there is any active modem on the device. + */ + public boolean hasActiveModem() { + return mHasActiveModem; + } } diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 93cb2ab8d8..45c636e115 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; @@ -138,6 +164,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; @@ -243,6 +270,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,7 +297,8 @@ public class WifiMetrics { private WifiHealthMonitor mWifiHealthMonitor; private WifiScoreCard mWifiScoreCard; private SessionData mPreviousSession; - private SessionData mCurrentSession; + @VisibleForTesting + public SessionData mCurrentSession; private String mLastBssid; private int mLastFrequency = -1; private int mSeqNumInsideFramework = 0; @@ -301,6 +332,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. @@ -488,7 +521,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 +645,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 +699,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 +1225,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 +1692,7 @@ public class WifiMetrics { new WifiDeviceStateChangeManager.StateChangeCallback() { @Override public void onScreenStateChanged(boolean screenOn) { - setScreenState(screenOn); + handleScreenStateChanged(screenOn); } }); } @@ -6049,11 +6091,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 +6983,7 @@ public class WifiMetrics { WifiIsUnusableEvent event = new WifiIsUnusableEvent(); event.type = triggerType; + mUnusableEventType = triggerType; if (triggerType == WifiIsUnusableEvent.TYPE_FIRMWARE_ALERT) { event.firmwareAlertCode = firmwareAlertCode; } @@ -6995,6 +7043,10 @@ 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. @@ -8770,6 +8822,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 +9737,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 +9747,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..aa1d3398e9 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.bitsetToLong; +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; @@ -1557,6 +1562,8 @@ public class WifiNative { iface.featureSet = getSupportedFeatureSetInternal(iface.name); updateSupportedBandForStaInternal(iface); + mIsRsnOverridingSupported = mContext.getResources().getBoolean( + R.bool.config_wifiRsnOverridingEnabled) && rsnOverriding(); mWifiVendorHal.enableStaChannelForPeerNetwork(mContext.getResources().getBoolean( R.bool.config_wifiEnableStaIndoorChannelForPeerNetwork), @@ -2090,6 +2097,7 @@ public class WifiNative { ies, result.getCapabilities(), mIsEnhancedOpenSupported, + mIsRsnOverridingSupported, result.getFrequencyMhz(), mUnknownAkmMap); String flags = capabilities.generateCapabilitiesString(); @@ -3618,6 +3626,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); } /** @@ -3936,7 +3949,7 @@ public class WifiNative { long featureSet = 0; // First get the complete feature set stored in config store when supplicant was // started - featureSet = getCompleteFeatureSetFromConfigStore(); + featureSet = bitsetToLong(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. @@ -3973,9 +3986,10 @@ public class WifiNative { * @return bitmask defined by WifiManager.WIFI_FEATURE_* */ private long getSupportedFeatureSetInternal(@NonNull String ifaceName) { - long featureSet = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName) - | mWifiVendorHal.getSupportedFeatureSet(ifaceName) - | mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName); + BitSet featureBitset = mSupplicantStaIfaceHal.getAdvancedCapabilities(ifaceName); + featureBitset.or(mSupplicantStaIfaceHal.getWpaDriverFeatureSet(ifaceName)); + featureBitset.or(mWifiVendorHal.getSupportedFeatureSet(ifaceName)); + long featureSet = bitsetToLong(featureBitset); if (SdkLevel.isAtLeastT()) { if (((featureSet & WifiManager.WIFI_FEATURE_DPP) != 0) && mContext.getResources().getBoolean(R.bool.config_wifiDppAkmSupported)) { @@ -5159,12 +5173,13 @@ 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(long featureSetLong) { + BitSet featureSet = longToBitset(featureSetLong); + 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 +5187,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..7686e226f7 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSelector.java +++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java @@ -1129,7 +1129,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..9fa6113b1f 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -380,7 +380,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); @@ -1946,13 +1946,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 +1989,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 +2741,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/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 107a6449bd..c3c4a0fc34 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 @@ -145,6 +151,9 @@ public class WifiScoreReport { + " score=" + score); return; } + if (mIsExternalScorerDryRun) { + return; + } long millis = mClock.getWallClockMillis(); if (SdkLevel.isAtLeastS()) { mLegacyIntScore = score; @@ -198,6 +207,9 @@ public class WifiScoreReport { + " interfaceName=" + mInterfaceName); return; } + if (mIsExternalScorerDryRun) { + return; + } WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName); // update mWifiInfo @@ -257,6 +269,11 @@ public class WifiScoreReport { + " isUsable=" + isUsable); return; } + mExternalScorerPredictionStatusForEvaluation = + convertToPredictionStatusForEvaluation(isUsable); + if (mIsExternalScorerDryRun) { + return; + } if (mNetworkAgent == null) { return; } @@ -310,6 +327,9 @@ public class WifiScoreReport { + " currentSessionId=" + getCurrentSessionId()); return; } + if (mIsExternalScorerDryRun) { + return; + } if (!mAdaptiveConnectivityEnabledSettingObserver.get() || !mWifiSettingsStore.isWifiScoringEnabled()) { if (mVerboseLoggingEnabled) { @@ -330,6 +350,9 @@ public class WifiScoreReport { + " mSessionIdNoReset=" + mSessionIdNoReset); return; } + if (mIsExternalScorerDryRun) { + return; + } if (!mAdaptiveConnectivityEnabledSettingObserver.get() || !mWifiSettingsStore.isWifiScoringEnabled()) { if (mVerboseLoggingEnabled) { @@ -379,6 +402,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 +571,7 @@ public class WifiScoreReport { @Nullable private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder; + private boolean mIsExternalScorerDryRun; private final AdaptiveConnectivityEnabledSettingObserver mAdaptiveConnectivityEnabledSettingObserver; @@ -600,6 +625,7 @@ public class WifiScoreReport { */ public void reset() { mSessionNumber++; + clearScorerPredictionStatusForEvaluation(); mLegacyIntScore = isPrimary() ? ConnectedScore.WIFI_INITIAL_SCORE : ConnectedScore.WIFI_SECONDARY_INITIAL_SCORE; mIsUsable = true; @@ -634,11 +660,6 @@ public class WifiScoreReport { * Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds. */ 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 +717,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 +1016,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 +1037,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 +1064,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 +1075,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 +1115,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 +1194,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 +1224,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 +1247,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 +1291,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 3a45356a34..4347040fca 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); @@ -5608,7 +5687,7 @@ public class WifiServiceImpl extends BaseWifiService { mWifiInjector.getWifiVoipDetector().dump(fd, pw, args); } pw.println(); - mWifiResourceCache.dump(pw); + mResourceCache.dump(pw); } }, TAG + "#dump"); } @@ -5743,7 +5822,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 @@ -6231,7 +6310,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; @@ -6264,12 +6343,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; @@ -6285,7 +6367,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; @@ -6299,11 +6381,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; @@ -6315,16 +6400,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")); } /** @@ -7559,7 +7645,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); @@ -7765,11 +7852,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())) { @@ -7786,13 +7873,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; @@ -7843,14 +7930,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"); } @@ -7873,7 +7962,7 @@ public class WifiServiceImpl extends BaseWifiService { */ @Override public String[] getOemPrivilegedWifiAdminPackages() { - return mContext.getResources() + return mResourceCache .getStringArray(R.array.config_oemPrivilegedWifiAdminPackages); } @@ -7955,7 +8044,7 @@ public class WifiServiceImpl extends BaseWifiService { } @Override public int getMaxNumberOfChannelsPerRequest() { - return mContext.getResources() + return mResourceCache .getInteger(R.integer.config_wifiNetworkSpecifierMaxPreferredChannels); } @@ -8003,7 +8092,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()) { @@ -8018,33 +8107,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"); } @@ -8542,7 +8637,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"); @@ -8577,9 +8672,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"); @@ -8609,9 +8701,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"); 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 c0ce760b6a..59061d2439 100644 --- a/service/java/com/android/server/wifi/aware/PairingConfigManager.java +++ b/service/java/com/android/server/wifi/aware/PairingConfigManager.java @@ -42,8 +42,12 @@ public class PairingConfigManager { private static final String TAG = "AwarePairingManager"; - private static final int NIK_SIZE_IN_BYTE = 16; - private static final int TAG_SIZE_IN_BYTE = 8; + // NIK size + public static final int NIK_SIZE_IN_BYTE = 16; + // TAG size + public static final int TAG_SIZE_IN_BYTE = 8; + // NIR byte array + public static final byte[] NIR = {'N', 'I', 'R'}; /** * Store the NPKSA from the NAN Pairing confirmation @@ -76,7 +80,6 @@ public class PairingConfigManager { private byte[] createRandomNik() { long first, second; - Random mRandom = new SecureRandom(); first = mRandom.nextLong(); second = mRandom.nextLong(); @@ -119,14 +122,13 @@ public class PairingConfigManager { private boolean checkMatchAlias(String alias, byte[] nonce, byte[] tag, byte[] mac) { byte[] nik = mAliasToNikMap.get(alias); - byte[] nir = {'N', 'I', 'R'}; if (nik == null) return false; SecretKeySpec spec = new SecretKeySpec(nik, "HmacSHA256"); try { Mac hash = Mac.getInstance("HmacSHA256"); hash.init(spec); - hash.update(nir); + hash.update(NIR); hash.update(mac); hash.update(nonce); byte[] message = Arrays.copyOf(hash.doFinal(), TAG_SIZE_IN_BYTE); @@ -155,11 +157,8 @@ public class PairingConfigManager { if (info == null) { return; } - Set<String> pairedDevices = mPerAppPairedAliasMap.get(packageName); - if (pairedDevices == null) { - pairedDevices = new HashSet<>(); - mPerAppPairedAliasMap.put(packageName, pairedDevices); - } + Set<String> pairedDevices = mPerAppPairedAliasMap.computeIfAbsent(packageName, + k -> new HashSet<>()); pairedDevices.add(alias); mAliasToNikMap.put(alias, info.mPeerNik); mAliasToSecurityInfoMap.put(alias, info); diff --git a/service/java/com/android/server/wifi/aware/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/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..ee64cfef71 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; } 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..120de838d6 100644 --- a/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java +++ b/service/java/com/android/server/wifi/scanner/WifiScanningServiceImpl.java @@ -528,12 +528,7 @@ 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); @@ -653,7 +648,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; @@ -1029,6 +1025,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 +1092,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 +1237,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 +1339,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 +1615,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 +1640,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) { @@ -1772,7 +1822,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 +1844,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 +1918,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 +1995,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 +2177,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 +2201,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."); @@ -3277,33 +3376,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/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..18d1fbe2f3 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ActiveModeWardenTest.java @@ -63,10 +63,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 +78,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; @@ -158,8 +158,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; @@ -226,16 +226,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); @@ -678,7 +678,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 +787,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 +1498,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 +1532,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 +1647,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 +3027,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 +3121,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 +3361,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 +3383,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 +3396,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 +3426,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 +3438,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 +3450,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 +3463,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 +3488,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 +3506,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 +3521,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 +3559,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 +3583,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 +3595,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 +3607,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 +3620,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 +3634,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 +3647,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 +3672,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 +3685,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 +3698,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 +3712,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 +3727,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 +3742,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 +3827,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 +3908,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 +3972,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 +4032,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 +4080,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 +4357,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 +4435,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 +4739,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 +4804,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( @@ -4896,14 +4896,14 @@ public class ActiveModeWardenTest extends WifiBaseTest { 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 +4912,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,13 +4928,13 @@ 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())) 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..2d114d20c4 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -1574,6 +1574,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 +1801,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 +2649,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. @@ -7800,12 +7853,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. @@ -10099,6 +10154,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 +10183,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)); } /** @@ -11142,4 +11201,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( + 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/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/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/SoftApManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java index aeb84c21e5..5ba7e3ae7b 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/SoftApManagerTest.java @@ -61,7 +61,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 +78,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; @@ -195,7 +195,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; @@ -340,24 +340,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 +393,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()) @@ -537,7 +538,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 +615,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 +653,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 +695,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 +734,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 +768,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 +1013,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 +1080,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 +1158,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 +1226,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 +1280,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 +1315,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 +1362,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 +1973,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 +2537,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 +2578,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 +2723,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 +2751,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 +2787,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 +3181,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 +3217,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 +3328,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 +3362,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 +3539,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 +3779,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 +3802,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 +3813,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 +3835,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 +3852,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 +3866,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 +3880,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 +3896,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 +3914,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 +3983,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 +3992,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 +4063,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 +4087,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 +4111,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 +4137,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 +4166,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 +4193,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 +4209,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..57e0c128f5 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,8 @@ 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))); } /** @@ -2263,30 +2298,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 +2385,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 +2420,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 +2854,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 +3465,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/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/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..6e88ddb744 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -5551,6 +5551,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)); } 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..81b182c9df 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java @@ -18,6 +18,7 @@ package com.android.server.wifi; import static android.net.wifi.WifiEnterpriseConfig.OCSP_NONE; import static android.net.wifi.WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS; +import static android.net.wifi.hotspot2.PasspointConfiguration.MAX_URL_BYTES; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -53,6 +54,7 @@ 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; @@ -77,6 +79,7 @@ public class WifiConfigurationUtilTest extends WifiBaseTest { 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 final String mGeneratedString256 = "a".repeat(256); private MockitoSession mSession; @@ -1606,4 +1609,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/WifiConnectivityManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java index e5ddabb0e1..d0f3ad65f6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java @@ -107,6 +107,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto; import com.android.server.wifi.scanner.WifiScannerInternal; import com.android.server.wifi.util.LruConnectionTracker; import com.android.server.wifi.util.WifiPermissionsUtil; +import com.android.wifi.flags.FeatureFlags; import com.android.wifi.resources.R; import org.junit.After; @@ -179,6 +180,10 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { when(mPrimaryClientModeManager.getRole()).thenReturn(ActiveModeManager.ROLE_CLIENT_PRIMARY); when(mPrimaryClientModeManager.getConnectionInfo()).thenReturn(mWifiInfo); when(mActiveModeWarden.getPrimaryClientModeManager()).thenReturn(mPrimaryClientModeManager); + when(mDeviceConfigFacade.getFeatureFlags()).thenReturn(mFeatureFlags); + when(mFeatureFlags.delayedCarrierNetworkSelection()).thenReturn(true); + when(mWifiCarrierInfoManager.isCarrierNetworkOffloadEnabled(anyInt(), anyBoolean())) + .thenReturn(true); doAnswer(new AnswerWithArguments() { public void answer(ExternalClientModeManagerRequestListener listener, WorkSource requestorWs, String ssid, String bssid) { @@ -267,6 +272,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); } /** @@ -313,6 +322,7 @@ public class WifiConnectivityManagerTest extends WifiBaseTest { @Mock private WifiNetworkSuggestion mWifiNetworkSuggestion; @Mock private IPowerManager mPowerManagerService; @Mock private DeviceConfigFacade mDeviceConfigFacade; + @Mock private FeatureFlags mFeatureFlags; @Mock private ActiveModeWarden mActiveModeWarden; @Mock private ConcreteClientModeManager mPrimaryClientModeManager; @Mock private ConcreteClientModeManager mSecondaryClientModeManager; @@ -350,6 +360,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 +419,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 +490,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 +503,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()); @@ -752,6 +762,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); @@ -2272,6 +2283,130 @@ 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())).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())).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. @@ -2330,6 +2465,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())).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. @@ -2857,6 +3027,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. */ @@ -5737,11 +5927,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 +5942,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 +5953,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 +5969,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 +5978,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 +5986,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()); } 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/WifiMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java index 3c4f6c4db1..8035444dbc 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 @@ -7316,4 +7369,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..e2806fe6de 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNativeInterfaceManagementTest.java @@ -72,6 +72,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import java.util.Set; @@ -85,7 +86,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; @@ -180,6 +181,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 +204,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,7 +235,7 @@ 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))) @@ -581,8 +585,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 +613,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 +626,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 +1381,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 +1833,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 +2049,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..a970e187a1 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; @@ -73,6 +77,7 @@ import com.android.server.wifi.hal.WifiChip; 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 +94,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 +256,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); @@ -302,6 +308,7 @@ 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(mBuildProperties.isEngBuild()).thenReturn(false); when(mBuildProperties.isUserdebugBuild()).thenReturn(false); @@ -316,6 +323,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); @@ -332,8 +341,8 @@ public class WifiNativeTest extends WifiBaseTest { 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 +353,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(false); + mWifiNative = new WifiNative( mWifiVendorHal, mStaIfaceHal, mHostapdHal, mWificondControl, mWifiMonitor, mPropertyService, mWifiMetrics, @@ -1586,13 +1599,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 testGetSupportedFeatureSetWhenInterfaceDoesntExist() throws Exception { - long featureSet = mWifiNative.getSupportedFeatureSet(null); - assertEquals(featureSet, WIFI_TEST_FEATURE); + 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 = longToBitset(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 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 = longToBitset(mWifiNative.getSupportedFeatureSet(null)); + assertTrue(featureSet.equals(longToBitset(legacyFeatures))); } /** @@ -1820,4 +1854,18 @@ public class WifiNativeTest extends WifiBaseTest { WifiManager.ROAMING_MODE_NORMAL)); verify(mWifiVendorHal).setRoamingMode(WIFI_IFACE_NAME, WifiManager.ROAMING_MODE_NORMAL); } + + @Test + public void testRsnOverridingFeatureFlag() throws Exception { + mResources.setBoolean(R.bool.config_wifiRsnOverridingEnabled, true); + when(Flags.rsnOverriding()).thenReturn(false); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + assertFalse(mWifiNative.mIsRsnOverridingSupported); + mWifiNative.teardownAllInterfaces(); + when(Flags.rsnOverriding()).thenReturn(true); + mWifiNative.setupInterfaceForClientInScanMode(null, TEST_WORKSOURCE, + mConcreteClientModeManager); + assertTrue(mWifiNative.mIsRsnOverridingSupported); + } } 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..14048100e0 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -18,6 +18,7 @@ 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; @@ -105,6 +106,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 +156,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 +190,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 +269,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))) @@ -712,7 +719,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 +729,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 +772,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 +784,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 +798,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 +1693,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 +1711,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 +4063,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/WifiNetworkSuggestionsManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java index 131f7de508..09f5969952 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java @@ -89,6 +89,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 +157,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 @@ -750,7 +752,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 +788,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 +4724,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 +4740,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 +4769,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 +4777,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/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..25cbb86de8 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,32 @@ 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()); + } + } 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..971722a82c 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 @@ -2922,6 +2922,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); |